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