[Mybatis desde la entrada hasta el tutorial de combate real] Capítulo 2 Desarrollo de Mybatis DAO

2. Desarrollo de Mybatis DAO

Por lo general, existen dos métodos para desarrollar Dao utilizando Mybatis, a saber, el método de desarrollo Dao original y el método de desarrollo de la interfaz Mapper.

2.1 API de Mybatis

2.1.1 SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder se usa para crear SqlSessionFactoryBuilder. Una vez que se crea SqlSessionFactoryBuilder, SqlSessionFactoryBuilder no es necesario. Debido a que SqlSession se produce a través de SqlSessionFactory, SqlSessionFactoryBuilder se puede usar como una clase de herramienta. El mejor rango de uso es el alcance del método, es decir, las variables locales en el cuerpo del método.

2.1.2 SqlSessionFactory

    SqlSessionFactory es una interfaz que define diferentes métodos de sobrecarga de openSession. El mejor uso de SqlSessionFactory es durante toda la ejecución de la aplicación. Una vez creada, se puede reutilizar. SqlSessionFactory generalmente se administra en modo singleton.

    Nota: openSession (verdadero), verdadero es para confirmar automáticamente la transacción, falso es lo contrario.

2.1.3 Sesión Sql

    SqlSession es una interfaz orientada al usuario (programador), que proporciona muchos métodos para operar la base de datos. Tales como: selectOne (devuelve un solo objeto), selectList (devuelve uno o varios objetos), insert, update, delete.

    Las instancias de SqlSession no se pueden compartir, no es seguro para subprocesos, cada subproceso debe tener su propia instancia de SqlSession, por lo que el mejor alcance es el alcance de solicitud o método. Nunca ponga una referencia a una instancia de SqlSession en un campo estático o de instancia de una clase.

2.2 Clase de herramienta Mybatis

    Para simplificar el desarrollo de MyBatis, MyBatis se puede empaquetar aún más.

package com.newcapec.util;

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;
import java.io.InputStream;

/**
 * Mybatis工具类
 */
public class MybatisUtil {
    /**
     * 不让用户在外界创建工具类对象
     */
    private MybatisUtil() {
    }

    /**
     * 初始化SqlSessionFactory对象
     */
    private static SqlSessionFactory factory;

    static {
        try {
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取SqlSession对象的方法
     */
    public static SqlSession getSession() {
        return factory.openSession();
    }
}

prueba:

public class MybatisUtilTest {
    @Test
    public void test() {
        SqlSession sqlSession = MybatisUtil.getSession();
        System.out.println(sqlSession);
        sqlSession.close();
    }
}

2.3 El método original de desarrollo de DAO

    El método de desarrollo original de Dao requiere que los programadores escriban la interfaz de Dao y la clase de implementación de Dao, que no es más que llamar al sql definido en el archivo de mapeo en la clase de implementación de Dao.

2.3.1 Clase de entidad

package com.newcapec.entity;

/**
 * Dept实体类
 */
public class Dept {

    private Integer deptno;
    private String dname;
    private String loc;

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }
}

2.3.2 Interfaz

package com.newcapec.dao;

import com.newcapec.entity.Dept;

import java.util.List;

public interface DeptDao {
    List<Dept> select();

    Dept selectById(Integer deptno);

    int insert(Dept dept);

    int update(Dept dept);

    int delete(Integer deptno);
}

2.3.3 Clase de implementación

package com.newcapec.dao.impl;

import com.newcapec.dao.DeptDao;
import com.newcapec.entity.Dept;
import com.newcapec.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

/**
 * DeptDao实现类
 */
public class DeptDaoImpl implements DeptDao {
    @Override
    public List<Dept> select() {
        SqlSession sqlSession = MybatisUtil.getSession();
        List<Dept> list = sqlSession.selectList("dept.select");
        sqlSession.close();
        return list;
    }

    @Override
    public Dept selectById(Integer deptno) {
        SqlSession sqlSession = MybatisUtil.getSession();
        Dept dept = sqlSession.selectOne("dept.selectById", deptno);
        sqlSession.close();
        return dept;
    }

    @Override
    public int insert(Dept dept) {
        SqlSession sqlSession = MybatisUtil.getSession();
        int result = sqlSession.insert("dept.insert", dept);
        sqlSession.commit();
        sqlSession.close();
        return result;
    }

    @Override
    public int update(Dept dept) {
        SqlSession sqlSession = MybatisUtil.getSession();
        int result = sqlSession.update("dept.update", dept);
        sqlSession.commit();
        sqlSession.close();
        return result;
    }

    @Override
    public int delete(Integer deptno) {
        SqlSession sqlSession = MybatisUtil.getSession();
        int result = sqlSession.delete("dept.delete", deptno);
        sqlSession.commit();
        sqlSession.close();
        return result;
    }
}

2.3.4 archivo de mapeo

<?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="dept">

    <select id="select" resultType="com.newcapec.entity.Dept">
        select deptno,dname,loc from dept
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Dept">
        select deptno,dname,loc from dept where deptno=#{deptno}
    </select>

    <insert id="insert" parameterType="com.newcapec.entity.Dept">
        insert into dept(dname,loc) values(#{dname},#{loc})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.Dept">
        update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        delete from dept where deptno=#{deptno}
    </delete>
</mapper>

Cargar archivo de mapeador:

<!-- 加载映射文件的位置 -->
<mappers>
    <mapper resource="mapper/Dept.xml"/>
</mappers>

2.3.5 Pruebas

package com.newcapec;

import com.newcapec.dao.DeptDao;
import com.newcapec.dao.impl.DeptDaoImpl;
import com.newcapec.entity.Dept;
import org.junit.Test;

import java.util.List;

public class DaoTest {

    private DeptDao deptDao = new DeptDaoImpl();

    @Test
    public void testSelect() {
        List<Dept> list = deptDao.select();
        for (Dept dept : list) {
            System.out.println(dept);
        }
    }

    @Test
    public void testSelectById() {
        Dept dept = deptDao.selectById(20);
        System.out.println(dept);
    }

    @Test
    public void testInsert() {
        Dept dept = new Dept();
        dept.setDname("企划部");
        dept.setLoc("深圳");
        int result = deptDao.insert(dept);
        System.out.println("影响数据库的条数:" + result);
    }

    @Test
    public void testUpdate() {
        Dept dept = new Dept();
        dept.setDeptno(41);
        dept.setDname("生产部");
        dept.setLoc("杭州");
        int result = deptDao.update(dept);
        System.out.println("影响数据库的条数:" + result);
    }

    @Test
    public void testDelete() {
        int result = deptDao.delete(41);
        System.out.println("影响数据库的条数:" + result);
    }
}

2.3.6 Problemas de desarrollo de DAO originales

    Hay una gran cantidad de métodos de plantilla en el método de clase de implementación de la interfaz dao.Imagínese si estos códigos se pueden extraer para reducir en gran medida la carga de trabajo de los programadores.
    
    Llamar al método de operación de la base de datos de sqlSession necesita especificar la identificación de la declaración, que está codificada aquí, lo que no es propicio para el desarrollo y el mantenimiento.
    
    La variable se pasó al llamar al método SqlSession, ya que el método SqlSession usa genéricos, incluso si el tipo de variable se pasa incorrectamente, no se informará ningún error durante la etapa de compilación, lo que no es propicio para el desarrollo del programador.  
    Nota: El desarrollo Dao original es básicamente similar al desarrollo Dao que explicamos en la etapa Web. Todos tienen interfaces Dao y clases de implementación Dao, pero las clases de implementación Dao en la etapa Web usan DBUtils para operar SQL; ahora el desarrollo Dao original de Mybatis separa SQL Está fuera, solo está escrito en el archivo de mapeo XML.

2.4 Método de proxy Mapper (punto clave)

    El método de desarrollo del proxy Mapper solo requiere que los programadores escriban la interfaz Mapper (equivalente a la interfaz Dao), y el marco MyBatis crea el objeto proxy dinámico de la interfaz de acuerdo con la definición de la interfaz. El cuerpo del método del objeto proxy es el mismo que el método de clase de implementación de la interfaz Dao anterior.
    
    Los programadores deben seguir algunas especificaciones de desarrollo al escribir la interfaz Mapper, y MyBatis puede generar automáticamente un objeto proxy de la clase de implementación de la interfaz Mapper.

2.4.1 Especificaciones de desarrollo

    1. El espacio de nombres en el archivo Mapper.xml es el mismo que el classpath de la interfaz del mapeador.

    2. El nombre del método de interfaz de Mapper es el mismo que el id de cada etiqueta definida en Mapper.xml.

    3. El tipo de parámetro del método de interfaz Mapper es el mismo que el tipo de parámetro de cada sql definido en mapper.xml.

    4. El tipo de valor de retorno del método de interfaz Mapper es el mismo que el tipo de resultado de cada sql definido en mapper.xml.

Nota: El archivo de mapeo Mapper.xml debe ser preferiblemente consistente con el nombre de la interfaz Mapper;

2.4.2 Clase de entidad

package com.newcapec.entity;

import java.util.Date;

/**
 * Emp实体类
 */
public class Emp {

    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private Date hiredate;
    private Double sal;
    private Double comm;
    private Integer deptno;

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Integer getMgr() {
        return mgr;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    public Double getComm() {
        return comm;
    }

    public void setComm(Double comm) {
        this.comm = comm;
    }

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hiredate=" + hiredate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                '}';
    }
}

2.4.3 Interfaz del mapeador

package com.newcapec.mapper;

import com.newcapec.entity.Emp;

import java.util.List;

/*
 * Mapper接口相当于我们之前写的Dao接口,只是在Mybatis里面我们习惯这么写而已。
 */
public interface EmpMapper {
    List<Emp> select();

    Emp selectById(Integer empno);

    void insert(Emp emp);

    int update(Emp emp);

    boolean delete(Integer empno);
}
  • Consulta por lotes: el valor de retorno del método es de tipo Lista, lo que significa que el objeto SqlSession llamará al método selectList().

  • Consulta única: el valor de retorno del método es un objeto de entidad única, lo que significa que el objeto SqlSession llamará al método selectOne().

  • Adiciones, supresiones y modificaciones:

    1. El valor de retorno del método es nulo, lo que significa que no se procesará el valor de retorno de los métodos de inserción, actualización y eliminación en el objeto SqlSession.

    2. El valor de retorno del método es de tipo int, lo que indica que el valor de retorno de los métodos de inserción, actualización y eliminación en el objeto SqlSession se devuelve directamente.

    3. El valor de retorno del método es de tipo booleano, indicando si la operación es exitosa o no según el valor de retorno de los métodos de inserción, actualización y eliminación en el objeto SqlSession (el número de entradas que afectan a la base de datos). las entradas que afectan a la base de datos es mayor que 0, significa éxito, de lo contrario significa falla.

2.4.4 archivo de mapeo

<?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">
<!--namespace:与Mapper接口的全限定名保持一致-->
<mapper namespace="com.newcapec.mapper.EmpMapper">

    <!--
        statementId与Mapper接口的方法名称保持一致
        parameterType的类型必须与方法的参数类型保持一致
        resultType的类型必须与方法的返回值类型保持一致
    -->
    <select id="select" resultType="com.newcapec.entity.Emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Emp">
        select empno,ename,job,hiredate,mgr,sal,comm,deptno from emp where empno=#{empno}
    </select>

    <insert id="insert" parameterType="com.newcapec.entity.Emp">
        insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
        values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.Emp">
        update emp set
        ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno}
        where empno=#{empno}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        delete from emp where empno=#{empno}
    </delete>
</mapper>

Cargar archivo de mapeador:

<!-- 加载映射文件的位置 -->
<mappers>
    <mapper resource="mapper/EmpMapper.xml"/>
</mappers>

2.4.5 Pruebas

package com.newcapec;

import com.newcapec.entity.Emp;
import com.newcapec.mapper.EmpMapper;
import com.newcapec.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Date;
import java.util.List;

public class MapperTest {

    private SqlSession sqlSession;
    private EmpMapper empMapper;

    @Before
    public void before() {
        sqlSession = MybatisUtil.getSession();
        //获取Mapper接口的代理对象
        empMapper = sqlSession.getMapper(EmpMapper.class);
    }

    @After
    public void after() {
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void test() {
        System.out.println(sqlSession);
        System.out.println(empMapper);
    }

    @Test
    public void testSelect() {
        List<Emp> list = empMapper.select();
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    @Test
    public void testSelectById() {
        Emp emp = empMapper.selectById(7938);
        System.out.println(emp);
    }

    @Test
    public void testInsert() {
        Emp emp = new Emp();
        emp.setEname("小明");
        emp.setJob("职员");
        emp.setSal(4500.0);
        emp.setComm(1000.0);
        emp.setMgr(1);
        emp.setHiredate(new Date());

        empMapper.insert(emp);
    }

    @Test
    public void testUpdate() {
        Emp emp = new Emp();
        emp.setEmpno(7940);
        emp.setEname("小李");
        emp.setJob("秘书");
        emp.setSal(5300.0);
        emp.setComm(1300.0);
        emp.setMgr(1);
        emp.setHiredate(new Date());

        int result = empMapper.update(emp);
        System.out.println("方法的返回值:" + result);
    }

    @Test
    public void testDelete() {
        boolean result = empMapper.delete(7940);
        System.out.println("方法的返回值:" + result);
    }
}

    Mybatis recomienda oficialmente usar el método mapper proxy para desarrollar la interfaz mapper. Los programadores no necesitan escribir una clase de implementación de la interfaz mapper. Cuando se usa el método mapper proxy, los parámetros de entrada pueden usar objetos de empaquetado pojo u objetos map para garantizar la versatilidad de dao. .

Supongo que te gusta

Origin blog.csdn.net/ligonglanyuan/article/details/124272731
Recomendado
Clasificación