第一章:前言
- 注解开发虽然不如 XML 开发那样,可以完全做到代码和配置文件分离,但是其开发灵活快速的特性,使得在企业开发中的地位日益显著,而 Mybatis 作为时下最流行的持久层框架,掌握 Mybatis 注解开发势在必行。
第二章:环境准备
-- ------------------------------ Table structure for account-- ----------------------------DROP TABLE IF EXISTS `account`;CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NULL DEFAULT NULL COMMENT '外键', `money` double NULL DEFAULT NULL COMMENT '存款', PRIMARY KEY (`id`) USING BTREE, INDEX `fk_user_id`(`user_id`) USING BTREE, CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of account-- ----------------------------INSERT INTO `account` VALUES (1, 1, 5000);INSERT INTO `account` VALUES (2, 2, 2000);INSERT INTO `account` VALUES (3, 3, 3000);-- ------------------------------ Table structure for course-- ----------------------------DROP TABLE IF EXISTS `course`;CREATE TABLE `course` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程名称', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of course-- ----------------------------INSERT INTO `course` VALUES (1, '语文');INSERT INTO `course` VALUES (2, '数学');INSERT INTO `course` VALUES (3, '英语');-- ------------------------------ Table structure for student-- ----------------------------DROP TABLE IF EXISTS `student`;CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学生姓名', `age` int(11) NULL DEFAULT NULL COMMENT '学生年龄', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of student-- ----------------------------INSERT INTO `student` VALUES (1, '张三', 20);INSERT INTO `student` VALUES (2, '李四', 25);-- ------------------------------ Table structure for student_course-- ----------------------------DROP TABLE IF EXISTS `student_course`;CREATE TABLE `student_course` ( `sid` int(11) NULL DEFAULT NULL COMMENT '外键,指向学生表的主键', `cid` int(11) NULL DEFAULT NULL COMMENT '外键,指向课程表的主键', INDEX `fk_sid`(`sid`) USING BTREE, INDEX `fk_cid`(`cid`) USING BTREE, CONSTRAINT `fk_cid` FOREIGN KEY (`cid`) REFERENCES `course` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `fk_sid` FOREIGN KEY (`sid`) REFERENCES `student` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of student_course-- ----------------------------INSERT INTO `student_course` VALUES (1, 1);INSERT INTO `student_course` VALUES (1, 2);INSERT INTO `student_course` VALUES (1, 3);INSERT INTO `student_course` VALUES (2, 3);-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', `birthday` datetime(0) NULL DEFAULT NULL COMMENT '生日', `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别', `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES (1, '张三', '2021-11-02 10:43:06', '男', '江苏苏州');INSERT INTO `user` VALUES (2, '李四', '2021-10-26 10:43:24', '女', '江苏南京');INSERT INTO `user` VALUES (3, '王五', '2021-10-26 10:43:45', '男', '江苏徐州');
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version></dependency><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version></dependency><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version></dependency><dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope></dependency>
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.134.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <package name="com.github.mapper"/> </mappers></configuration>
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="info" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root></log4j:configuration>
第三章:Mybatis 注解实现常用的 CRUD
package com.sunxiaping.domain;import java.io.Serializable;import java.util.Date;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String gender; private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", gender='" + gender + '\'' + ", address='" + address + '\'' + '}'; }}
package com.sunxiaping.mapper;import com.sunxiaping.domain.User;import org.apache.ibatis.annotations.*;import java.util.List;public interface UserMapper { /** * 查询所有用户信息 * * @return */ @Select(" SELECT * FROM `user`") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "username", column = "username"), @Result(property = "birthday", column = "birthday"), @Result(property = "gender", column = "gender"), @Result(property = "address", column = "address"), }) List<User> findAll(); /** * 添加用户信息 * * @param user */ @Insert(" INSERT INTO `user` (username,birthday,gender,address) VALUES (#{username},#{birthday},#{gender},#{address})") void saveUser(User user); /** * 修改用户信息 * * @param user */ @Update(" UPDATE `user` set username = #{username},gender= #{gender} ,address = #{address} WHERE id = #{id} ") void updateUser(User user); /** * 删除用户信息 * * @param id */ @Delete(" DELETE FROM `user` WHERE id = #{id} ") void deleteById(Integer id);}
package com.sunxiaping;import com.sunxiaping.domain.User;import com.sunxiaping.mapper.UserMapper;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.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.Date;import java.util.List;public class UserTest { SqlSessionFactory sqlSessionFactory = null; SqlSession sqlSession = null; @Before public void before() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @After public void after() { if (sqlSession != null) { sqlSession.close(); } } @Test public void testFindAll() throws IOException { sqlSession = sqlSessionFactory.openSession(true); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.findAll(); System.out.println("userList = " + userList); } @Test public void testSaveUser() { sqlSession = sqlSessionFactory.openSession(true); User user = new User(); user.setUsername("zhangsan"); user.setBirthday(new Date()); user.setGender("男"); user.setAddress("江苏苏州"); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.saveUser(user); } @Test public void testUpdateUser() { sqlSession = sqlSessionFactory.openSession(true); User user = new User(); user.setId(1); user.setUsername("张三"); user.setGender("女"); user.setAddress("江苏苏州"); user.setBirthday(new Date()); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.updateUser(user); } @Test public void testDeleteById() { sqlSession = sqlSessionFactory.openSession(true); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.deleteById(1); }}
第四章:Mybatis 注解实现一对一关联查询

SELECT * FROM `account`
SELECT * FROM `user` WHERE id = #{id}
package com.github.entity;import java.io.Serializable;import java.util.Date;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:42 */public class User implements Serializable { private Integer id; private String username; private Date birthday; private String gender; private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", gender='" + gender + '\'' + ", address='" + address + '\'' + '}'; }}
package com.github.entity;import java.io.Serializable;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:44 */public class Account implements Serializable { private Integer id; private Double money; /** * 一个账户属于一个用户 */ private User user; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Account{" + "id=" + id + ", money=" + money + ", user=" + user + '}'; }}
package com.github.mapper;import com.github.entity.User;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Result;import org.apache.ibatis.annotations.Results;import org.apache.ibatis.annotations.Select;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:45 */@Mapperpublic interface UserMapper { @Select("SELECT * FROM `user` WHERE id = #{id}") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "username", column = "username"), @Result(property = "birthday", column = "birthday"), @Result(property = "gender", column = "gender"), @Result(property = "address", column = "address"), }) User findById(Integer id);}
package com.github.mapper;import com.github.entity.Account;import com.github.entity.User;import org.apache.ibatis.annotations.*;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:45 */@Mapperpublic interface AccountMapper { @Select("SELECT * FROM `account`") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "money", column = "money"), @Result( property = "user", javaType = User.class, column = "user_id", one = @One(select = "com.github.mapper.UserMapper.findById") ) }) List<Account> findAll();}
package com.github.mybatis;import com.github.entity.Account;import com.github.mapper.AccountMapper;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.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-10-29 14:19 */public class MybatisTest { SqlSession sqlSession; @Before public void before() throws IOException { // 使用Mybatis的Resources读取mybatis-config.xml配置文件 InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); sqlSession = sqlSessionFactory.openSession(); } @Test public void test() throws IOException { AccountMapper accountMapper = sqlSession.getMapper(AccountMapper.class); List<Account> accountList = accountMapper.findAll(); accountList.forEach(System.out::println); } @After public void after() { if (null != sqlSession) { sqlSession.close(); } }}
第五章:Mybatis 注解实现一对多关联查询

SELECT * FROM `user`
SELECT * FROM `account` where user_id = #{user_id}
package com.github.entity;import java.io.Serializable;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:44 */public class Account implements Serializable { private Integer id; private Double money; public Account(Integer id, Double money) { this.id = id; this.money = money; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", money=" + money + '}'; }}
package com.github.entity;import java.io.Serializable;import java.util.Date;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:42 */public class User implements Serializable { private Integer id; private String username; private Date birthday; private String gender; private String address; // 一个用户有多个账号 private List<Account> accountList; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public List<Account> getAccountList() { return accountList; } public void setAccountList(List<Account> accountList) { this.accountList = accountList; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", gender='" + gender + '\'' + ", address='" + address + '\'' + ", accountList=" + accountList + '}'; }}
package com.github.mapper;import com.github.entity.Account;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Result;import org.apache.ibatis.annotations.Results;import org.apache.ibatis.annotations.Select;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:45 */@Mapperpublic interface AccountMapper { @Select("SELECT * FROM `account` where user_id = #{userId}") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "money", column = "money")} ) List<Account> findByUserId(Integer userId);}
package com.github.mapper;import com.github.entity.User;import org.apache.ibatis.annotations.*;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 10:45 */@Mapperpublic interface UserMapper { @Select(" SELECT * FROM `user`") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "username", column = "username"), @Result(property = "birthday", column = "birthday"), @Result(property = "gender", column = "gender"), @Result(property = "address", column = "address"), @Result( property = "accountList", // 被包含对象的变量名 column = "id", // 根据查询出来的user表中的id去根据user_id查询 many = @Many(select = "com.github.mapper.AccountMapper.findByUserId")), }) List<User> findAll();}
package com.github.mybatis;import com.github.entity.User;import com.github.mapper.UserMapper;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.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-10-29 14:19 */public class MybatisTest { SqlSession sqlSession; @Before public void before() throws IOException { // 使用Mybatis的Resources读取mybatis-config.xml配置文件 InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); sqlSession = sqlSessionFactory.openSession(); } @Test public void test() throws IOException { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.findAll(); userList.forEach(System.out::println); } @After public void after() { if (null != sqlSession) { sqlSession.close(); } }}
第六章:Mybatis 注解实现多对多关联查询

SELECT * FROM `student`
SELECT c.* FROM `student_course` sc INNER JOIN `course` c ON sc.cid = c.id WHERE sc.sid = #{id}
package com.github.entity;import java.io.Serializable;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 11:06 */public class Student implements Serializable { private Integer id; private String name; private Integer age; private List<Course> courseList; public Student() {} public Student(Integer id, String name, Integer age, List<Course> courseList) { this.id = id; this.name = name; this.age = age; this.courseList = courseList; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", courseList=" + courseList + '}'; }}
package com.github.entity;import java.io.Serializable;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 11:07 */public class Course implements Serializable { private Integer id; private String name; public Course() {} public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Course{" + "id=" + id + ", name='" + name + '\'' + '}'; }}
package com.github.mapper;import com.github.entity.Course;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Select;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 11:09 */@Mapperpublic interface CourseMapper { @Select("SELECT c.* FROM `student_course` sc INNER JOIN `course` c ON sc.cid = c.id WHERE sc.sid = #{id}") List<Course> findBySid(Integer id);}
package com.github.mapper;import com.github.entity.Student;import org.apache.ibatis.annotations.*;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-11-02 11:09 */@Mapperpublic interface StudentMapper { @Select("SELECT * FROM `student`") @Results({ @Result(id = true, property = "id", column = "id"), @Result(property = "name", column = "name"), @Result(property = "age", column = "age"), @Result( property = "courseList", //被包含对象的变量名 column = "id", //根据查询出来的student表中的id去中间表和course表中查询 many = @Many(select = "com.github.mapper.CourseMapper.findBySid") ) }) List<Student> findAll();}
package com.github.mybatis;import com.github.entity.Student;import com.github.mapper.StudentMapper;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.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.List;/** * @author 许大仙 * @version 1.0 * @since 2021-10-29 14:19 */public class MybatisTest { SqlSession sqlSession; @Before public void before() throws IOException { // 使用Mybatis的Resources读取mybatis-config.xml配置文件 InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); sqlSession = sqlSessionFactory.openSession(); } @Test public void test() throws IOException { StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); List<Student> studentList = studentMapper.findAll(); studentList.forEach(System.out::println); } @After public void after() { if (null != sqlSession) { sqlSession.close(); } }}