The use and source code analysis of mybatis

Keywords: Session xml Apache Mybatis

Source code of the project: https://github.com/zhuquanwen/mybatis-learn/releases/tag/with-annotation
Construction process:
Based on the previous article, some processes are not described in detail. The previous source code has been attached. Please refer to the previous article: https://blog.csdn.net/u011943534/article/details/104717560
Project structure:

1. Log4j was introduced before but not configured. This time, configure it through InitLog4J class

package com.learn.zqw.log;

import org.apache.log4j.PropertyConfigurator;

/**
 * //TODO
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/8 10:35
 * @since jdk1.8
 */
public class InitLog4J {
    public static void init(){
        PropertyConfigurator.configure("log4j.properties");
    }
    static {
        init();
    }
}

2. Two sql scripts of the test are introduced. Because the associated query function is implemented by this time, two sql scripts are introduced

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50722
Source Host           : localhost:3306
Source Database       : mybatis_learn

Target Server Type    : MYSQL
Target Server Version : 50722
File Encoding         : 65001

Date: 2020-03-08 14:23:37
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for library
-- ----------------------------
DROP TABLE IF EXISTS `library`;
CREATE TABLE `library` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of library
-- ----------------------------
INSERT INTO `library` VALUES ('1', 'national library', 'Beijing City');

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50722
Source Host           : localhost:3306
Source Database       : mybatis_learn

Target Server Type    : MYSQL
Target Server Version : 50722
File Encoding         : 65001

Date: 2020-03-08 14:23:47
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for book
-- ----------------------------
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `num` int(11) DEFAULT NULL,
  `library_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `book_ibfk_1` (`library_id`),
  CONSTRAINT `book_ibfk_1` FOREIGN KEY (`library_id`) REFERENCES `library` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of book
-- ----------------------------
INSERT INTO `book` VALUES ('1', 'C Language programming V2', '789', '1');
INSERT INTO `book` VALUES ('2', 'Tagore's poetry collection', '234', null);
INSERT INTO `book` VALUES ('3', 'Morning and evening', '435', null);
INSERT INTO `book` VALUES ('5', 'discrete mathematics', '400', '1');
INSERT INTO `book` VALUES ('6', 'Big data Era', '300', '1');

3. Define two corresponding entities Book and Library

package com.learn.zqw.sqlannotation.domain;

import lombok.Data;

/**
 * //TODO
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/8 13:18
 * @since jdk1.8
 */
@Data
public class Library {

    private Integer id;

    private String name;

    private String address;
}

package com.learn.zqw.sqlannotation.domain;

import lombok.Data;

/**
 * Book Entity class
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/8 12:05
 * @since jdk1.8
 */
@Data
public class Book {

    private Integer id;

    private String name;

    private Integer num;

    private Library library;
}

As mentioned above, define the library attribute in book. There is a many to one relationship between book and library

4. Mapper defining Book and Library, four files in total

<?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="com.learn.zqw.sqlannotation.mapper.LibraryMapper">
    
</mapper>
package com.learn.zqw.sqlannotation.mapper;

import com.learn.zqw.sqlannotation.domain.Book;
import com.learn.zqw.sqlannotation.domain.Library;
import org.apache.ibatis.annotations.Select;

public interface LibraryMapper {

    @Select("select * from library where id = #{id}")
    Library findById(int id);

    int insert(Book book);

}

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.learn.zqw.sqlannotation.mapper.BookMapper">
    <!--Insert a record-->
    <insert id="insert" parameterType="com.learn.zqw.sqlannotation.domain.Book">
        insert into book (name, num, library_id) values (#{name}, #{num}, #{library.id})
    </insert>

    <!--Insert record and return ID-->
    <insert id="insertReturnId" useGeneratedKeys="true" keyProperty="id" keyColumn="id" parameterType="com.learn.zqw.sqlannotation.domain.Book">
        insert into book(name, num, library_id)
        values(#{name}, #{num}, #{library.id})
    </insert>
</mapper>
package com.learn.zqw.sqlannotation.mapper;

import com.learn.zqw.sqlannotation.domain.Book;
import com.learn.zqw.sqlannotation.domain.Library;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

public interface BookMapper {

    int insert(Book book);

    int insertReturnId(Book book);

    @Select("select * from book")
    List<Book> findAll();

    @Select("select * from book where id = #{id}")
    @Results({
            @Result(id=true,column="id",property="id"),
            @Result(column = "name",property = "name"),
            @Result(column = "num",property = "num"),
            @Result(column = "library_id",property = "library",javaType = Library.class,
                    one = @One(select = "com.learn.zqw.sqlannotation.mapper.LibraryMapper.findById",fetchType = FetchType.LAZY)),
    })
    Book findById(int id);
    Book findById(Book book);


    @Select(value = {" <script>" +
            " SELECT * FROM book " +
            " <where> 1=1 " +
            " <if test=\"name != null\"> AND name like CONCAT('%', #{name}, '%')</if> " +
            " <if test=\"num != null\" >  AND num>#{num}</if> " +
            " </where>" +
            " </script>"})
    @Results({
            @Result(id=true,column="id",property="id"),
            @Result(column = "name",property = "name"),
            @Result(column = "num",property = "num"),
            @Result(column = "library_id",property = "library",javaType = Library.class,
                    one = @One(select = "com.learn.zqw.sqlannotation.mapper.LibraryMapper.findById",fetchType = FetchType.LAZY)),
    })
    List<Book> findByCondition(Book book);

    @Insert("insert into book(name, num, library_id) values (#{name}, #{num}, #{library.id})")
    int insert2(Book book);

    @Update("update book set name = #{name} where id = #{id}")
    int update(Book book);

    @Delete("delete from book where id = #{id}")
    int delete(int id);
    int delete(Book id);


}

As mentioned above, @ Select is used for query, @ Update is used for modification, @ Delete is used for deletion, @ Insert is used for addition, @ SQL writing method is basically the same as that in XML. You can use @ Results and other annotations to customize the return Results.
Note the following:

  • Annotation and XML can be mixed. Here, the SQL of insert, insertReturnId and other functions is defined in XML;
  • When associating query, you can use the method of one=@One in the returned custom @ Result to define an associated query;
  • You can use the above {library.id} method when nesting values;
  • The syntax of fuzzy query is as follows: name like concat ('%', {name}, '%');
  • There is a difference between ා and $;
  • It's OK to mix it with generator here.

5. Inject new Mapper
Add two new XML in SqlMapConfig.xml or use package scan

	<mappers>

        <mapper resource="com/learn/zqw/IUserMapper.xml" />
        <mapper resource="com/learn/zqw/generator/mapper/StudentMapper.xml" />

        <! -- you can configure each xml directly, or use package scanning or package scanning. If you use pure annotation, you can also delete the corresponding. xml file -- >
        <!--<mapper resource="com/learn/zqw/sqlannotation/mapper/BookMapper.xml" />-->
        <!-- <mapper resource="com/learn/zqw/sqlannotation/mapper/LibraryMapper.xml" />-->
        <package name="com.learn.zqw.sqlannotation.mapper"/>
    </mappers>

6. Write unit tests

package com.learn.zqw.sqlannotation;

import com.learn.zqw.sqlannotation.domain.Book;
import com.learn.zqw.sqlannotation.domain.Library;
import com.learn.zqw.sqlannotation.mapper.BookMapper;
import com.learn.zqw.sqlannotation.mapper.LibraryMapper;
import lombok.Cleanup;
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 org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * Test annotation method SQL execution
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/8 12:11
 * @since jdk1.8
 */
@RunWith(JUnit4.class)
public class BookTests {

    /**
     * Test query all
     * */
    @Test
    public void test() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        List<Book> books = mapper.findAll();
        Assert.assertNotNull(books);
        if (books != null) {
            books.forEach(System.out::println);
        }
    }

    /**
     * The test queries by ID, associates a main table record, and customizes the result
     * */
    @Test
    public void test2() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        Book book = mapper.findById(1);
        Assert.assertNotNull(book);
        System.out.println(book);
        Book book1 = new Book();
        book1.setId(2);
        Book book2 = mapper.findById(book1);
        Assert.assertNotNull(book2);
        System.out.println(book2);
    }

    /**
     * The test uses the insert method in XML and is nested
     *
     * */
    @Test
    public void test3() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        Book book = new Book();
        book.setName("discrete mathematics");
        book.setNum(400);
        LibraryMapper libraryMapper = session.getMapper(LibraryMapper.class);
        Library library = libraryMapper.findById(1);
        book.setLibrary(library);
        int inserted = mapper.insert(book);
        Assert.assertEquals(1, inserted);
        System.out.println(inserted);
        session.commit();
    }

    /**
     * Test annotation condition query
     * */
    @Test
    public void test4() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        Book book = new Book();
        book.setName("C");
        book.setNum(10);
        List<Book> books = mapper.findByCondition(book);
        Assert.assertNotNull(books);
        books.forEach(System.out::println);
    }

    /**
     * The test uses the insert method in the annotation and inserts for nesting
     *
     * */
    @Test
    public void test5() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        Book book = new Book();
        book.setName("Big data Era");
        book.setNum(300);
        LibraryMapper libraryMapper = session.getMapper(LibraryMapper.class);
        Library library = libraryMapper.findById(1);
        book.setLibrary(library);
        int inserted = mapper.insert2(book);
        Assert.assertEquals(1, inserted);
        System.out.println(inserted);
        session.commit();
    }

    /**
     * Test using the modified input method in annotations
     *
     * */
    @Test
    public void test6() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        Book book = mapper.findById(1);
        book.setName("C Language programming V2");
        int updated = mapper.update(book);
        Assert.assertEquals(1, updated);
        System.out.println(updated);
        session.commit();
    }

    /**
     * Delete method in test usage annotation
     *
     * */
    @Test
    public void test7() throws IOException {
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        BookMapper mapper = session.getMapper(BookMapper.class);
        Book book = new Book();
        book.setName(UUID.randomUUID().toString());
        book.setNum(300);
        LibraryMapper libraryMapper = session.getMapper(LibraryMapper.class);
        Library library = libraryMapper.findById(1);
        book.setLibrary(library);
        int inserted = mapper.insertReturnId(book);
        session.commit();
        Assert.assertEquals(1, inserted);

        int delete = mapper.delete(book.getId());
        Assert.assertEquals(1, delete);
        session.commit();
    }
}

199 original articles published, 33 praised, 210000 visitors+
Private letter follow

Posted by davieboy on Sat, 07 Mar 2020 23:49:30 -0800