SpringBoot中使用tkMapper的方法详解
luis林威 人气:0说明:基于 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 配置文件中配置相关信息
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8 username: root password: luis mybatis: type-aliases-package: com.luis.beans mapper-locations: classpath:mappers/*Mapper.xml
注意:配置后,手动创建 beans 和 mappers 文件夹
3.创建 dao 文件夹,在启动类上添加 dao 的包扫描器 @MapperScan(basePackages = {"com.luis.dao"})
tkMapper 环境搭建
1.添加依赖
<!-- tkMapper --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.1.5</version> </dependency>
如果自己在 maven 仓库中搜索,注意搜索关键词:mapper starter
PS:添加后,注意手动刷新 pom
2.更换启动类上 dao 包的包扫描器来源,不使用原先的 @MapperScan
,要使用新添加的 tkMapper 的 @MapperScan
import tk.mybatis.spring.annotation.MapperScan; @SpringBootApplication @MapperScan(basePackages = {"com.luis.dao"}) //使用tkMapper的包扫描器注解 public class SpringbootTkMapperDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringbootTkMapperDemoApplication.class, args); } }
PS:注意注解的包来源 import tk.mybatis.spring.annotation.MapperScan
3.以上,tkMapper 环境已经搭建完成
tkMapper 对数据的通用操作
tkMapper 提供针对单表通用的数据库操作方法。
数据准备
1. 创建数据库表
DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `user_id` int(11) NOT NULL AUTO_INCREMENT, `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `user_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `user_realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `user_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, PRIMARY KEY (`user_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
2. 创建实体类
@Data @NoArgsConstructor @AllArgsConstructor @Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系! public class User { @Id //指定主键 private Integer userId; private String userName; private String userPwd; private String userRealname; private String userImg; }
3. 创建 Dao 接口【重点】
注意:创建的 Dao 接口需要继承 tkMapper 中提供的 Mapper
和 MySqlMapper
两个接口,这两个接口提供了对单表的通用操作。
public interface UserDao extends Mapper<User>, MySqlMapper<User> { }
可选优化策略【建议使用】:
如果不想每次创建 dao 接口时都继承 tkMapper 中的两个接口,可以自己写一个通用的接口模板,只需要让这个通用的接口模板继承 tkMapper 中的两个接口,然后自己创建的 dao 接口只需要继承这个通用的接口模板即可!
但是,需要注意的是,这个通用的接口模板千万不能写在 dao 目录下!因为 dao 目录下的接口会被扫描到,有固定的功能用处;而我们自定义的通用接口模板只是为了继承,没有其他特殊功能!
使用示例:
1、可在 dao 目录同级创建 general 目录,在 general 目录下创建 GeneralDao 接口,并继承 tkMapper 中的两个接口。
package com.luis.general; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.MySqlMapper; /** * @Author: Luis * @date: 2022/11/9 14:39 * @description: 自定义的通用接口模板 */ public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> { }
2、创建 dao 接口,继承 GeneralDao 即可!
public interface UserDao extends GeneralDao<User> { }
4. 测试
添加 Junit 和 springboot test 两个测试依赖:
<!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!-- springboot test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency>
写测试类进行测试:
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class public class UserDaoTest { @Autowired private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Test public void test() { User user = new User(); user.setUserName("mike"); user.setUserPwd("123"); user.setUserRealname("zhangsan"); user.setUserImg("user/default.jpg"); int i = userDao.insert(user); System.out.println("========> i = " + i); } }
tkMapper 常用方法之增删改
insert
:普通添加insertUseGeneratedKeys
:可返回自增 id 的添加updateByPrimaryKey
:根据主键修改deleteByPrimaryKey
:根据主键删除
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class public class UserDaoTest { @Autowired private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Test public void testInsert() { User user = new User(); user.setUserName("juno4"); user.setUserPwd("321"); user.setUserRealname("lin"); user.setUserImg("user/default.jpg"); /** * insert: 添加(自增的id不会返回) */ int i = userDao.insert(user); System.out.println("========> i = " + i); System.out.println(user.getUserId()); //null } @Test public void testInsertUseGeneratedKeys() { User user = new User(); user.setUserName("juno3"); user.setUserPwd("321"); user.setUserRealname("lin"); user.setUserImg("user/default.jpg"); /** * insertUseGeneratedKeys: 添加(自增的id可以返回) * 注意: * 1. 数据库中主键字段需要设置为自增 * 2. 实体类中主键属性需要使用@Id注解指定;并且需要使用包装类型Integer,不要使用int */ int i = userDao.insertUseGeneratedKeys(user); System.out.println("========> i = " + i); System.out.println(user.getUserId()); //10 } @Test public void testUpdateByPrimaryKey() { User user = new User(); user.setUserId(10); //必须指定要修改的id user.setUserName("juno new"); user.setUserPwd("000"); user.setUserRealname("lin new"); user.setUserImg("new.jpg"); /** * updateByPrimaryKey:根据主键修改 */ int i = userDao.updateByPrimaryKey(user); System.out.println("========> i = " + i); System.out.println(user); } @Test public void testDeleteByPrimaryKey() { /** * deleteByPrimaryKey:根据主键删除 */ int i = userDao.deleteByPrimaryKey(9); System.out.println("========> i = " + i); } }
PS:其实还有根据自定义条件修改或删除的方法(使用方法参考带条件的查询示例)
tkMapper 常用方法之查询
selectAll
:查所有selectByPrimaryKey
:根据主键查所有selectByExample
:根据条件查所有selectByRowBounds
:分页查询selectByExampleAndRowBounds
:带条件的分页查询selectCount
:查总记录数selectCountByExample
:根据条件查总记录数
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class public class UserDaoTest { @Autowired private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Test public void testSelectAll() { /** * selectAll:查询所有 */ List<User> users = userDao.selectAll(); for (User user : users) { System.out.println(user); } } @Test public void testSelectByPrimaryKey() { /** * selectByPrimaryKey:根据主键查询 */ User user = userDao.selectByPrimaryKey(10); System.out.println(user); } @Test public void testSelectByExample() { //封装查询条件 Example example = new Example(User.class); Example.Criteria criteria = example.createCriteria(); //条件信息(根据Criteria对象的各种方法进行设置) criteria.andEqualTo("userRealname", "lin"); // criteria.orEqualTo("userPwd", "123"); // criteria.andLike("userName", "%i%"); /** * selectByPrimaryKey:根据条件查询(PS:根据条件修改或删除与此类似) * 注意:需要设置查询条件信息,并传入条件对象 */ List<User> users = userDao.selectByExample(example); for (User user : users) { System.out.println("========> " + user); } } @Test public void testSelectByRowBounds() { //分页查询信息 int pageNum = 2; //第几页 int pageSize = 3; //每页显示多少行 int start = (pageNum - 1) * pageSize; //起始显示的下标 RowBounds rowBounds = new RowBounds(start, pageSize); /** * selectByRowBounds:查所有的分页查询 */ List<User> users = userDao.selectByRowBounds(new User(), rowBounds); for (User user : users) { System.out.println("========> " + user); } /** * selectCount:查询总记录数 */ int count = userDao.selectCount(new User()); System.out.println("========> count = " + count); } @Test public void testSelectByExampleAndRowBounds() { //封装查询条件 Example example = new Example(User.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("userRealname", "lin"); //分页查询信息 int pageNum = 2; //第几页 int pageSize = 2; //每页显示多少行 int start = (pageNum - 1) * pageSize; //起始显示的下标 RowBounds rowBounds = new RowBounds(start, pageSize); /** * selectByExampleAndRowBounds:带条件的分页查询 */ List<User> users = userDao.selectByExampleAndRowBounds(example, rowBounds); for (User user : users) { System.out.println("========> " + user); } /** * selectCountByExample:根据条件查询总记录数 */ int count = userDao.selectCountByExample(example); System.out.println("========> count = " + count); } }
tkMapper 关联/多表查询
说明:所有的关联/多表查询都可以由多个单表查询组成
关联/多表查询实现方式:
方式一:多次使用单表查询,然后封装数据
方式二:自定义查询方法和 SQL
情景:基于以上的用户表,新添加一个订单表 orders,订单表中有订单信息,但是也有用户 id;
要求:在查询用户表的同时还要查询出用户的订单信息,这就涉及到了两张表的查询。
具体业务要求:根据用户名查询用户的所有信息,包括订单信息。
数据准备
新建订单表 orders:
DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` ( `order_id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `receiver_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `receiver_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`order_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact; INSERT INTO `orders` VALUES (1, 1, 'luis', '13344445555', '湖北武汉');
新建实体类 Order:
@Data @NoArgsConstructor @AllArgsConstructor @Table(name = "orders") public class Order { @Id private Integer orderId; private Integer userId; private String receiverName; private String receiverMobile; private String receiverAddress; }
新建 dao 接口:
注意,此处 dao 接口继承的是自定义的通用接口模板,相关说明参见之前创建示例 UserDao 的步骤。
也可以直接继承 tkMapper 的两个接口。(注意灵活运用!)
public interface OrderDao extends GeneralDao<Order> { }
说明:进行关联/多表查询前,需要修改下之前的 User 实体类,在实体类中需要添加一个订单的字段,以便查询出用户所关联的订单信息。
@Data @NoArgsConstructor @AllArgsConstructor @Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系! public class User { @Id //指定主键 private Integer userId; private String userName; private String userPwd; private String userRealname; private String userImg; //订单 private List<Order> orderList; }
方式一:多次单表查询
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class public class UserDaoTest { @Autowired private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Autowired private OrderDao orderDao; @Test public void test() { //根据用户名查询用户信息 Example example = new Example(User.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("userName", "luis"); //条件查询 List<User> users = userDao.selectByExample(example); User user = users.get(0); //根据用户id查询订单信息 Example example1 = new Example(Order.class); Example.Criteria criteria1 = example.createCriteria(); criteria.andEqualTo("userId", user.getUserId()); //条件查询 List<Order> orders = orderDao.selectByExample(example1); //将查询到的订单信息设置到user中 user.setOrderList(orders); System.out.println("========> " + user); } }
方式二:自定义连接查询
1.UserDao 接口中新建查询方法
public interface UserDao extends GeneralDao<User> { public User selectByUserName(String userName); }
2.mappers 目录下创建对应的 UserMapper.xml 文件,自定义查询 SQL
<?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.luis.dao.UserDao"> <resultMap id="userMap" type="com.luis.beans.User"> <id column="user_id" property="userId"/> <result column="user_name" property="userName"/> <result column="user_pwd" property="userPwd"/> <result column="user_realname" property="userRealname"/> <result column="user_img" property="userImg"/> <collection property="orderList" ofType="com.luis.beans.Order"> <id column="order_id" property="orderId"/> <result column="user_id" property="userId"/> <result column="receiver_name" property="receiverName"/> <result column="receiver_mobile" property="receiverMobile"/> <result column="receiver_address" property="receiverAddress"/> </collection> </resultMap> <select id="selectByUserName" resultMap="userMap"> select u.user_id,u.user_name,u.user_pwd,u.user_realname,u.user_img, o.order_id,o.user_id,o.receiver_name,o.receiver_mobile,o.receiver_address from users u inner join orders o on u.user_id = o.user_id; </select> </mapper>
3.测试
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class public class UserDaoTest { @Autowired private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Autowired private OrderDao orderDao; @Test public void test02() { //使用自定义的查询方法 User user = userDao.selectByUserName("luis"); System.out.println("========> " + user); } }
逆向工程
所谓逆向工程,就是通过数据库表,来自动生成实体类、dao 接口和 mapper 文件。
需要注意的是,本逆向工程是最好配合 tkMapper 环境使用,因为,有一些配置和 tkMapper 相关,如生成的 dao 接口会继承自定义的通用接口模板,而该通用的接口模板就是继承了 tkMapper 中的两个接口,从而才能使用 tkMapper 提供的通用数据操作方法;还有,生成的实体类上的注解需要依赖 tkMapper 环境。
重要说明:本逆向工程使用的 mysql 版本是低版本 5.1.36!经测试,如果使用高版本如 8.xxx,很大概率会生成有问题!所以建议项目中统一使用低版本的 MySQL。
1.在 pom.xml 中 build 的 plugins 下添加下列生成器插件
<!-- mybatis-generator-maven-plugin --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.6</version> <!-- 生成器配置文件位置;如果还没有添加,可以先注释,添加后再放开 --> <configuration> <configurationFile> ${basedir}/src/main/resources/generator/GeneratorConfig.xml </configurationFile> </configuration> <!-- 插件所需的两个依赖 --> <dependencies> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.36</version> </dependency> <!-- mapper --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>4.1.5</version> </dependency> </dependencies> </plugin>
注意:推荐直接复制,但如果想自己在 maven 仓库中搜索,注意关键词:mybatis-generator-maven-plugin
,并且,千万注意,你搜索到的肯定是依赖,而并非插件!此时,你只需要复制依赖的 gav 坐标,自己在 pom 中创建空 plugin 标签,将 gav 坐标复制进去即可!(如果相关依赖刷新添加失败,可以复制到 dependences 下,重新刷新添加试试,添加成功后复制回来即可)
2.注意查看项目中是否自定义有通用接口模板 GeneralDao,使其继承 tkMapper 的两个接口;如果没有,则在 dao 同级目录,创建 general 目录,在 general 目录下创建自定义通用接口模板 GeneralDao,继承 tkMapper 的两个接口;
public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> { }
3.在 resources/generator
下添加 GeneratorConfig.xml
生成器配置(创建并复制后改主要配置即可)
主要需要配置:配置数据库连接、配置实体类存放路径、配置 XML 存放路径、配置 DAO 存放路径、配置 GeneralDao
注意:默认配置是生成指定数据库中所有表,也可以自定义的指定只生成哪些表
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- 引入数据库连接配置 --> <!-- <properties resource="jdbc.properties"/>--> <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"> <property name="beginningDelimiter" value="`"/> <property name="endingDelimiter" value="`"/> <!-- 配置 GeneralDao --> <plugin type="tk.mybatis.mapper.generator.MapperPlugin"> <property name="mappers" value="com.luis.general.GeneralDao"/> </plugin> <!-- 配置数据库连接(注意数据库版本问题,需要使用低版本的,高版本可能出现问题!) --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/springdb?serverTimezone=UTC" userId="root" password="luis"> </jdbcConnection> <!-- 配置实体类存放路径 --> <javaModelGenerator targetPackage="com.luis.beans" targetProject="src/main/java"/> <!-- 配置 XML 存放路径 --> <sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/> <!-- 配置 Dao 存放路径 --> <javaClientGenerator targetPackage="com.luis.dao" targetProject="src/main/java" type="XMLMAPPER"/> <!-- 配置需要指定生成的数据库和表,% 代表所有表 --> <table tableName="%"> <!-- mysql 配置 --> <!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>--> </table> <!-- <table tableName="tb_roles">--> <!-- <!– mysql 配置 –>--> <!-- <generatedKey column="roleid" sqlStatement="Mysql" identity="true"/>--> <!-- </table>--> <!-- <table tableName="tb_permissions">--> <!-- <!– mysql 配置 –>--> <!-- <generatedKey column="perid" sqlStatement="Mysql" identity="true"/>--> <!-- </table>--> </context> </generatorConfiguration>
4.打开 IDEA 右侧 Maven 窗口,找到项目--》Plugins--》mybatis-generator--》mybatis-generator:generate,双击执行逆向生成即可!
示例图:
5.查看 beans、dao、mappers 目录下的生成情况,看生成的相关接口是否符合开发要求,根据情况可做相关修改,然后进行相关测试。
加载全部内容