• Spring Boot 中使用 tkMapper


    说明:基于 MyBatis 有很多第三方功能插件,这些插件可以完成数据操作方法的封装、数据库逆向工程的生成等。

    tkMapper 和 MyBatis-plus 都是基于 MyBatis 提供的第三方插件,功能类似,下面介绍 tkMapper 的使用。

    简介

    tkMapper 就是一个 MyBatis 插件,基于 MyBatis 提供很多工具,提高开发效率,主要有以下两个功能。

    • 提供针对单表通用的数据库操作方法
    • 逆向工程(根据数据表自动生成实体类、Dao 接口、Mapper 映射文件)

    MyBatis 基础环境

    tkMapper 的使用需要基于 MyBatis。

    1. 创建 Spring Boot 项目,选中 Lombok、Spring Web、MyBatis Framework、MySQL Driver 依赖

    2. application.yml 配置文件中配置相关信息

      1. spring:
      2. datasource:
      3. driver-class-name: com.mysql.jdbc.Driver
      4. url: jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
      5. username: root
      6. password: luis
      7. mybatis:
      8. type-aliases-package: com.luis.beans
      9. mapper-locations: classpath:mappers/*Mapper.xml

      注意:配置后,手动创建 beans 和 mappers 文件夹

    3. 创建 dao 文件夹,在启动类上添加 dao 的包扫描器 @MapperScan(basePackages = {"com.luis.dao"})

    tkMapper 环境搭建

    1. 添加依赖

      1. <!-- tkMapper -->
      2. <dependency>
      3. <groupId>tk.mybatis</groupId>
      4. <artifactId>mapper-spring-boot-starter</artifactId>
      5. <version>2.1.5</version>
      6. </dependency>

      如果自己在 maven 仓库中搜索,注意搜索关键词:mapper starter

      PS:添加后,注意手动刷新 pom

    2. 更换启动类上 dao 包的包扫描器来源,不使用原先的 @MapperScan,要使用新添加的 tkMapper 的 @MapperScan

      1. import tk.mybatis.spring.annotation.MapperScan;
      2. @SpringBootApplication
      3. @MapperScan(basePackages = {"com.luis.dao"}) //使用tkMapper的包扫描器注解
      4. public class SpringbootTkMapperDemoApplication {
      5. public static void main(String[] args) {
      6. SpringApplication.run(SpringbootTkMapperDemoApplication.class, args);
      7. }
      8. }

      PS:注意注解的包来源 import tk.mybatis.spring.annotation.MapperScan

    3. 以上,tkMapper 环境已经搭建完成

    tkMapper 对数据的通用操作

    tkMapper 提供针对单表通用的数据库操作方法。

    数据准备

    1. 创建数据库表

    1. DROP TABLE IF EXISTS `users`;
    2. CREATE TABLE `users` (
    3. `user_id` int(11) NOT NULL AUTO_INCREMENT,
    4. `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
    5. `user_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
    6. `user_realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
    7. `user_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
    8. PRIMARY KEY (`user_id`) USING BTREE
    9. ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

    2. 创建实体类

    1. @Data
    2. @NoArgsConstructor
    3. @AllArgsConstructor
    4. @Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
    5. public class User {
    6. @Id //指定主键
    7. private Integer userId;
    8. private String userName;
    9. private String userPwd;
    10. private String userRealname;
    11. private String userImg;
    12. }

    3. 创建 Dao 接口【重点】

    注意:创建的 Dao 接口需要继承 tkMapper 中提供的 Mapper 和 MySqlMapper 两个接口,这两个接口提供了对单表的通用操作。

    1. public interface UserDao extends Mapper<User>, MySqlMapper<User> {
    2. }

    可选优化策略【建议使用】:

    如果不想每次创建 dao 接口时都继承 tkMapper 中的两个接口,可以自己写一个通用的接口模板,只需要让这个通用的接口模板继承 tkMapper 中的两个接口,然后自己创建的 dao 接口只需要继承这个通用的接口模板即可!

    但是,需要注意的是,这个通用的接口模板千万不能写在 dao 目录下!因为 dao 目录下的接口会被扫描到,有固定的功能用处;而我们自定义的通用接口模板只是为了继承,没有其他特殊功能!

    使用示例:

    1、可在 dao 目录同级创建 general 目录,在 general 目录下创建 GeneralDao 接口,并继承 tkMapper 中的两个接口。

    1. package com.luis.general;
    2. import tk.mybatis.mapper.common.Mapper;
    3. import tk.mybatis.mapper.common.MySqlMapper;
    4. /**
    5. * @Author: Luis
    6. * @date: 2022/11/9 14:39
    7. * @description: 自定义的通用接口模板
    8. */
    9. public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
    10. }

    2、创建 dao 接口,继承 GeneralDao 即可!

    1. public interface UserDao extends GeneralDao<User> {
    2. }

    4. 测试

    添加 Junit 和 springboot test 两个测试依赖:

    1. <!-- junit -->
    2. <dependency>
    3. <groupId>junit</groupId>
    4. <artifactId>junit</artifactId>
    5. <scope>test</scope>
    6. </dependency>
    7. <!-- springboot test -->
    8. <dependency>
    9. <groupId>org.springframework.boot</groupId>
    10. <artifactId>spring-boot-starter-test</artifactId>
    11. </dependency>

    写测试类进行测试:

    1. @RunWith(SpringRunner.class)
    2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
    3. public class UserDaoTest {
    4. @Autowired
    5. private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
    6. @Test
    7. public void test() {
    8. User user = new User();
    9. user.setUserName("mike");
    10. user.setUserPwd("123");
    11. user.setUserRealname("zhangsan");
    12. user.setUserImg("user/default.jpg");
    13. int i = userDao.insert(user);
    14. System.out.println("========> i = " + i);
    15. }
    16. }

    tkMapper 常用方法之增删改

    • insert:普通添加
    • insertUseGeneratedKeys:可返回自增 id 的添加
    • updateByPrimaryKey:根据主键修改
    • deleteByPrimaryKey:根据主键删除
    1. @RunWith(SpringRunner.class)
    2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
    3. public class UserDaoTest {
    4. @Autowired
    5. private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
    6. @Test
    7. public void testInsert() {
    8. User user = new User();
    9. user.setUserName("juno4");
    10. user.setUserPwd("321");
    11. user.setUserRealname("lin");
    12. user.setUserImg("user/default.jpg");
    13. /**
    14. * insert: 添加(自增的id不会返回)
    15. */
    16. int i = userDao.insert(user);
    17. System.out.println("========> i = " + i);
    18. System.out.println(user.getUserId()); //null
    19. }
    20. @Test
    21. public void testInsertUseGeneratedKeys() {
    22. User user = new User();
    23. user.setUserName("juno3");
    24. user.setUserPwd("321");
    25. user.setUserRealname("lin");
    26. user.setUserImg("user/default.jpg");
    27. /**
    28. * insertUseGeneratedKeys: 添加(自增的id可以返回)
    29. * 注意:
    30. * 1. 数据库中主键字段需要设置为自增
    31. * 2. 实体类中主键属性需要使用@Id注解指定;并且需要使用包装类型Integer,不要使用int
    32. */
    33. int i = userDao.insertUseGeneratedKeys(user);
    34. System.out.println("========> i = " + i);
    35. System.out.println(user.getUserId()); //10
    36. }
    37. @Test
    38. public void testUpdateByPrimaryKey() {
    39. User user = new User();
    40. user.setUserId(10); //必须指定要修改的id
    41. user.setUserName("juno new");
    42. user.setUserPwd("000");
    43. user.setUserRealname("lin new");
    44. user.setUserImg("new.jpg");
    45. /**
    46. * updateByPrimaryKey:根据主键修改
    47. */
    48. int i = userDao.updateByPrimaryKey(user);
    49. System.out.println("========> i = " + i);
    50. System.out.println(user);
    51. }
    52. @Test
    53. public void testDeleteByPrimaryKey() {
    54. /**
    55. * deleteByPrimaryKey:根据主键删除
    56. */
    57. int i = userDao.deleteByPrimaryKey(9);
    58. System.out.println("========> i = " + i);
    59. }
    60. }

    PS:其实还有根据自定义条件修改或删除的方法(使用方法参考带条件的查询示例)

    tkMapper 常用方法之查询

    • selectAll:查所有
    • selectByPrimaryKey:根据主键查所有
    • selectByExample:根据条件查所有
    • selectByRowBounds:分页查询
    • selectByExampleAndRowBounds:带条件的分页查询
    • selectCount:查总记录数
    • selectCountByExample:根据条件查总记录数
    1. @RunWith(SpringRunner.class)
    2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
    3. public class UserDaoTest {
    4. @Autowired
    5. private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
    6. @Test
    7. public void testSelectAll() {
    8. /**
    9. * selectAll:查询所有
    10. */
    11. List<User> users = userDao.selectAll();
    12. for (User user : users) {
    13. System.out.println(user);
    14. }
    15. }
    16. @Test
    17. public void testSelectByPrimaryKey() {
    18. /**
    19. * selectByPrimaryKey:根据主键查询
    20. */
    21. User user = userDao.selectByPrimaryKey(10);
    22. System.out.println(user);
    23. }
    24. @Test
    25. public void testSelectByExample() {
    26. //封装查询条件
    27. Example example = new Example(User.class);
    28. Example.Criteria criteria = example.createCriteria();
    29. //条件信息(根据Criteria对象的各种方法进行设置)
    30. criteria.andEqualTo("userRealname", "lin");
    31. // criteria.orEqualTo("userPwd", "123");
    32. // criteria.andLike("userName", "%i%");
    33. /**
    34. * selectByPrimaryKey:根据条件查询(PS:根据条件修改或删除与此类似)
    35. * 注意:需要设置查询条件信息,并传入条件对象
    36. */
    37. List<User> users = userDao.selectByExample(example);
    38. for (User user : users) {
    39. System.out.println("========> " + user);
    40. }
    41. }
    42. @Test
    43. public void testSelectByRowBounds() {
    44. //分页查询信息
    45. int pageNum = 2; //第几页
    46. int pageSize = 3; //每页显示多少行
    47. int start = (pageNum - 1) * pageSize; //起始显示的下标
    48. RowBounds rowBounds = new RowBounds(start, pageSize);
    49. /**
    50. * selectByRowBounds:查所有的分页查询
    51. */
    52. List<User> users = userDao.selectByRowBounds(new User(), rowBounds);
    53. for (User user : users) {
    54. System.out.println("========> " + user);
    55. }
    56. /**
    57. * selectCount:查询总记录数
    58. */
    59. int count = userDao.selectCount(new User());
    60. System.out.println("========> count = " + count);
    61. }
    62. @Test
    63. public void testSelectByExampleAndRowBounds() {
    64. //封装查询条件
    65. Example example = new Example(User.class);
    66. Example.Criteria criteria = example.createCriteria();
    67. criteria.andEqualTo("userRealname", "lin");
    68. //分页查询信息
    69. int pageNum = 2; //第几页
    70. int pageSize = 2; //每页显示多少行
    71. int start = (pageNum - 1) * pageSize; //起始显示的下标
    72. RowBounds rowBounds = new RowBounds(start, pageSize);
    73. /**
    74. * selectByExampleAndRowBounds:带条件的分页查询
    75. */
    76. List<User> users = userDao.selectByExampleAndRowBounds(example, rowBounds);
    77. for (User user : users) {
    78. System.out.println("========> " + user);
    79. }
    80. /**
    81. * selectCountByExample:根据条件查询总记录数
    82. */
    83. int count = userDao.selectCountByExample(example);
    84. System.out.println("========> count = " + count);
    85. }
    86. }

    tkMapper 关联/多表查询

    说明:所有的关联/多表查询都可以由多个单表查询组成

    关联/多表查询实现方式:

    方式一:多次使用单表查询,然后封装数据

    方式二:自定义查询方法和 SQL

    情景:基于以上的用户表,新添加一个订单表 orders,订单表中有订单信息,但是也有用户 id;

    要求:在查询用户表的同时还要查询出用户的订单信息,这就涉及到了两张表的查询。

    具体业务要求:根据用户名查询用户的所有信息,包括订单信息。

    数据准备

    新建订单表 orders:

    1. DROP TABLE IF EXISTS `orders`;
    2. CREATE TABLE `orders` (
    3. `order_id` int(11) NOT NULL AUTO_INCREMENT,
    4. `user_id` int(11) NOT NULL,
    5. `receiver_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
    6. `receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
    7. `receiver_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
    8. PRIMARY KEY (`order_id`) USING BTREE
    9. ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
    10. INSERT INTO `orders` VALUES (1, 1, 'luis', '13344445555', '湖北武汉');

    新建实体类 Order:

    1. @Data
    2. @NoArgsConstructor
    3. @AllArgsConstructor
    4. @Table(name = "orders")
    5. public class Order {
    6. @Id
    7. private Integer orderId;
    8. private Integer userId;
    9. private String receiverName;
    10. private String receiverMobile;
    11. private String receiverAddress;
    12. }

    新建 dao 接口:

    注意,此处 dao 接口继承的是自定义的通用接口模板,相关说明参见之前创建示例 UserDao 的步骤。

    也可以直接继承 tkMapper 的两个接口。(注意灵活运用!)

    1. public interface OrderDao extends GeneralDao<Order> {
    2. }

    说明:进行关联/多表查询前,需要修改下之前的 User 实体类,在实体类中需要添加一个订单的字段,以便查询出用户所关联的订单信息。

    1. @Data
    2. @NoArgsConstructor
    3. @AllArgsConstructor
    4. @Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
    5. public class User {
    6. @Id //指定主键
    7. private Integer userId;
    8. private String userName;
    9. private String userPwd;
    10. private String userRealname;
    11. private String userImg;
    12. //订单
    13. private List<Order> orderList;
    14. }

    方式一:多次单表查询

    1. @RunWith(SpringRunner.class)
    2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
    3. public class UserDaoTest {
    4. @Autowired
    5. private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
    6. @Autowired
    7. private OrderDao orderDao;
    8. @Test
    9. public void test() {
    10. //根据用户名查询用户信息
    11. Example example = new Example(User.class);
    12. Example.Criteria criteria = example.createCriteria();
    13. criteria.andEqualTo("userName", "luis");
    14. //条件查询
    15. List<User> users = userDao.selectByExample(example);
    16. User user = users.get(0);
    17. //根据用户id查询订单信息
    18. Example example1 = new Example(Order.class);
    19. Example.Criteria criteria1 = example.createCriteria();
    20. criteria.andEqualTo("userId", user.getUserId());
    21. //条件查询
    22. List<Order> orders = orderDao.selectByExample(example1);
    23. //将查询到的订单信息设置到user中
    24. user.setOrderList(orders);
    25. System.out.println("========> " + user);
    26. }
    27. }

    方式二:自定义连接查询

    1. UserDao 接口中新建查询方法

      1. public interface UserDao extends GeneralDao<User> {
      2. public User selectByUserName(String userName);
      3. }
    2. mappers 目录下创建对应的 UserMapper.xml 文件,自定义查询 SQL

      1. <?xml version="1.0" encoding="UTF-8" ?>
      2. <!DOCTYPE mapper
      3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      5. <mapper namespace="com.luis.dao.UserDao">
      6. <resultMap id="userMap" type="com.luis.beans.User">
      7. <id column="user_id" property="userId"/>
      8. <result column="user_name" property="userName"/>
      9. <result column="user_pwd" property="userPwd"/>
      10. <result column="user_realname" property="userRealname"/>
      11. <result column="user_img" property="userImg"/>
      12. <collection property="orderList" ofType="com.luis.beans.Order">
      13. <id column="order_id" property="orderId"/>
      14. <result column="user_id" property="userId"/>
      15. <result column="receiver_name" property="receiverName"/>
      16. <result column="receiver_mobile" property="receiverMobile"/>
      17. <result column="receiver_address" property="receiverAddress"/>
      18. </collection>
      19. </resultMap>
      20. <select id="selectByUserName" resultMap="userMap">
      21. select u.user_id,u.user_name,u.user_pwd,u.user_realname,u.user_img,
      22. o.order_id,o.user_id,o.receiver_name,o.receiver_mobile,o.receiver_address
      23. from users u inner join orders o
      24. on u.user_id = o.user_id;
      25. </select>
      26. </mapper>
    3. 测试

      1. @RunWith(SpringRunner.class)
      2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
      3. public class UserDaoTest {
      4. @Autowired
      5. private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
      6. @Autowired
      7. private OrderDao orderDao;
      8. @Test
      9. public void test02() {
      10. //使用自定义的查询方法
      11. User user = userDao.selectByUserName("luis");
      12. System.out.println("========> " + user);
      13. }
      14. }

    逆向工程

    所谓逆向工程,就是通过数据库表,来自动生成实体类、dao 接口和 mapper 文件。

    需要注意的是,本逆向工程是最好配合 tkMapper 环境使用,因为,有一些配置和 tkMapper 相关,如生成的 dao 接口会继承自定义的通用接口模板,而该通用的接口模板就是继承了 tkMapper 中的两个接口,从而才能使用 tkMapper 提供的通用数据操作方法;还有,生成的实体类上的注解需要依赖 tkMapper 环境。

    重要说明:本逆向工程使用的 mysql 版本是低版本 5.1.36!经测试,如果使用高版本如 8.xxx,很大概率会生成有问题!所以建议项目中统一使用低版本的 MySQL。

    1. 在 pom.xml 中 build 的 plugins 下添加下列生成器插件

      1. <!-- mybatis-generator-maven-plugin -->
      2. <plugin>
      3. <groupId>org.mybatis.generator</groupId>
      4. <artifactId>mybatis-generator-maven-plugin</artifactId>
      5. <version>1.3.6</version>
      6. <!-- 生成器配置文件位置;如果还没有添加,可以先注释,添加后再放开 -->
      7. <configuration>
      8. <configurationFile>
      9. ${basedir}/src/main/resources/generator/GeneratorConfig.xml
      10. </configurationFile>
      11. </configuration>
      12. <!-- 插件所需的两个依赖 -->
      13. <dependencies>
      14. <!-- mysql -->
      15. <dependency>
      16. <groupId>mysql</groupId>
      17. <artifactId>mysql-connector-java</artifactId>
      18. <version>5.1.36</version>
      19. </dependency>
      20. <!-- mapper -->
      21. <dependency>
      22. <groupId>tk.mybatis</groupId>
      23. <artifactId>mapper</artifactId>
      24. <version>4.1.5</version>
      25. </dependency>
      26. </dependencies>
      27. </plugin>

      注意:推荐直接复制,但如果想自己在 maven 仓库中搜索,注意关键词:mybatis-generator-maven-plugin,并且,千万注意,你搜索到的肯定是依赖,而并非插件!此时,你只需要复制依赖的 gav 坐标,自己在 pom 中创建空 plugin 标签,将 gav 坐标复制进去即可!(如果相关依赖刷新添加失败,可以复制到 dependences 下,重新刷新添加试试,添加成功后复制回来即可)

    2. 注意查看项目中是否自定义有通用接口模板 GeneralDao,使其继承 tkMapper 的两个接口;如果没有,则在 dao 同级目录,创建 general 目录,在 general 目录下创建自定义通用接口模板 GeneralDao,继承 tkMapper 的两个接口;

      1. public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
      2. }
    3. 在 resources/generator 下添加 GeneratorConfig.xml 生成器配置(创建并复制后改主要配置即可)

      主要需要配置:配置数据库连接、配置实体类存放路径、配置 XML 存放路径、配置 DAO 存放路径、配置 GeneralDao

      注意:默认配置是生成指定数据库中所有表,也可以自定义的指定只生成哪些表

      1. "1.0" encoding="UTF-8"?>
      2. generatorConfiguration
      3. PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
      4. "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
      5. <generatorConfiguration>
      6. <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
      7. <property name="beginningDelimiter" value="`"/>
      8. <property name="endingDelimiter" value="`"/>
      9. <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
      10. <property name="mappers" value="com.luis.general.GeneralDao"/>
      11. plugin>
      12. <jdbcConnection driverClass="com.mysql.jdbc.Driver"
      13. connectionURL="jdbc:mysql://localhost:3306/springdb?serverTimezone=UTC"
      14. userId="root" password="luis">
      15. jdbcConnection>
      16. <javaModelGenerator targetPackage="com.luis.beans" targetProject="src/main/java"/>
      17. <sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
      18. <javaClientGenerator targetPackage="com.luis.dao" targetProject="src/main/java" type="XMLMAPPER"/>
      19. <table tableName="%">
      20. table>
      21. context>
      22. generatorConfiguration>
    4. 打开 IDEA 右侧 Maven 窗口,找到项目--》Plugins--》mybatis-generator--》mybatis-generator:generate,双击执行逆向生成即可!

      示例图:

    5. 查看 beans、dao、mappers 目录下的生成情况,看生成的相关接口是否符合开发要求,根据情况可做相关修改,然后进行相关测试。

  • 相关阅读:
    git 删除远程非主分支
    AirPods Pro的降噪功能让你体验更好,那么如何打开这个功能
    【数据结构】测试3 栈和队列
    CSS基础入门手册
    GIS杂记(三):MaxEnt模型中的图像地理范围不匹配【全网最好的方法,没有之一】
    mysql与SQL SERVER 基本语法区别
    electron 应用开发优秀实践
    Python 模块
    Flask数据库_SQLAIchemy常用的数据类型与使用
    [安网杯 2021] REV WP
  • 原文地址:https://blog.csdn.net/m0_73311735/article/details/127787456