MyBatis advanced interface proxy mode

Posted by richclever on Wed, 23 Feb 2022 12:16:51 +0100

Dao interface proxy

1. Introduction to agent development mode

The agent development mode of Mybatis is adopted to realize the development of DAO layer, which is the mainstream of entering the enterprise later.

Mapper interface development method only requires programmers to write mapper interface (equivalent to Dao interface). 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 that of the Dao interface above.

Mapper interface development needs to follow the following specifications:

1) Mapper. The namespace in the XML file is the same as the fully qualified name of the mapper interface

2) Mapper interface method name and mapper The id of each statement defined in XML is the same

3) Input parameter type of mapper interface method and mapper The parameterType of each sql defined in XML is of the same type

4) Mapper interface method output parameter type and mapper The resultType of each sql defined in XML is the same

Summary:

Interface development method: programmers only need to define interfaces to operate the database. How to create specific objects?

1. The programmer is responsible for defining the interface

2. When operating the database, mybatis framework generates proxy objects through dynamic proxy according to the interface, and is responsible for the crud operation of the database

2. Write StudentMapper interface

[the transfer of external chain pictures fails, and the source station may have anti-theft chain mechanism. It is recommended to save the pictures and upload them directly (img-3fzygzja-1645105791146) (/ users / Herma / downloads / 06. Mybatis / 02 mybatis advanced / Notes / img/1590937589503.png)]

3 test agent mode

 public Student selectById(Integer id) {
        Student stu = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1. Load core configuration file
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2. Get SqlSession factory object
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3. Obtain SqlSession object through factory object
            sqlSession = sqlSessionFactory.openSession(true);

            //4. Get the implementation class object of StudentMapper interface
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5. Call the method by implementing the class object to receive the result
            stu = mapper.selectById(id);

        } catch (Exception e) {

        } finally {
            //6. Release resources
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7. Return results
        return stu;
    }

4 source code analysis

  • Analyze how dynamic proxy objects are generated?

    Through the dynamic agent development mode, we only write an interface, not an implementation class. We finally get org. Org through the getMapper() method apache. ibatis. binding. Mapperproxy proxy object and then perform functions. MyBatis uses JDK's dynamic proxy technology to help us generate proxy implementation class objects. Thus, relevant persistence operations can be performed.

  • How is the analysis method performed?

    When the dynamic proxy implementation class object executes the method, it finally calls mappermethod Execute () method. In this method, the switch statement is used to judge the operations of adding, modifying, deleting and querying according to the operation type. The last step returns to the most original SqlSession mode of MyBatis to execute adding, deleting, modifying and querying.

5 knowledge summary

The interface proxy method allows us to write only the interface, and the implementation class object is generated by MyBatis.

Implementation rules:

  1. The namespace in the mapping configuration file must be the same as the full class name of the Dao layer interface.
  2. The id attribute of the addition, deletion, modification and query tag in the mapping configuration file must be the same as the method name of the Dao layer interface.
  3. The parameterType attribute of the addition, deletion, modification and query tag in the mapping configuration file must be the same as the parameters of the Dao layer interface method.
  4. The resultType attribute of the add / delete / modify query tag in the mapping configuration file must be the same as the return value of the Dao layer interface method. 
  5. Get the getMapper() method in the SqlSession function class of the dynamic proxy object.

dynamic sql statement

1 overview of dynamic sql statements

In the mapping file of Mybatis, our SQL is relatively simple. Sometimes when the business logic is complex, our SQL changes dynamically. At this time, our SQL can not meet the requirements in the previous study.

2 dynamic SQL < if >

We use different SQL statements to query according to different values of entity classes. For example, if the id is not empty, you can query according to the id. if the username is different, you need to add the user name as a condition. This situation is often encountered in our multi condition combined query.

As shown below:

<select id="findByCondition" parameterType="student" resultType="student">
    select * from student
    <where>
        <if test="id!=0">
            and id=#{id}
        </if>
        <if test="username!=null">
            and username=#{username}
        </if>
    </where>
</select>

When both query condition id and username exist, the sql statement printed on the console is as follows:

     ... ... ...
     //Obtain the implementation class of StudentMapper interface generated by MyBatis framework
    StudentMapper mapper = sqlSession.getMapper( StudentMapper.class);
    Student condition = new Student();
    condition.setId(1);
    condition.setUsername("lucy");
    Student student = mapper.findByCondition(condition);
    ... ... ...
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 252651381.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@f0f2775]
DEBUG [main] - ==>  Preparing: select * from student where sid=? and name=? and age=?; 
DEBUG [main] - ==> Parameters: 1(Integer), Zhang San(String), null
DEBUG [main] - <==      Total: 0
[]

When only id exists in the query condition, the sql statement printed on the console is as follows:

 ... ... ...
 //Get the implementation class of UserMapper interface generated by MyBatis framework
 StudentMapper mapper = sqlSession.getMapper( StudentMapper.class);
    Student condition = new Student();
    condition.setId(1);
    Student student = mapper.findByCondition(condition);
... ... ...

DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1397616978.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@534df152]
DEBUG [main] - ==>  Preparing: select * from student WHERE sid=? and name=? ; 
DEBUG [main] - ==> Parameters: 1(Integer), Zhang San(String)
DEBUG [main] - <==      Total: 1
[Student{sid=1, name='Zhang San', age=23}]

Summary syntax:

<where>: Condition label. If there are dynamic conditions, use this label instead where keyword.
<if>: Condition judgment label.
<if test=""Conditional judgment">
	Query condition splicing
</if>

3 < foreach > of dynamic SQL

Perform sql splicing operations circularly, for example: SELECT * FROM student WHERE id IN (1,2,5).

<select id="findByIds" parameterType="list" resultType="student">
   select * from student
   <where>
       <foreach collection="array" open="id in(" close=")" item="id" separator=",">
           #{id}
       </foreach>
   </where>
</select>

The test code fragment is as follows:

 ... ... ...
 //Get the implementation class of UserMapper interface generated by MyBatis framework
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int[] ids = new int[]{2,5};
List<Student> sList = mapper.findByIds(ids);
System.out.println(sList);
... ... ...

Summary syntax:

<foreach>: Loop through labels. Applicable to multiple parameters or relationships.
    <foreach collection=""open=""close=""item=""separator="">
		Get parameters
	</foreach>

attribute
Collection: parameter container type, (list collection, array array).
open: start SQL statement.
close: end the SQL statement.
item: parameter variable name.
Separator: separator.

4 SQL fragment extraction

Duplicate sql can be extracted from sql and referenced with include when used, so as to achieve the purpose of sql reuse

<!--extract sql Fragment simplification-->
<sql id="selectStudent" select * from student</sql>
<select id="findById" parameterType="int" resultType="student">
    <include refid="selectStudent"></include> where id=#{id}
</select>
<select id="findByIds" parameterType="list" resultType="student">
    <include refid="selectStudent"></include>
    <where>
        <foreach collection="array" open="id in(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </where>
</select>

Summary syntax:

We can extract some repetitive SQL statements to achieve the effect of reuse.

-  <sql>: extract SQL Statement label. 
-  <include>: introduce SQL Clip labels. 
   <sql id=""Fragment unique identifier">Extracted SQL sentence</sql> <include refid=""Fragment unique identifier"/>
 

5 knowledge summary

MyBatis mapping file configuration:

<select>: query

<insert>: insert

<update>: modify

<delete>: delete

<where>: where condition

<if>: if judge

<foreach>: loop

<sql>: sql Fragment extraction

III Paging plug-in

1 Introduction to paging plug-in

[the external link image transfer fails. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-3h2w4gyk-1645105791147) (/ users / Herma / downloads / 06. Mybatis / 02 mybatis advanced / Notes / img/1590937779260.png)]

  • Pagination can display many results in pagination.
  • If you are currently on the first page, there is no previous page. If the current is on the last page, there is no next page.
  • It is necessary to specify the current page and how many results are displayed on this page.
  • MyBatis paging plug-in summary
    1. Pagination is also a common technology in enterprise development. MyBatis currently used without paging function. If you want to realize paging function, you need to write LIMIT statement manually. However, different databases have different SQL statements to realize paging, so the cost of handwritten paging is high. At this time, we can use the paging plug-in to help us realize the paging function.
    2. PageHelper: third party paging assistant. Encapsulate the complex paging operation, so that the paging function becomes very simple.

2 use of paging plug-in

MyBatis can use third-party plug-ins to expand its functions. The paging assistant PageHelper encapsulates the complex operations of paging and obtains the relevant data of paging in a simple way

Development steps:

① Import jar package with PageHelper

② Configure the PageHelper plug-in in the mybatis core configuration file

<!-- Note: the plug-in configuration of paging assistant is in general mapper before -->
<plugin interceptor="com.github.pagehelper.PageHelper">
    <!-- Designated dialect -->
    <property name="dialect" value="mysql"/>
</plugin>

③ Test paging data acquisition

@Test
public void testPageHelper(){
    //Set paging parameters
    PageHelper.startPage(1,2);

    List<User> select = userMapper2.select(null);
    for(User user : select){
        System.out.println(user);
    }
}

3 parameter acquisition of paging plug-in

Get other parameters related to paging:

//Other paged data
PageInfo<User> pageInfo = new PageInfo<User>(select);
System.out.println("Total number of articles:"+pageInfo.getTotal());
System.out.println("Total pages:"+pageInfo.getPages());
System.out.println("Current page:"+pageInfo.getPageNum());
System.out.println("Display length per page:"+pageInfo.getPageSize());
System.out.println("First page:"+pageInfo.isIsFirstPage());
System.out.println("Last page:"+pageInfo.isIsLastPage());

4. Summary of paging plug-in knowledge

Pagination: many results can be displayed in pagination.

  • Paging plug-in jar package: pagehelper-5.1.10 jar jsqlparser-3.1. jar

  • : integration plug-in label.

  • Paging assistant related API

    ​ 1.PageHelper: paging assistant function class.

    1. startPage(): set paging parameters
    2. PageInfo: paging related parameter function class.
    3. getTotal(): get the total number of entries
    4. getPages(): get the total number of pages
    5. getPageNum(): get the current page
    6. getPageSize(): get the number of displays per page
    7. getPrePage(): get previous page
    8. getNextPage(): get the next page
    9. isIsFirstPage(): get whether it is the first page
    10. Isilastpage(): gets whether it is the last page

Multi table operation of MyBatis

1 Introduction to multi table model

What we learned before is based on single table operation, but in the actual development, with the deepening of business difficulty, we must need multi table operation.

  • Multi table model classification one-to-one: establish a foreign key on either party and associate the other party's primary key.
  • One to many: establish a foreign key in one of many parties and associate the primary key of one party.
  • Many to many: with the help of an intermediate table, at least two fields in the intermediate table are associated with the primary keys of the two tables respectively.

2. One to one operation of multi table model

  1. One to one model the first mock exam is identity card.

  2. code implementation

    • Step 1: sql statement preparation

      CREATE TABLE person(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	NAME VARCHAR(20),
      	age INT
      );
      INSERT INTO person VALUES (NULL,'Zhang San',23);
      INSERT INTO person VALUES (NULL,'Li Si',24);
      INSERT INTO person VALUES (NULL,'Wang Wu',25);
      
      CREATE TABLE card(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	number VARCHAR(30),
      	pid INT,
      	CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id)
      );
      INSERT INTO card VALUES (NULL,'12345',1);
      INSERT INTO card VALUES (NULL,'23456',2);
      INSERT INTO card VALUES (NULL,'34567',3);
      
    • Step 2: configuration 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="mybatis.demo.mapper.OneToOneMapper">
          <!--Configure the mapping relationship between fields and entity object attributes-->
          <resultMap id="oneToOne" type="card">
              <id column="cid" property="id" />
              <result column="number" property="number" />
              <!--
                  association: Configure the mapping relationship of the included objects
                  property: Variable name of the included object
                  javaType: The data type of the contained object
              -->
              <association property="p" javaType="person">
                  <id column="pid" property="id" />
                  <result column="name" property="name" />
                  <result column="age" property="age" />
              </association>
          </resultMap>
      
          <select id="selectAll" resultMap="oneToOne">
              SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
          </select>
      </mapper>
      
    • Step 3: test class

       @Test
          public void selectAll() throws Exception{
              //1. Load core configuration file
              InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
      
              //2. Get SqlSession factory object
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
      
              //3. Obtain SqlSession object through factory object
              SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
              //4. Get the implementation class object of the OneToOneMapper interface
              OneToOneMapper mapper = sqlSession.getMapper(OneToOneMapper.class);
      
              //5. Call the method of the implementation class and receive the result
              List<Card> list = mapper.selectAll();
      
              //6. Treatment results
              for (Card c : list) {
                  System.out.println(c);
              }
      
              //7. Release resources
              sqlSession.close();
              is.close();
          }
      

    3. One to one configuration summary:

    <resultMap>: Configure the mapping relationship labels of fields and object properties.
        id Attribute: unique identification
        type Attributes: entity object types
    <id>: Configure the primary key mapping relationship label.
    <result>: Configure non primary key mapping relationship labels.
        column Attribute: field name in table
        property Attribute: entity object variable name
    <association>: Configure the mapping relationship label of the included object.
        property Attribute: the variable name of the contained object
        javaType Property: the data type of the contained object
    

3 multi table model one to many operation

  1. One to many model: one to many model: class and students. A class can have multiple students.

  2. code implementation

    • Step 1: sql statement preparation

      CREATE TABLE classes(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	NAME VARCHAR(20)
      );
      INSERT INTO classes VALUES (NULL,'Dark horse class 1');
      INSERT INTO classes VALUES (NULL,'Dark horse class 2');
      
      
      CREATE TABLE student(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	NAME VARCHAR(30),
      	age INT,
      	cid INT,
      	CONSTRAINT cs_fk FOREIGN KEY (cid) REFERENCES classes(id)
      );
      INSERT INTO student VALUES (NULL,'Zhang San',23,1);
      INSERT INTO student VALUES (NULL,'Li Si',24,1);
      INSERT INTO student VALUES (NULL,'Wang Wu',25,2);
      INSERT INTO student VALUES (NULL,'Zhao Liu',26,2);
      
    • Step 2: configuration file

      <mapper namespace="mybatis.demo.mapper.OneToManyMapper">
          <resultMap id="oneToMany" type="classes">
              <id column="cid" property="id"/>
              <result column="cname" property="name"/>
      
              <!--
                  collection: Configure the mapping relationship of contained collection objects
                  property: Variable name of the included object
                  ofType: The actual data type of the contained object
              -->
              <collection property="students" ofType="student">
                  <id column="sid" property="id"/>
                  <result column="sname" property="name"/>
                  <result column="sage" property="age"/>
              </collection>
          </resultMap>
          <select id="selectAll" resultMap="oneToMany">
              SELECT c.id cid,c.name cname,s.id sid,s.name sname,s.age sage FROM classes c,student s WHERE c.id=s.cid
          </select>
      </mapper>
      
    • Step 3: test class

          @Test
          public void selectAll() throws Exception{
              //1. Load core configuration file
              InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
      
              //2. Get SqlSession factory object
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
      
              //3. Obtain SqlSession object through factory object
              SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
              //4. Get the implementation class object of the OneToManyMapper interface
              OneToManyMapper mapper = sqlSession.getMapper(OneToManyMapper.class);
      
              //5. Call the method of the implementation class and receive the result
              List<Classes> classes = mapper.selectAll();
      
              //6. Treatment results
              for (Classes cls : classes) {
                  System.out.println(cls.getId() + "," + cls.getName());
                  List<Student> students = cls.getStudents();
                  for (Student student : students) {
                      System.out.println("\t" + student);
                  }
              }
      
              //7. Release resources
              sqlSession.close();
              is.close();
          }
      

    3. One to many profile summary:

    <resultMap>: Configure the mapping relationship labels of fields and object properties.
        id Attribute: unique identification
        type Attributes: entity object types
    <id>: Configure the primary key mapping relationship label.
    <result>: Configure non primary key mapping relationship labels.
        column Attribute: field name in table
        property Attribute: entity object variable name
    <collection>: The collection of mapped objects that contains the mapping relationships.
        property Property: the variable name of the contained collection object
        ofType Attribute: the type of object data saved in the collection
    

4 multi table model many to many operation

  1. Many to many model: students and courses. A student can choose multiple courses and a course can also be selected by multiple students.

  2. code implementation

    • Step 1: sql statement preparation

      CREATE TABLE course(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	NAME VARCHAR(20)
      );
      INSERT INTO course VALUES (NULL,'language');
      INSERT INTO course VALUES (NULL,'mathematics');
      
      
      CREATE TABLE stu_cr(
      	id INT PRIMARY KEY AUTO_INCREMENT,
      	sid INT,
      	cid INT,
      	CONSTRAINT sc_fk1 FOREIGN KEY (sid) REFERENCES student(id),
      	CONSTRAINT sc_fk2 FOREIGN KEY (cid) REFERENCES course(id)
      );
      INSERT INTO stu_cr VALUES (NULL,1,1);
      INSERT INTO stu_cr VALUES (NULL,1,2);
      INSERT INTO stu_cr VALUES (NULL,2,1);
      INSERT INTO stu_cr VALUES (NULL,2,2);
      
    • Step 2: configuration 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="mybatis.demo.mapper.ManyToManyMapper">
          <resultMap id="manyToMany" type="student">
              <id column="sid" property="id"/>
              <result column="sname" property="name"/>
              <result column="sage" property="age"/>
      
              <collection property="courses" ofType="course">
                  <id column="cid" property="id"/>
                  <result column="cname" property="name"/>
              </collection>
          </resultMap>
          <select id="selectAll" resultMap="manyToMany">
              SELECT sc.sid,s.name sname,s.age sage,sc.cid,c.name cname FROM student s,course c,stu_cr sc WHERE sc.sid=s.id AND sc.cid=c.id
          </select>
      </mapper>
      
    • Step 3: test class

       @Test
          public void selectAll() throws Exception{
              //1. Load core configuration file
              InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
      
              //2. Get SqlSession factory object
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
      
              //3. Obtain SqlSession object through factory object
              SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
              //4. Get the implementation class object of ManyToManyMapper interface
              ManyToManyMapper mapper = sqlSession.getMapper(ManyToManyMapper.class);
      
              //5. Call the method of the implementation class and receive the result
              List<Student> students = mapper.selectAll();
      
              //6. Treatment results
              for (Student student : students) {
                  System.out.println(student.getId() + "," + student.getName() + "," + student.getAge());
                  List<Course> courses = student.getCourses();
                  for (Course cours : courses) {
                      System.out.println("\t" + cours);
                  }
              }
      
              //7. Release resources
              sqlSession.close();
              is.close();
          }
          
      

    3. Summary of many to many configuration files:

    <resultMap>: Configure the mapping relationship labels of fields and object properties.
    	id Attribute: unique identification
    	type Attributes: entity object types
     <id>: Configure the primary key mapping relationship label.
     <result>: Configure non primary key mapping relationship labels.
    	column Attribute: field name in table
    	property Attribute: entity object variable name
    <collection>: Configure the mapping relationship label of the included collection object.
    	property Property: the variable name of the contained collection object
    	ofType Attribute: the type of object data saved in the collection
    

5 multi table model operation summary

 <resultMap>: Configure the mapping relationship labels of fields and object properties.
    id Attribute: unique identification
    type Attributes: entity object types
<id>: Configure the primary key mapping relationship label.
<result>: Configure non primary key mapping relationship labels.
	column Attribute: field name in table
	property Attribute: entity object variable name
<association>: Configure the mapping relationship label of the included object.
	property Attribute: the variable name of the contained object
	javaType Property: the data type of the contained object
<collection>: Configure the mapping relationship label of the included collection object.
	property Property: the variable name of the contained collection object
	ofType Attribute: the type of object data saved in the collection

Topics: Java MySQL