MyBatisPlus 0 lombok 插件问题
我们可以使用 Lombok 的 @Data标签,不用手动添加get set方法,但是如果项目中其他类中使用get、set方法,如果报错,原因是idea中没有添加Lombok插件,添加上插件便可以解决
在 IDEA的 setting 中,找到 Plugins. 搜索 lombok 。
1 mybatisPlus位置 1 官网地址:https://baomidou.com/
MyBatis-Plus (opens new window) (简称 MP)是一个 MyBatis (opens new window) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性: 优点: 看官网介绍。
然后可以在Bean上使用:
@Data :自动提供getter和setter、hashCode、equals、toString等方法
@Getter:自动提供getter方法
@Setter:自动提供setter方法
@Slf4j:自动在bean中提供log变量,其实用的是slf4j的日志功能。 @NoArgsConstructor,
@AllArgsConstructor,
https://www.cnblogs.com/ooo0/p/12448096.html
2 mybatisplus的第一个案例
数据表结构参照官网 快速开始
1 2 3 4 5 6 7 8 9 10 11 12 13 14 CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) ); INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');
创建springboot工程。
主要POM文件是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.10.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.lpc</groupId> <artifactId>mp4</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>mp4</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
创建实体类
1 2 3 4 5 6 7 8 9 @Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String name; private Integer age; private String email; }
数据源配置信息
1 2 3 4 5 6 7 8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.url=jdbc:mysql://localhost:3306/myjpa?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #spring.datasource.initialization-mode=always mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
创建Mapper映射文件 接口
1 2 3 4 @Repository public interface UserMapper extends BaseMapper<User> { }
在启动类扫描
1 2 3 4 5 6 7 @SpringBootApplication @MapperScan("com.lpc.mapper") public class Mp4Application { public static void main(String[] args) { SpringApplication.run(Mp4Application.class, args); } }
在测试类 测试即可。
测试情况 抄 官网
3 配置日志 显示执行的Sql 配置日志 默认的控制台输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
4 CRUD 测试 4.1 插入测试 1 2 3 4 5 6 7 8 9 @Test void inserttest(){ User user=new User(); user.setAge(100); user.setEmail("123@qq.com"); user.setName("张三"); userMapper.insert(user); System.out.println(user); }
插入之后会发现 自动 插入了ID值
Parameters: 1384691084839411714(Long), 张三(String), 100(Integer), 123@qq.com (String)
在核心功能的自定义 ID 生成器。 在文档中 中可以查看 自定义ID生成器
此ID 默认 用了 雪花算法来实现。可以参照:
https://www.cnblogs.com/haoxinyue/p/5208136.html
1 snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0
实体类
1 2 3 4 5 6 7 8 9 10 11 12 @Data @AllArgsConstructor @NoArgsConstructor public class User { @TableId(type=IdType.INPUT) private Long id; private String name; private Integer age; private String email; } 可以配置成自己输入的。
4.2 删除测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 单个删除 userMapper.deleteById(6666 ); 批量删除: List<Long> list=new ArrayList<>(); list.add(1415693168090914817L ); list.add(1415693532735270913L ); userMapper.deleteBatchIds(list); DELETE FROM user WHERE id IN ( ? , ? ) Map删除 底层 用 and 拼接: Map<String,Object> map =new HashMap<>();map.put("name" ,"Jone" ); map.put("age" ,18 ); userMapper.deleteByMap(map);
4.3 修改测试
修改 在 文档的 CRUD接口中的 Update这里。。
1 2 3 4 5 6 7 8 9 10 // 根据 UpdateWrapper 条件,更新记录 需要设置sqlset boolean update(Wrapper<T> updateWrapper); // 根据 whereEntity 条件,更新记录 boolean update(T entity, Wrapper<T> updateWrapper); // 根据 ID 选择修改 boolean updateById(T entity); // 根据ID 批量更新 boolean updateBatchById(Collection<T> entityList); // 根据ID 批量更新 boolean updateBatchById(Collection<T> entityList, int batchSize);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 根据id单个修改 @Test void updatetest(){ User user=new User(); user.setAge(100); user.setEmail("123@qq.com"); user.setName("李四"); userMapper.updateById(user); } 也可以根据传入条件 查询: @Test public void xg() { User user=new User(); user.setAge(100); user.setEmail("1232323@qq.com"); user.setName("张分双方的士大夫三"); UpdateWrapper wrapper=new UpdateWrapper(); wrapper.eq("id",1415587633979031553L); userMapper.update(user,wrapper); } 条件具体构造: https://blog.csdn.net/typ1805/article/details/84649606
修改的时候 自动拼接Sql
自动填充时间 如数据的插入时间,修改时间等。
自动填充有数据库级别的自动填充 和 程序级别的自动填充
4.4 数据库级别自动填充
设置 默认时间为 CURRENT_TIMESTAMP
修改时间 勾选 根据当前时间戳更新。
添加字段
1 2 private Date inserttime; private Date updatetime;
重新测试插入数据 和修改数据 。即可测试到效果。
4.5 代码级别自动填充
用mybatisplus 来 做自动填充,删除上面 所做的默认时间戳。
1 2 3 4 5 6 // 插入的时候更新 @TableField(fill=FieldFill.INSERT) private Date inserttime; // 插入和更新的时候都更新 @TableField(fill=FieldFill.INSERT_UPDATE) private Date updatetime;
然后写处理器 处理 注解。 官网上看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Component public class MyBatisPlusTime implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.fillStrategy(metaObject, "inserttime", new Date()); this.fillStrategy(metaObject, "updatetime", new Date()); } @Override public void updateFill(MetaObject metaObject) { this.fillStrategy(metaObject, "updatetime", new Date()); } } 自动填充问题: https://blog.csdn.net/kingwinstar/article/details/113418552
删除操作:
1 2 3 4 5 // 测试真实删除 @Test void deleteuser(){ userMapper.deleteById(1); }
// 查询
@Test
void selectAlltest(){
List<User> list= userMapper.selectBatchIds(Arrays.asList(1,2,3));
list.forEach(System.out::println);
}
4.6 测试逻辑删除
逻辑删除的理念是 标记一个状态 让查询通过这个状态, 不真实的 从数据库删除。 看文档。
可以给表中做一个 deleted 字段。
如 deleted = 0 是 正常状态 deleted =1 是删除状态。
操作: 1 在数据库中 添加 deleted 字段 默认是 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1 在数据库中 添加 deleted 字段 默认是 0 2 在实体类中配置: @TableLogic private int deleted; 3 在application.properties 中配置 mybatis-plus.global-config.db-config.logic-not-delete-value=0 mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-delete-field=deleted 4 测试: // 测试逻辑删除 @Test void deleteuser1(){ userMapper.deleteById(2); } 看生成的Sql语句,可以 再查询 User user= userMapper.selectById(2); System.out.println(user); 可观察生成的 Sql. SELECT id,name,age,email,deleted FROM user WHERE id=? AND deleted=0
4.7 条件查询构造器 Wrapper 1 2 3 4 5 6 7 8 @Test void wappertest(){ QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.like("name","李"); queryWrapper.eq("age",100); List<User> list=userMapper.selectList(queryWrapper); list.forEach(System.out::println); }
4.8 查询测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 selectById User user= userMapper.selectById(2 ); System.out.println(user); 2 selectCount int a= userMapper.selectCount(null ); 3 selectBatchIds List<Integer> list=new ArrayList<>(); list.add(2 ); list.add(3 ); list.add(4 ); List<User> users= userMapper.selectBatchIds(list); users.forEach(System.out::println); 4 selectByMap Map<String,Object> map=new HashMap<>(); map.put("name" ,"Jack" ); map.put("age" ,20 ); List<User> users= userMapper.selectByMap(map); users.forEach(System.out::println); 5 selectList(wrapper); QueryWrapper wrapper=new QueryWrapper(); wrapper.like("name" ,"T" ); wrapper.gt("age" ,20 ); List<User> userList =userMapper.selectList(wrapper); userList.forEach(System.out::println);
5 乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新 看文档 乐观锁实现方式:
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 1 给 表中 和字段中 加 version, 默认是 1 2 在 表字段的 version 上面加 @Version 表示是个乐观锁。 @Version private Integer version; 3 在 spring boot注解方式: 看官网 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } @EnableTransactionManagement @Configuration public class MyConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }
1 2 3 4 5 6 7 8 9 // 测试更新 测试更新的时候一定要 先查询 @Test void updatetest(){ User user=userMapper.selectById(1385046598274363393L); user.setAge(104330); user.setEmail("1332431@qq.com"); user.setName("4311李四12323"); userMapper.updateById(user); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // 测试乐观锁 更新 多线程情况下 @Test void updatetest1(){ User user=userMapper.selectById(1385046598274363393L); user.setAge(100); user.setEmail("1231@qq.com"); user.setName("999你好我好12323"); User user1=userMapper.selectById(1385046598274363393L); user1.setAge(100); user1.setEmail("1231@qq.com"); user1.setName("77你好我好12323"); userMapper.updateById(user1); userMapper.updateById(user); } 后面的 不会成功。
6 分页
PaginationInnerInterceptor
导入分页插件,分页插件和乐观锁插件是重合的。
1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration @MapperScan("com.lpc.mapper") @EnableTransactionManagement //事务处理 public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 添加 Mybatis的分页插件 mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return mybatisPlusInterceptor; } }
测试分页:
1 2 3 4 5 6 7 // 测试分页插件 @Test void selectpage(){ Page page = new Page(1,5); userMapper.selectPage(page,null); page.getRecords().forEach(System.out::println); }
Page中参数详解:
1 2 3 4 5 6 7 8 9 10 11 参数名 参数类型 默认值 描述 records List<T> 用来存放查询出来的数据 total long 返回记录的总数 size long 每页显示条数 current long 当前页 orders List<OrderItem> 排序字段信息 optimizeCountSql boolean true 自动优化 COUNT SQL isSearchCount boolean true 是否进行 count 查询,设置false 后不会返回total hitCount boolean false 是否命中count缓存 countId String 暂时未知 maxLimit Long null 单页分页条数限制
7 代码生成器 1 2 3 4 5 6 7 8 9 10 11 12 核心功能: 代码生成器: <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4 .1 </version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.2 </version> </dependency>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public class CodeGenerator { public static void main (String[] args) { AutoGenerator mpg = new AutoGenerator(); GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir" ); gc.setOutputDir(projectPath + "/src/main/java" ); gc.setAuthor("lpc" ); gc.setOpen(false ); gc.setFileOverride(false ); gc.setIdType(IdType.ASSIGN_UUID); mpg.setGlobalConfig(gc); DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/myjpa?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false" ); dsc.setDriverName("com.mysql.cj.jdbc.Driver" ); dsc.setUsername("root" ); dsc.setPassword("123456" ); mpg.setDataSource(dsc); PackageConfig pc = new PackageConfig(); pc.setParent("com.xmx" ); pc.setEntity("entity" ); pc.setMapper("mapper" ); pc.setService("service" ); pc.setController("controller" ); mpg.setPackageInfo(pc); StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("student" ,"teacher" ); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true ); strategy.setRestControllerStyle(true ); strategy.setControllerMappingHyphenStyle(true ); strategy.setTablePrefix(pc.getModuleName() + "_" ); mpg.setStrategy(strategy); mpg.execute(); System.out.println(111111111 ); } }