MyBatis-Plus(简称 MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatisPlus的愿景是成为MyBatis最好的搭档,就像魂斗罗中的1P、2P,基友搭配,效率翻倍。
官方网址:MyBatis-Plus
1、创建SpringBoot项目,添加MyBatisPlus起步依赖
org.springframework.boot spring-boot-starterorg.springframework.boot spring-boot-starter-testtest com.baomidou mybatis-plus-boot-starter3.5.0 mysql mysql-connector-java8.0.26 org.projectlombok lomboktrue
2、在SpringBoot配置文件中配置数据源
# 数据源 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql:///mybatis?serverTimezone=UTC username: root password: 123456
3、编写实体类
@Data public class User { public Integer id; public String username; public String sex; public String address; public Integer account; }
4、编写Mapper接口,继承BaseMapper
public interface UserMapper extends BaseMapper{ }
5、在 SpringBoot启动类中添加 @MapperScan 注解,扫描Mapper文件夹
@SpringBootApplication @MapperScan("com.zj.mapper") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
6、测试Mapper方法
@SpringBootTest public class TestUserMapper { @Resource private UserMapper userMapper; @Test public void test(){ User user = userMapper.selectById(10); System.out.println(user); } }
1、配置文件开启SQL日志打印
# 开启SQL日志 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2、测试添加方法
@Test public void testAdd(){ User user = new User(null,"梅川内酷","男","临沂市",3000); userMapper.insert(user); // MyBatisPlus插入成功后,可直接直接获取主键的值 System.out.println(user.getUserId()); }
我们将user类中的字段修改为和数据库表中的字段不一致。将表名称改为tb_user, 这样表中的字段、表名都和实体类不一致。这样mybatosplus无法自动将字段和属性对应。也就无法生成正确的sql语句。此时需要使用注解来指定映射关系。
作用:指定类为哪个表的实体类
位置:类上方
作用:指定实体类的属性为主键
位置:属性上方
属性:
value:主键字段名
type:主键策略
值 | 描述 |
---|---|
NONE | 无状态,不设置主键类型 |
AUTO | 自增主键 |
INPUT | 插入前自行设置主键值 |
ASSIGN_ID | 默认策略,使用雪花算法自动生成主键ID,主键类型为整形或字符串。(雪花算法:微博开源的分布式ID生成算法,使用一个64位的Long类型数字作为全局唯一ID。在分布式系统中的应用十分广泛,且ID引入了时间戳,基本上保持自增) |
ASSIGN_UUID | 自动生成排除中划线的UUID作为主键,主键类型为 |
作用:在属性和列名不同的情况下,指定映射关系
位置:非主键属性上方
@Data @AllArgsConstructor @TableName("tb_user") public class User { @TableId(value = "id",type = IdType.AUTO) public Integer UserId; @TableField("username") public String userName; @TableField("sex") public String userSex; @TableField("address") public String userAddress; @TableField("account") public Integer userAccount; }
@Test public void testUpdate(){ User user = new User(1,"梅川丘酷","男","烟台市",4000); userMapper.updateById(user); }
@Test public void testDeleteById(){ userMapper.deleteById(8); }
@Test public void testDeleteBatch(){ ArrayListids = new ArrayList<>(); ids.add(9); ids.add(10); ids.add(11); userMapper.deleteBatchIds(ids); }
@Test public void testDeleteMap(){ Mapmap = new HashMap (); map.put("sex","男"); ;//删除所有字段(字段是数据库列名不是类的属性名)值是男的数据 userMapper.deleteByMap(map); }
@Test public void testFindById(){ User user = userMapper.selectById(1); System.out.println(user); }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE id=? ==> Parameters: 5(Integer) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 5, 翟玲娇, 女, 长沙市, 1000 <== Total: 1
@Test public void testFindBatch(){ ArrayListids = new ArrayList<>(); ids.add(5); ids.add(6); ids.add(12); List users = userMapper.selectBatchIds(ids); }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE id IN ( ? , ? , ? ) ==> Parameters: 5(Integer), 6(Integer), 12(Integer) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 5, 翟玲娇, 女, 长沙市, 1000 <== Row: 6, 张晓, 女, 青岛市, 2500 <== Row: 12, 唐宛凝, 女, 石家庄市, 3334 <== Total: 3
@Test public void testFindByMap(){ Mapmap = new HashMap (); //条件之间是and关系 map.put("username","张晓"); map.put("address","青岛市"); List users = userMapper.selectByMap(map); }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE address = ? AND username = ? ==> Parameters: 青岛市(String), 张晓(String) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 6, 张晓, 女, 青岛市, 2500 <== Total: 1
Mybatis-Plus通过QueryWrapper对象让用户自由的构建SQL条件,简单便捷,没有额外的负担,能够有效提高开发效率。
条件参数说明:
查询方式 | 说明 |
---|---|
or | 或条件语句 |
and | 且条件语句 |
like | 模糊查询 like |
notLike | 模糊查询 not Like |
exists | exists 条件语句 |
notExists | not Exists 条件语句 |
isNull | null 值查询 |
isNotNull | is Not Null 查询 |
in | in 查询 |
notIn | not in 查询 |
groupBy | 分组查询 |
orderBy | 排序查询 |
having | 分组后筛选 |
eq | 等于 = |
ne | 不等于 <> |
between | between 条件语句 |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
示例1:查询账户余额在1000-3000之间的用户的信息
@Test public void testFindWrapper(){ //创建条件构造器 QueryWrapperwrapper = new QueryWrapper<>(); wrapper.ge("account", 1000).lt("account", 3000); List users = userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE (account >= ? AND account < ?) ==> Parameters: 1000(Integer), 3000(Integer) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 5, 翟玲娇, 女, 长沙市, 1000 <== Row: 6, 张晓, 女, 青岛市, 2500 <== Total: 2
示例2:查询账户小于1000或者大于等于9000的用户
@Test public void testFindWrapper(){ //创建条件构造器 QueryWrapperwrapper = new QueryWrapper<>(); wrapper.lt("account", 2000).or().ge("account", 9000); List users = userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE (account < ? OR account >= ?) ==> Parameters: 2000(Integer), 9000(Integer) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 5, 翟玲娇, 女, 长沙市, 1000 <== Row: 16, 郑怜雪, 女, 重庆市, 555900 <== Row: 19, 黎飒, 男, 深圳市, 9000 <== Total: 3
示例3:查询名字中有张的用户,按照账户升序排序。
@Test public void testFindWrapper(){ //创建条件构造器 QueryWrapperwrapper = new QueryWrapper<>(); wrapper.like("username", "张").orderByAsc("account"); List users = userMapper.selectList(wrapper); }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE (username LIKE ?) ORDER BY account ASC ==> Parameters: %张%(String) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 6, 张晓, 女, 青岛市, 2500 <== Row: 21, 张三, 男, 昆明市, 5000 <== Total: 2
// 注册插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }
2、测试分页查询
@Test public void testFindPage(){ //分页条件;第一个参数表示从第几条开始,第二个参数表示取几条数据。 Page page = new Page(0,2); IPageiPage = userMapper.selectPage(page, null);//null表示查询全部 System.out.println("结果集:"+iPage.getRecords()); System.out.println("总页数:"+iPage.getPages()); System.out.println("总条数:"+iPage.getTotal()); System.out.println("当前页:"+iPage.getCurrent()); System.out.println("每页条数:"+iPage.getSize()); }
==> Preparing: SELECT COUNT(*) AS total FROM tb_user ==> Parameters: <== Columns: total <== Row: 8 <== Total: 1 ==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user LIMIT ? ==> Parameters: 2(Long) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 5, 翟玲娇, 女, 长沙市, 1000 <== Row: 6, 张晓, 女, 青岛市, 2500 <== Total: 2 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ff2b8ca] 结果集:[User(UserId=5, userName=翟玲娇, userSex=女, userAddress=长沙市, userAccount=1000), User(UserId=6, userName=张晓, userSex=女, userAddress=青岛市, userAccount=2500)] 总页数:4 总条数:8 当前页:1 每页条数:2
假如数据库的所有表都以tb_开头,主键都是自增的。如果针对每一个实体类都要添加相关注解比较麻烦,可以在SpringBoot配置文件中进行全局配置,该配置在所有的实体类中都生效。
mybatis-plus: # 全局配置 global-config: db-config: #主键类型 id-type: AUTO # 设置表名前缀 table-prefix: tb_ # 是否使用驼峰转下划线命名,默认开启 ,例如 实体类中的UserAddress属性等于数据库中的 user_address字段 table-underline: true
Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
在MyBatisPlus中,AR模式即在实体类中封装了对数据库的访问,而不通过mapper类。
1、虽然操作数据库不通过mapper类,但需要编写mapper类并继承BaseMapper
public interface UserMapper extends BaseMapper{ }
2、实体类继承Model类,开启AR模式
@Data @AllArgsConstructor @TableName("tb_user") public class User extends Model{ @TableId(value = "id",type = IdType.AUTO) public Integer UserId; @TableField("username") public String userName; @TableField("sex") public String userSex; @TableField("address") public String userAddress; @TableField("account") public Integer userAccount; }
@Test public void testAdd(){ User user = new User(null, "李四", "男", "北京市", 12000); user.insert(); }
==> Preparing: INSERT INTO tb_user ( username, sex, address, account ) VALUES ( ?, ?, ?, ? ) ==> Parameters: 李四(String), 男(String), 北京市(String), 12000(Integer) <== Updates: 1
@Test public void testUpdate(){ // 创建实体类对象 User user = new User(); // 设置需要更新的属性 user.setUserAccount(13000); // 设置需要修改的id user.setUserId(22); // 根据主键进行更新,没有设置的值忽略 user.updateById(); }
==> Preparing: UPDATE tb_user SET account=? WHERE id=? ==> Parameters: 13000(Integer), 22(Integer) <== Updates: 1
@Test public void testFindById(){ User user = new User(); user.setUserId(16); User user1 = user.selectById(); }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE id=? ==> Parameters: 16(Integer) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 16, 郑怜雪, 女, 重庆市, 555900 <== Total: 1
@Test public void testDeleteById(){ User user = new User(); user.setUserId(21); user.deleteById(); }
==> Preparing: DELETE FROM tb_user WHERE id=? ==> Parameters: 21(Integer) <== Updates: 1
@Test public void testFindAll(){ User user = new User(); Listusers = user.selectAll(); }
==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user ==> Parameters: <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 5, 翟玲娇, 女, 长沙市, 1000 <== Row: 6, 张晓, 女, 青岛市, 2500 <== Row: 12, 唐宛凝, 女, 石家庄市, 3334 <== Row: 16, 郑怜雪, 女, 重庆市, 555900 <== Row: 18, 梅川内酷, 男, 临沂市, 3000 <== Row: 19, 黎飒, 男, 深圳市, 9000 <== Row: 20, 黄林, 男, 昆明市, 5000 <== Row: 22, 李四, 男, 北京市, 13000 <== Total: 8
@Test public void testFindPage(){ // 创建分页条件 Page page = new Page(0,2); // 查询构造器 QueryWrapperqueryWrapper = new QueryWrapper<>(); // 查询名字包含"张"的学生,按照账户升序排序 queryWrapper.like("username","张").orderByAsc("account"); User user = new User(); // 分页查询 IPage iPage = user.selectPage(page, queryWrapper); // 打印分页数据 System.out.println("结果集:"+iPage.getRecords()); System.out.println("总页数:"+iPage.getPages()); System.out.println("总条数:"+iPage.getTotal()); System.out.println("当前页:"+iPage.getCurrent()); System.out.println("每页条数:"+iPage.getSize()); }
==> Preparing: SELECT COUNT(*) AS total FROM tb_user WHERE (username LIKE ?) ==> Parameters: %张%(String) <== Columns: total <== Row: 2 <== Total: 1 ==> Preparing: SELECT id AS UserId,username,sex AS userSex,address AS userAddress,account AS userAccount FROM tb_user WHERE (username LIKE ?) ORDER BY account ASC LIMIT ? ==> Parameters: %张%(String), 2(Long) <== Columns: UserId, username, userSex, userAddress, userAccount <== Row: 6, 张晓, 女, 青岛市, 2500 <== Row: 23, 张三, 男, 北京市, 12000 <== Total: 2
注意:AR分页查询也需要配置分页插件
MyBatis插件就是对Executor、StatementHandler、ParameterHandler、ResultSetHandler这四个接口上的方法进行拦截,利用JDK动态代理机制,为这些接口的实现类创建代理对象,在执行方法时,先去执行代理对象的方法,从而执行自己编写的拦截逻辑。
Executor
MyBatis的内部执行器,它负责调用StatementHandler操作数据库,并把结果集通过 ResultSetHandler进行自动映射。
StatementHandler
MyBatis直接让数据库执行sql脚本的对象。
ParameterHandler
MyBatis实现Sql入参设置的对象。
ResultSetHandler
MyBatis把ResultSet集合映射成POJO的接口对象。
MyBatisPlus依据MyBatis插件机制,为我们提供了一些开发中常用的插件,我们在开发中使用即可。
常用插件:
这些插件都实现了InnerInterceptor接口
在配置类或启动类配置分页插件,之前用过,不配置插件的话分页功能无法实现。
// 注册插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }
作用:分析删除/更新语句,防止小白或者恶意进行删除/更新全表操作。
注意:
- 该插件只支持 MySQL5.6.3 以上版本
- 该插件只建议在开发环境中使用,不建议在生产环境使用
插件使用:
1、在配置类或启动类配置防止全表更新与删除插件
// 注册插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 防止全表更新与删除插件 interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); return interceptor; }
2、测试全表删除
@Test public void testDeleteAll() { User user = new User(); user.delete(new QueryWrapper()); }
修改数据库中的数据时,为了避免同时被其他人修改,最好的办法就是对该数据进行加锁以防止并发。
锁的设计分为悲观锁和乐观锁:
MyBatisPlus乐观锁插件实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
使用MyBatisPlus乐观锁插件:
1、注册乐观锁插件
// 注册插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 防止全表更新与删除插件 interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }
2、修改实体类,添加version列并在该属性上面增加@Version
@Data @AllArgsConstructor @NoArgsConstructor @TableName("tb_user") public class User extends Model{ @TableId(value = "id",type = IdType.AUTO) public Integer UserId; @TableField("username") public String userName; @TableField("sex") public String userSex; @TableField("address") public String userAddress; @TableField("account") public Integer userAccount; @Version private Integer version; }
3、修改数据库表,添加一列整型version字段并设置默认值为0
4、测试修改功能
@Test public void testUpdate1() { User user = new User(); user.setUserId(18); user.setUserName("梅川丘酷"); //如果版本号和数据库一致更新成功,版本号+1,如果不一致更新失败 user.setVersion(0); user.updateById(); }
==> Preparing: UPDATE tb_user SET username=?, version=? WHERE id=? AND version=? ==> Parameters: 梅川丘酷(String), 1(Integer), 18(Integer), 0(Integer) <== Updates: 1
在实际开发中,由于数据十分重要,为了避免误删除数据导致数据无法找回,我们往往不会使用物理删除,即从数据库中直接删除数据。而是采用逻辑删除的方式,即不会真正在数据库删除数据,而是通过一个变量代表它被删除。
deleted属性代表该数据是否删除,0代表未删除,1代表已删除。此时增删改查的Sql语句发生变化:
- 插入: 不作限制
- 查找: 追加where条件过滤掉已删除数据。
- 更新: 追加where条件防止更新到已删除数据。
- 删除: 转变为更新
例如:
- 删除: update user set deleted=1 where id = 1 and deleted=0
- 查找: select id,name,deleted from user where deleted=0
1、在配置文件配置逻辑删除
# mybatis-plus相关配置 mybatis-plus: # 全局配置 global-config: db-config: # 全局逻辑删除的字段名 logic-delete-field: deleted # 逻辑已删除值(默认为 1) logic-delete-value: 1 # 逻辑未删除值(默认为 0) logic-not-delete-value: 0
2、修改实体类,添加逻辑删除属性
@Data @AllArgsConstructor @NoArgsConstructor @TableName("tb_user") public class User extends Model{ @TableId(value = "id",type = IdType.AUTO) public Integer UserId; @TableField("username") public String userName; @TableField("sex") public String userSex; @TableField("address") public String userAddress; @TableField("account") public Integer userAccount; @Version private Integer version; /*逻辑删除*/ @TableLogic private Integer deleted; }
3、修改数据库表,添加一列整型deleted字段并设置默认值为0
4、测试删除和查询方法,会看到删除时将deleted字段变为1,查询时添加条件deleted=0
@Test public void testDelete() { User user = new User(); user.deleteById(23); }
==> Preparing: UPDATE tb_user SET deleted=1 WHERE id=? AND deleted=0 ==> Parameters: 23(Integer) <== Updates: 1
bug:
Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1 at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:218) at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:176) at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:171) at org.yaml.snakeyaml.reader.StreamReader.peek(StreamReader.java:126) at org.yaml.snakeyaml.scanner.ScannerImpl.scanToNextToken(ScannerImpl.java:1177) at org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:287) at org.yaml.snakeyaml.scanner.ScannerImpl.checkToken(ScannerImpl.java:227) at org.yaml.snakeyaml.parser.ParserImpl$ParseImplicitDocumentStart.produce(ParserImpl.java:195) at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:158) at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:148) at org.yaml.snakeyaml.composer.Composer.checkNode(Composer.java:72) at org.yaml.snakeyaml.constructor.BaseConstructor.checkData(BaseConstructor.java:114) at org.yaml.snakeyaml.Yaml.hasNext(Yaml.java:543) at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:160) at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:134) at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:75) at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50) at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadDocuments(ConfigFileApplicationListener.java:562) at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:518) ... 37 common frames omitted Caused by: java.nio.charset.MalformedInputException: Input length = 1这里要将编码格式设置为utf-8,然后再删除yml配置文件,再重新写一个yml。
由于有了逻辑删除字段,那么向数据库插入数据时候,都需要设置deleted=0,而每次插入数据时都要设置该值十分繁琐,于是MyBatisPlus提供了自动填充功能。
1、为实体类的自动填充字段添加@TableField
@TableLogic // 自动填充字段 @TableField(fill = FieldFill.INSERT) private Integer deleted;
填充策略:
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入操作填充字段 |
UPDATE | 更新操作填充字段 |
INSERT_UPDATE | 插入操作和更新操作均填充字段 |
2、自定义填充类实现MetaObjectHandler接口
package com.zj.meta; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; @Component public class MyMetaObjectHandler implements MetaObjectHandler { /* 插入时填充逻辑 * metaObject 元对象 * */ @Override public void insertFill(MetaObject metaObject) { /* 参数1:填充字段名 * 参数2:参数值 * 参数3:元对象*/ this.setFieldValByName("deleted",0,metaObject); } @Override public void updateFill(MetaObject metaObject) { } }
3、测试插入数据
@Test public void testAdd() { User user = new User(); user.setUserName("小刚"); user.setUserAddress("淄博市"); user.setUserSex("男"); user.setUserAccount(4000); user.insert(); }
==> Preparing: INSERT INTO tb_user ( username, sex, address, account, deleted ) VALUES ( ?, ?, ?, ?, ? ) ==> Parameters: 小刚(String), 男(String), 淄博市(String), 4000(Integer), 0(Integer) <== Updates: 1: 1
在插入数据的时候,如果将数据库的deleted字段设置默认值为0的话,其实不需要使用mybatisplus的自动填充,因为在添加数据的时候自动就赋值为0了。
MyBatisPlus方法是有限的,我们可以使用SQL注入器自定义全局方法,注入到全局中,这样所有的Mapper类都能使用该方法,接下来我们自定义一个deleteAll方法。
1、创建注入方法类,继承AbstractMethod
public class DeleteAll extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) { //1.定义sql语句 String sql = "delete from "+tableInfo.getTableName(); //2.定义方法名 String methodName = "deleteAll"; //3.构建sqlSource对象,负责将sql传递到数据库 SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass); //4.构建删除方法 return this.addDeleteMappedStatement(mapperClass,methodName,sqlSource); } }
2、创建SQL自动注入器,继承AbstractSqlInjector
@Component public class MySqlInject extends AbstractSqlInjector { //注入自定义方法集合 @Override public List getMethodList(Class> mapperClass, TableInfo tableInfo) { ArrayList abstractMethods = new ArrayList<>(); abstractMethods.add(new DeleteAll()); return abstractMethods; } }
3、注销防止全表更新与删除插件
4、在Mapper接口中定义deleteAll方法
public interface UserMapper extends BaseMapper{ void deleteAll(); }
5、测试deleteAll方法,测试的时候不能使用AR模式,因为该方法不存在User类中,而是自定义的。
@Test public void testDeleteAll() { userMapper.deleteAll(); }
如果不想手动编写实体类等文件,MyBaitsPlus提供了代码生成器,它可以读取数据库的表信息,生成MyBaitsPlus代码供我们使用,之前我们学过MyBatis的代码生成器MyBatis Generator,这二者的区别是:
1、添加代码生成器所需的依赖
com.baomidou mybatis-plus-generator3.5.1 org.apache.velocity velocity-engine-core2.2
2、编写代码生成器
package com.zj.Generator; import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; public class MyGenerator { public static void main(String[] args) { FastAutoGenerator.create("jdbc:mysql:///mybatis", "root", "123456") // 全局配置 .globalConfig(builder -> { builder.author("zhangjin") // 设置作者 .commentDate("MM-dd") // 注释日期格式 .outputDir(System.getProperty("user.dir") + "/src/main/java") // 指定输出目录 .fileOverride(); //覆盖文件 }) // 包配置 .packageConfig(builder -> { builder.parent("com.zj") // 包名前缀 .entity("pojo") //实体类包名 .mapper("mapper") //mapper接口包名 .service("service") //service包名 .controller("controller") //controller包名 .xml("mapper"); //映射文件包名 }) // 策略配置 .strategyConfig(builder -> { builder.addInclude("tb_user") // 设置需要生成的表名,可以有多个 .addTablePrefix("tb_") // 设置表名前缀 .entityBuilder() // 开始实体类配置 .enableLombok() // 开启lombok模型 .naming(NamingStrategy.underline_to_camel) //表名下划线转驼峰 .columnNaming(NamingStrategy.underline_to_camel);//列名下划线转驼峰 }) .execute(); } }
3、运行代码生成器即可生成代码
MybatisX是一款基于IDEA的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Marketplace,输入 mybatisx 搜索并安装。
1、在IDEA中连接数据库
2、如下操作可以根据数据库表生成Mybaits代码
1、在Mapper接口中编写方法
public interface StudentMapper extends BaseMapper{ List selectAllBySname(String sname); }
2、如下操作即可在映射文件中自动生成映射配置
代码跳转
点击Mapper接口或映射文件前的小鸟图案,即可快速在Mapper接口与映射文件间跳转