【MyBatis】| Aplicar MyBatis en WEB (usando patrón de arquitectura MVC)

Tabla de contenido 

Uno: Aplicar MyBatis en la WEB (usando el patrón de arquitectura MVC)

1. Preparación preliminar

2. Implementación del código central

3. Control de transacciones

4. El alcance de los tres objetos principales


Uno: Aplicar MyBatis en la WEB (usando el patrón de arquitectura MVC)

Objetivo:

① Domina cómo usar mybatis en aplicaciones web

②El alcance y el ciclo de vida de los tres objetos mybatis

③Principio y uso de ThreadLocal

④Consolidar el modelo de arquitectura MVC

⑤ Prepárese para aprender el mecanismo de proxy de interfaz de MyBatis

Función realizada: transferencia de cuenta bancaria

Tecnología utilizada: HTML + Servlet + MyBatis

El nombre de la aplicación WEB: banco

1. Preparación preliminar

(1) Preparación de la tabla de la base de datos

estructura de la mesa de diseño

 insertar datos

 (2) Use Mybatis para construir el entorno en la aplicación web, cree una aplicación web, agregue un servidor Tomcat local y luego configure los recursos

①Introducir dependencias en el archivo pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  
  <name>mybatis-004-web</name>
  <groupId>com.bjpowernode</groupId>
  <artifactId>mybatis-004-web</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!--mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.10</version>
    </dependency>
    <!--mysql依赖-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.23</version>
    </dependency>
    <!--logback依赖-->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.11</version>
    </dependency>
    <!--servlet依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>
  </dependencies>

</project>

②Introducción de algunos archivos de configuración

③ Escriba la página de transferencia front-end index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>银行账户转账</title>
</head>
<body>
    <form action="/bank/transfer" method="post">
        转出账号:<input type="text" name="fromActno"><br>
        转入账号:<input type="text" name="toActno"><br>
        转账余额:<input type="text" name="money"><br>
        <input type="submit" value="转账">
    </form>
</body>
</html>

④ Use el patrón de arquitectura MVC para crear un paquete

Explicación: dao es para conectarse a la base de datos, pojo es una clase ordinaria de java, servicio es para escribir negocios, utils es una clase de herramienta, web es un servlet

(1) Según el análisis de la arquitectura de tres niveles: la web es la capa de presentación, el servicio es la capa comercial y dao es la capa de persistencia.
(2) Análisis según el patrón de arquitectura MVC: pojo, dao y service pertenecen a M, all .jsp pertenece a V y web pertenece a C. (3) La relación entre el patrón de arquitectura MVC y las tres capas: M incluye la capa comercial y la capa de persistencia, y V y C pertenecen a la capa de presentación.

clase pojo, encapsulando información de cuenta

package com.bjpowernode.bank.pojo;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.pojo
 * @Project:mybatis
 * @name:Account
 * @Date:2023/1/1 17:53
 */
public class Account {
    private Long id;
    private String actno;
    private Double balance;
    // 构造方法
    public Account() {
    }
    public Account(Long id, String actno, Double balance) {
        this.id = id;
        this.actno = actno;
        this.balance = balance;
    }
    // setter and getter
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
    // 重写toString
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", actno='" + actno + '\'' +
                ", balance=" + balance +
                '}';
    }
}

 Clase de herramienta, la clase que se conecta a la base de datos.

package com.bjpowernode.bank.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

public class SqlSessionUtils {
    public SqlSessionUtils() {
    }
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession openSession(){
        return sqlSessionFactory.openSession();
    }

}

2. Implementación del código central

Detalles: Hay una configuración en el archivo web.xml, metadata-complete="true"> indica que solo se admite la forma de archivo de configuración, y no se admite el desarrollo en forma de anotación; igual a falso indica que ambos son ¡soportado!

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="false">
</web-app>

El formulario de marco principal y las páginas de visualización requeridas

① Paquete Bao: la operación de conexión a la base de datos, programación orientada a la interfaz, interfaz y clase de implementación correspondiente

②paquete de excepción: lanzar excepciones, una es la excepción lanzada por saldo insuficiente y la otra es la excepción que ocurre durante el proceso de transferencia

③paquete pojo: encapsula datos, clase java ordinaria

④paquete de servicio: escribir código de lógica empresarial, programación orientada a interfaz, interfaz y clase de implementación correspondiente

⑤paquete de utilidades: paquete de código para conectarse a la base de datos

⑥ paquete web: escribir servlet, es el comandante, para programar

①index.html es la página para enviar datos en la parte delantera, donde ingresa la información de la transferencia

②money-not-enough.html es la página donde el saldo de la transferencia es insuficiente y se muestran los resultados

③success.html es la página donde la transferencia es exitosa

④transfer-error.html es la página donde hay un problema con la transferencia

①AccountMapper.xml: declaración sql especialmente escrita

②jdbc.properties: información de configuración requerida para conectarse a la base de datos

③logback.xml: información de configuración de registro

④mybatis-config.xml: archivo de configuración principal para importar registros, leer archivos de configuración de bases de datos de conexión, conectar bases de datos y asociar archivos de configuración de AccountMapper.xml y otra información

(1) Escriba un servlet, escriba AccountServlet de acuerdo con la solicitud enviada por el front-end, este Servlet es equivalente al Comandante C y envía dos secretarios M y V

package com.bjpowernode.bank.web;

import com.bjpowernode.bank.exception.MoenyNotEnoughException;
import com.bjpowernode.bank.exception.TransferException;
import com.bjpowernode.bank.service.AccountService;
import com.bjpowernode.bank.service.impl.AccountServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.web
 * @Project:mybatis
 * @name:AccountServlet
 * @Date:2023/1/1 19:23
 */
@WebServlet("/transfer")
public class AccountServlet extends HttpServlet {
    // 编写业务逻辑的类,声明为成员变量,其它方法也能调用
    private AccountService accountService = new AccountServiceImpl();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取表单数据
        String fromActno = request.getParameter("fromActno");
        String toActno = request.getParameter("toActno");
        double money = Double.parseDouble(request.getParameter("money"));
        // AccountService accountService = new AccountServiceImpl(); // 面向接口编程
        try {
            // 调用service的转账方法完成转账(调度业务层-M)
            accountService.transfer(fromActno,toActno,money);
            // 调用View完成展示结果
            // 转账成功,跳转页面
            response.sendRedirect(request.getContextPath()+"/success.html");
        } catch (MoenyNotEnoughException e) {
            // 钱不够,跳转页面
            response.sendRedirect(request.getContextPath()+"/money-not-enough.html");
        } catch (TransferException e) {
            // 转账失败,跳转页面
            response.sendRedirect(request.getContextPath()+"/transfer-error.html");
        }

    }
}

 Saldo insuficiente página money-not-enough.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>余额不足</title>
</head>
<body>
    <h1>余额不足</h1>
</body>
</html>

 Transferencia exitosa de la página Success.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>转账成功</title>
</head>
<body>
    <h1>转账成功</h1>
</body>
</html>

Transferencia fallida página transfer-error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>转账失败</title>
</head>
<body>
    <h1>转账失败</h1>
</body>
</html>

(2) La lógica anterior encontró que Commander Servlet llama al código de lógica empresarial (M) para completar la operación de transferencia, por lo que es necesario escribir la interfaz AccountService y la clase de implementación AccountServiceImpl

Interfaz de servicio de cuenta

package com.bjpowernode.bank.service;

import com.bjpowernode.bank.exception.MoenyNotEnoughException;
import com.bjpowernode.bank.exception.TransferException;

public interface AccountService {
    /**
     * 账户转账
     * @param fromActno 转账账号
     * @param toActno 转入账号
     * @param money 转账金额
     */
    void transfer(String fromActno,String toActno,double money) throws MoenyNotEnoughException, TransferException;
}

Clase de implementación AccountServiceImpl

package com.bjpowernode.bank.service.impl;

import com.bjpowernode.bank.bao.AccountDao;
import com.bjpowernode.bank.bao.impl.AccountDaoImpl;
import com.bjpowernode.bank.exception.MoenyNotEnoughException;
import com.bjpowernode.bank.exception.TransferException;
import com.bjpowernode.bank.pojo.Account;
import com.bjpowernode.bank.service.AccountService;

/** 编写业务逻辑代码
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.service.impl
 * @Project:mybatis
 * @name:AccountServiceImpl
 * @Date:2023/1/1 19:40
 */
public class AccountServiceImpl implements AccountService {---
   // 修改数据的类
   private AccountDao accountDao = new AccountDaoImpl();
    @Override
    public void transfer(String fromActno, String toActno, double money) throws MoenyNotEnoughException, TransferException {
        // 判断转出账户的余额是否充足
        Account fromAct = accountDao.selectByActno(fromActno);
        if (fromAct.getBalance() < money) {
            // 如果转出账户余额不足,抛出异常提示用户
            throw new MoenyNotEnoughException("对不起,余额不足");
        }
        // 如果余额充足,更新转出和转入账户余额
        Account toAct = accountDao.selectByActno(toActno);
        // 修改内存中的余额
        fromAct.setBalance(fromAct.getBalance()-money);
        toAct.setBalance(toAct.getBalance()+money);
        // 修改数据库当中余额
        int count = accountDao.updateByActno(fromAct);
        count += accountDao.updateByActno(toAct);
        if (count != 2) {
            // 转账异常
            throw new TransferException("转账异常");
        }
    }
}

 Saldo insuficiente lanza una excepción MoenyNotEnoughException

package com.bjpowernode.bank.exception;

public class MoenyNotEnoughException extends Exception{
    // 两个构造方法
    public MoenyNotEnoughException() {
    }
    public MoenyNotEnoughException(String message) {
        super(message);
    }
}

 Se lanza una excepción TransferException cuando falla la transferencia

package com.bjpowernode.bank.exception;

public class TransferException extends Exception{
    public TransferException() {
    }
    public TransferException(String message) {
        super(message);
    }
}

(3) Al escribir la lógica de negocios, se encuentra que se requieren operaciones de base de datos, lo que requiere una clase dedicada a conectarse a la base de datos y procesar operaciones de datos; programación orientada a la interfaz, escritura de interfaz AccountDao y clase AccountDaoImpl

Interfaz de AccountDao

package com.bjpowernode.bank.bao;

import com.bjpowernode.bank.pojo.Account;

/**
 * 负责对表中数据进行CRUD
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.bao
 * @Project:mybatis
 * @name:AccountDao
 * @Date:2023/1/1 19:48
 */
public interface AccountDao {
    /**
     * 根据账号查询账户信息
     * @param actno
     * @return 返回的是账户信息
     */
   Account selectByActno(String actno);

    /**
     * 更新账户信息
     * @param act
     * @return 1表示更新成功
     */
   int updateByActno(Account act);
}

Clase AccountDaoImpl

package com.bjpowernode.bank.bao.impl;

import com.bjpowernode.bank.bao.AccountDao;
import com.bjpowernode.bank.pojo.Account;
import com.bjpowernode.bank.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.bao.impl
 * @Project:mybatis
 * @name:AccountDaoImpl
 * @Date:2023/1/1 19:57
 */
public class AccountDaoImpl implements AccountDao {
    @Override
    public Account selectByActno(String actno) {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        Account account = (Account) sqlSession.selectOne("account.selectByActno", actno);
        sqlSession.close();
        return account;
    }

    @Override
    public int updateByActno(Account act) {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        int count = sqlSession.update("account.updateByActno", act);
        sqlSession.commit();
        sqlSession.close();
        return count;
    }
}

AccountMapper.xml para escribir declaraciones sql

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="account">
    <select id="selectByActno" resultType="com.bjpowernode.bank.pojo.Account">
        select * from t_act where actno=#{actno}
    </select>

    <update id="updateByActno">
        update t_act set balance = #{balance} where actno = #{actno};
    </update>
</mapper>

El archivo de configuración jdbc.properties para conectarse a la base de datos

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123

Archivo de configuración principal mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--读取配置文件-->
    <properties resource="jdbc.properties" />
    <!--引入日志-->
    <settings>
        <setting name="logImpl" value="SLF4J"/>
    </settings>
    <environments default="mybatisDB">
        <!--连接的是mybatis数据库-->
        <environment id="mybatisDB">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--关联AccountMapper.xml配置文件-->
        <mapper resource="AccountMapper.xml"/>
    </mappers>

</configuration>

3. Control de transacciones

Nota: El código actual no tiene control de transacciones. Si se agrega una excepción de puntero nulo después de la primera declaración de actualización y antes de la segunda declaración de actualización, se perderá dinero, lo que requiere control de transacciones.

(1) De hecho, el control de la transacción no debe colocarse en la capa Dao, y debe enviarse una vez si no se puede actualizar; debe enviarse a la capa Servicio y toda la lógica se completa antes de enviar.

(2) No es aceptable que agreguemos directamente códigos para controlar transacciones en la capa de Servicio, porque el objeto sqlSession obtenido aquí y el objeto sqlSession obtenido al ejecutar la declaración de actualización no son el mismo objeto sqlSession.

package com.bjpowernode.bank.service.impl;

import com.bjpowernode.bank.bao.AccountDao;
import com.bjpowernode.bank.bao.impl.AccountDaoImpl;
import com.bjpowernode.bank.exception.MoenyNotEnoughException;
import com.bjpowernode.bank.exception.TransferException;
import com.bjpowernode.bank.pojo.Account;
import com.bjpowernode.bank.service.AccountService;
import com.bjpowernode.bank.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.service.impl
 * @Project:mybatis
 * @name:AccountServiceImpl
 * @Date:2023/1/1 19:40
 */
public class AccountServiceImpl implements AccountService {
   private AccountDao accountDao = new AccountDaoImpl();
    @Override
    public void transfer(String fromActno, String toActno, double money) throws MoenyNotEnoughException, TransferException {

        // 添加事务控制代码
        SqlSession sqlSession = SqlSessionUtils.openSession();

        // 判断转出账户的余额是否充足
        Account fromAct = accountDao.selectByActno(fromActno);
        if (fromAct.getBalance() < money) {
            // 如果转出账户余额不足,抛出异常提示用户
            throw new MoenyNotEnoughException("对不起,余额不足");
        }
        // 如果余额充足,更新转出和转入账户余额
        Account toAct = accountDao.selectByActno(toActno);
        // 修改内存中的余额
        fromAct.setBalance(fromAct.getBalance()-money);
        toAct.setBalance(toAct.getBalance()+money);
        // 修改数据库当中余额
        int count = accountDao.updateByActno(fromAct);
        count += accountDao.updateByActno(toAct);
        if (count != 2) {
            // 转账异常
            throw new TransferException("转账异常");
        }

        // 提交事务
        sqlSession.commit();
        sqlSession.close();
    }
}

(3) Use el control ThreadLocal, que es esencialmente una colección de mapas. Su clave almacena el objeto de subproceso y su valor almacena el objeto sqlSession; almacenamos el objeto sqlSession en esta colección de mapas, y para el mismo subproceso, se eliminará más tarde Todos son el mismo objeto sqlSession.

Introduzca ThreadLocal en la clase de herramienta SqlSessionUtils

package com.bjpowernode.bank.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.mybatis.utils
 * @Project:mybatis
 * @name:SqlSessionUtils
 * @Date:2022/12/29 14:11
 */

public class SqlSessionUtils {
    public SqlSessionUtils() {
    }
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 全局的,服务器级别的,一个服务器当中定义一个
    private static ThreadLocal<SqlSession> local = new ThreadLocal<>();

    // 获取会话对象
    public static SqlSession openSession(){
        // 先从ThreadLocal当中获取
        SqlSession sqlSession = local.get();
        // 第一次获取肯定是空的
        if (sqlSession == null) {
            // 是空的,在去工厂中获取
            sqlSession = sqlSessionFactory.openSession();
            // 将sqlSession对象绑定到当前线程上
            local.set(sqlSession);
        }
        return sqlSession;
    }

    // 关闭sqlSession对象
    public static void close(SqlSession sqlSession){
        if (sqlSession != null) {
            sqlSession.close();
            // 移除sqlSession对象与当前线程的绑定关系
            // 因为Tomcat服务器是支持多线程的,被当前用户用到的t1线程,有可能继续被其他用户使用
            local.remove();
        }
    }
}

Modifique la clase AccountDaoImpl de la base de datos, no debe confirmar y cerrar en ella

package com.bjpowernode.bank.bao.impl;

import com.bjpowernode.bank.bao.AccountDao;
import com.bjpowernode.bank.pojo.Account;
import com.bjpowernode.bank.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.bao.impl
 * @Project:mybatis
 * @name:AccountDaoImpl
 * @Date:2023/1/1 19:57
 */
public class AccountDaoImpl implements AccountDao {
    @Override
    public Account selectByActno(String actno) {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        Account account = (Account) sqlSession.selectOne("account.selectByActno", actno);
        return account;
    }

    @Override
    public int updateByActno(Account act) {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        int count = sqlSession.update("account.updateByActno", act);
        return count;
    }
}

Agregar control de transacciones en la clase AccountServiceImpl de la capa de servicio

package com.bjpowernode.bank.service.impl;

import com.bjpowernode.bank.bao.AccountDao;
import com.bjpowernode.bank.bao.impl.AccountDaoImpl;
import com.bjpowernode.bank.exception.MoenyNotEnoughException;
import com.bjpowernode.bank.exception.TransferException;
import com.bjpowernode.bank.pojo.Account;
import com.bjpowernode.bank.service.AccountService;
import com.bjpowernode.bank.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.service.impl
 * @Project:mybatis
 * @name:AccountServiceImpl
 * @Date:2023/1/1 19:40
 */
public class AccountServiceImpl implements AccountService {
   private AccountDao accountDao = new AccountDaoImpl();
    @Override
    public void transfer(String fromActno, String toActno, double money) throws MoenyNotEnoughException, TransferException {

        // 添加事务控制代码
        SqlSession sqlSession = SqlSessionUtils.openSession();

        // 判断转出账户的余额是否充足
        Account fromAct = accountDao.selectByActno(fromActno);
        if (fromAct.getBalance() < money) {
            // 如果转出账户余额不足,抛出异常提示用户
            throw new MoenyNotEnoughException("对不起,余额不足");
        }
        // 如果余额充足,更新转出和转入账户余额
        Account toAct = accountDao.selectByActno(toActno);
        // 修改内存中的余额
        fromAct.setBalance(fromAct.getBalance()-money);
        toAct.setBalance(toAct.getBalance()+money);
        // 修改数据库当中余额
        int count = accountDao.updateByActno(fromAct);
        count += accountDao.updateByActno(toAct);
        if (count != 2) {
            // 转账异常
            throw new TransferException("转账异常");
        }

        // 提交事务
        sqlSession.commit();
        // 调用方法关闭
        SqlSessionUtils.close(sqlSession);
    }
}

4. El alcance de los tres objetos principales

(1) SqlSessionFactoryBuilder: esta clase se puede instanciar, usar y descartar, una vez que se crea SqlSessionFactory, ya no es necesaria . Entonces, el mejor alcance para una instancia de SqlSessionFactoryBuilder es el alcance del método (es decir, las variables del método local).

(2) SqlSessionFactory: una vez que se crea SqlSessionFactory , siempre debe existir durante la ejecución de la aplicación . No hay razón para descartarlo o recrear otra instancia, a menos que se conecte otra base de datos y una base de datos corresponda a un objeto SqlSessionFactory . La práctica recomendada de usar SqlSessionFactory es no crear varias veces durante la ejecución de la aplicación, por lo que se coloca en un bloque de código estático cuando se encapsula. Entonces, el mejor alcance para SqlSessionFactory es el alcance de la aplicación

(3 ) SqlSession: cada subproceso debe tener su propia instancia de SqlSession. Las instancias de SqlSession no son seguras para subprocesos y, por lo tanto, no se pueden compartir, por lo que su mejor ámbito es el ámbito de solicitud o método (una solicitud) . Un hilo corresponde a un objeto SqlSession .

Suplemento: encontramos que cada código de método de la clase de implementación de Dao AccountDaoImp ​​​​tiene solo dos líneas y una línea se repite; entonces, ¿no se puede escribir esta clase y la clase de implementación de esta interfaz se puede generar en la memoria? Con la tecnología javassist, solo puede proporcionar la interfaz y generar automáticamente la clase de implementación en la memoria de acuerdo con esta interfaz. ¡Esta es la tecnología que aprenderá a continuación!

package com.bjpowernode.bank.bao.impl;

import com.bjpowernode.bank.bao.AccountDao;
import com.bjpowernode.bank.pojo.Account;
import com.bjpowernode.bank.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author:朗朗乾坤
 * @Package:com.bjpowernode.bank.bao.impl
 * @Project:mybatis
 * @name:AccountDaoImpl
 * @Date:2023/1/1 19:57
 */
public class AccountDaoImpl implements AccountDao {
    @Override
    public Account selectByActno(String actno) {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        Account account = (Account) sqlSession.selectOne("account.selectByActno", actno);
        return account;
    }

    @Override
    public int updateByActno(Account act) {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        int count = sqlSession.update("account.updateByActno", act);
        return count;
    }
}

Supongo que te gusta

Origin blog.csdn.net/m0_61933976/article/details/128511127
Recomendado
Clasificación