[Mybatis from entry to actual combat tutorial] Chapter 2 Mybatis DAO Development

2. Mybatis DAO development

There are usually two methods for developing Dao using Mybatis, namely the original Dao development method and the Mapper interface development method.

2.1 Mybatis API

2.1.1 SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder is used to create SqlSessionFactoryBuilder. Once SqlSessionFactoryBuilder is created, SqlSessionFactoryBuilder is not needed. Because SqlSession is produced through SqlSessionFactory, SqlSessionFactoryBuilder can be used as a tool class. The best use range is the method scope, that is, the local variables in the method body.

2.1.2 SqlSessionFactory

    SqlSessionFactory is an interface that defines different overloading methods of openSession. The best use of SqlSessionFactory is during the entire application run. Once created, it can be reused. SqlSessionFactory is usually managed in a singleton mode.

    Note: openSession (true), true is to automatically commit the transaction, false is the opposite.

2.1.3 SqlSession

    SqlSession is a user-oriented (programmer) interface, which provides many methods for operating the database. Such as: selectOne (returns a single object), selectList (returns a single or multiple objects), insert, update, delete.

    Instances of SqlSession cannot be shared, it is not thread safe, each thread should have its own instance of SqlSession, so the best scope is request or method scope. Never put a reference to a SqlSession instance in a static or instance field of a class.

2.2 Mybatis tool class

    In order to simplify the development of MyBatis, MyBatis can be further packaged.

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();
    }
}

test:

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

2.3 The original DAO development method

    The original Dao development method requires programmers to write the Dao interface and the Dao implementation class, which is nothing more than calling the sql defined in the mapping file in the Dao implementation class.

2.3.1 Entity class

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 Interface

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 Implementation class

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 mapper file

<?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>

Load mapper file:

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

2.3.5 Testing

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 Original DAO development issues

    There are a large number of template methods in the dao interface implementation class method. Imagine whether these codes can be extracted to greatly reduce the workload of programmers.
    
    Calling the database operation method of sqlSession needs to specify the id of the statement, which is hard-coded here, which is not conducive to development and maintenance.
    
    The variable passed in when calling the SqlSession method, because the SqlSession method uses generics, even if the variable type is wrongly passed in, no error will be reported during the compilation stage, which is not conducive to programmer development.  
    Note: The original Dao development is basically similar to the Dao development we explained in the Web stage. They all have Dao interfaces and Dao implementation classes, but the Dao implementation classes in the Web stage use DBUtils to operate SQL; now the original Dao development of Mybatis separates SQL It's out, it's just written in the XML mapping file.

2.4 Mapper proxy method (key point)

    The Mapper proxy development method only requires programmers to write the Mapper interface (equivalent to the Dao interface), and the MyBatis framework creates the dynamic proxy object of the interface according to the interface definition. The method body of the proxy object is the same as the above Dao interface implementation class method.
    
    Programmers need to follow some development specifications when writing the Mapper interface, and MyBatis can automatically generate a proxy object of the Mapper interface implementation class.

2.4.1 Development Specifications

    1. The namespace in the Mapper.xml file is the same as the classpath of the mapper interface.

    2. The Mapper interface method name is the same as the id of each tag defined in Mapper.xml.

    3. The parameter type of the Mapper interface method is the same as the parameterType of each sql defined in mapper.xml.

    4. The return value type of the Mapper interface method is the same as the resultType of each sql defined in mapper.xml.

Note: The Mapper.xml mapping file should preferably be consistent with the name of the Mapper interface;

2.4.2 Entity class

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 Mapper interface

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);
}
  • Batch query: The return value of the method is List type, which means that the SqlSession object will call the selectList() method.

  • Single query: The return value of the method is a single entity object, which means that the SqlSession object will call the selectOne() method.

  • Additions, deletions and modifications:

    1. The return value of the method is void, which means that the return value of the insert, update, and delete methods in the SqlSession object will not be processed.

    2. The return value of the method is int type, indicating that the return value of the insert, update, and delete methods in the SqlSession object is returned directly.

    3. The return value of the method is boolean type, indicating whether the operation is successful or not according to the return value of the insert, update, and delete methods in the SqlSession object (the number of entries affecting the database). If the number of entries affecting the database is greater than 0, it means success, otherwise it means failure.

2.4.4 mapper file

<?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>

Load mapper file:

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

2.4.5 Testing

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 officially recommends using the mapper proxy method to develop the mapper interface. Programmers do not need to write a mapper interface implementation class. When using the mapper proxy method, the input parameters can use pojo packaging objects or map objects to ensure the versatility of dao.

Guess you like

Origin blog.csdn.net/ligonglanyuan/article/details/124272731