注意:尽量不要同时导入mybatis和mybatis-plus
二、基础的增删改查构建、创建时间更新时间、乐观锁、逻辑删除org.springframework.boot spring-boot-starter-webcom.baomidou mybatis-plus-boot-starter3.0.5 mysql mysql-connector-javaruntime org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest p6spy p6spy3.9.1 org.apache.velocity velocity-engine-core2.0 io.swagger swagger-annotations1.6.2
以下没有写Service层,仅仅用来学习Mybatis-plus,测试封装的方法!!!
1. 实体类注解使用说明:注解 | MyBatis-Plus
① 乐观锁version
当要更新一条记录的时候,希望这条记录没有被别人更新,从而实现线程安全的数据更新。乐观锁的实现,通过增加一个字段,比如version,来记录每次的更新。
②逻辑删除
物理删除:从数据库中直接删除
逻辑删除:在数据库中没有删除,而是通过一个变量来让他失效。类似:回收站!逻辑删除的字段,查询时显示为空,不存在!其实数据库中仍显示存在该数据。类似回收站(查询时会过滤被逻辑删除的字段);数据库字段默认为0;删除设置为1
逻辑删除好处:管理员可以查看被删除的记录,防止数据的丢失。
package com.example.demo09.pojo; import com.baomidou.mybatisplus.annotation.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @AllArgsConstructor @NoArgsConstructor public class User { @TableId(type = IdType.AUTO)//主键自增 private Long id; private String name; private Integer age; private String email; @Version//乐观锁注解 private Integer version; @TableLogic//逻辑删除 private Integer deleted; //字段填充内容 @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; }2. Dao层
package com.example.demo09.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.demo09.pojo.User; import org.springframework.stereotype.Repository; @Repository public interface UserMapper extends BaseMapper3. 配置创建时间、更新时间 方式一:数据库新增字段(类型:datetime):不推荐{//所有的CRUD操作都已经编写完成,不需要再配置一大堆文件 }
方法二:代码级别:推荐!!!
数据库不进行任何配置,只添加字段
package com.example.demo09.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.util.Date; @Slf4j//打印日志 @Component//将处理器加到IOC容器中 public class MyMetaObjectHandler implements MetaObjectHandler { //插入时的填充策略 @Override public void insertFill(MetaObject metaObject) { log.info("start insrt fill..."); this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } //更新时的填充策略 @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",new Date(),metaObject); } }4. 配置类
package com.example.demo09.config; import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.transaction.annotation.EnableTransactionManagement; @MapperScan("com.example.demo09.mapper")//扫描Mapper文件夹 @EnableTransactionManagement//自动加载事务 @Configuration public class MyBatisPlusConfig { //注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInnerInterceptor() { return new OptimisticLockerInterceptor(); } //注册分页插件 @Bean public PaginationInterceptor paginationInterceptor(){ return new PaginationInterceptor(); } //逻辑删除组件 @Bean public ISqlInjector sqlInjector(){ return new LogicSqlInjector(); } @Bean @Profile({"dev","test"})//设置dev,test环境开启,保证我们的效率 public PerformanceInterceptor performanceInterceptor(){ PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); performanceInterceptor.setMaxTime(100);//ms;设置sql执行的最大时间。如果超过了就不执行 performanceInterceptor.setFormat(true);//开启格式化支持,让sql语句看的更清楚 return performanceInterceptor; } }5. application.properties
#设置开发环境 spring.profiles.active=dev spring.datasource.username=root spring.datasource.password=123456 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #配置日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl #配置逻辑删除 mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=06. 测试
①基础的增删改查,直接用Mybatis-plus中自带的
package com.example.demo09; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.example.demo09.mapper.UserMapper; import com.example.demo09.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.Arrays; import java.util.HashMap; import java.util.List; @SpringBootTest class Demo09ApplicationTests { //继承了BaseMapper,所有的方法来自于父类。也可以编写自己的扩展方法! @Autowired private UserMapper userMapper; @Test void contextLoads() { //参数wrapper,条件构造器,不用 写null //查询全部的用户 //new QueryWrapper() List users = userMapper.selectList(null); users.forEach(System.out::println); } //查询前三个用户;测试批量查询! @Test public void testSelectByBatchId(){ List users = userMapper.selectBatchIds(Arrays.asList(1, 2)); users.forEach(System.out::println); } //测试查询 @Test public void testSelectById(){ User user = userMapper.selectById(1582629016255004675L); System.out.println(user); } //条件查询:map @Test public void testSelectByMap(){ HashMap map = new HashMap<>(); //自定义查询 map.put("name","tw");//可以任意条件,多个也行 List users = userMapper.selectByMap(map); users.forEach(System.out::println); } //测试分页查询 @Test public void testPage(){ Page page = new Page<>(1,5);//查询第一页当前五个数据 userMapper.selectPage(page,null); page.getRecords().forEach(System.out::println); System.out.println(page.getTotal());//查看总共多少数据 } @Test public void testInsert(){ User user = new User(); user.setName("黑河"); user.setAge(13); user.setEmail("127@qq.com"); int result = userMapper.insert(user);//自动生成id System.out.println(result); System.out.println("======="); System.out.println(user); } @Test public void testUpdate(){ User user = new User(); user.setId(1582629016255004675L); user.setName("小明"); int i = userMapper.updateById(user); System.out.println(i); } //测试删除 @Test public void testDeleteById(){ userMapper.deleteById(1582629016255004675L); } //批量删除 @Test public void testDeleteBatchId(){ userMapper.deleteBatchIds(Arrays.asList(2L,5L,6L)); } //通过条件删除:map删除 @Test public void testDeleteByMap(){ HashMap map = new HashMap<>(); map.put("name","小红"); userMapper.deleteByMap(map); } //测试乐观锁成功: @Test public void testOptimisticlocker(){ //1.查询用户信息 User user = userMapper.selectById(1L); //2.修改用户信息 user.setName("jkk"); user.setEmail("122@qq.com"); //3.执行更新操作 userMapper.updateById(user); } @Test //测试乐观锁失败:多线程下 public void testOptimisticlockerFail(){ //线程1: User user1 = userMapper.selectById(1L); user1.setName("jkk1"); user1.setEmail("1221@qq.com");//这时线程1还未执行更新操作 //线程2:模拟另一个线程执行插队操作 User user2 = userMapper.selectById(1L); user2.setName("jkk2"); user2.setEmail("1222@qq.com"); userMapper.updateById(user2); userMapper.updateById(user1);//如果没有乐观锁就会覆盖另一个的值 } }
② 复杂的增删改查,借助Wrapper条件
package com.example.demo09; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.example.demo09.mapper.UserMapper; import com.example.demo09.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest public class WrapperTest { @Autowired private UserMapper userMapper; @Test void contextLoads() { //查询name,email不为空,年龄大于等于12的用户 QueryWrapper三、代码自动生成器wrapper = new QueryWrapper<>(); wrapper .isNotNull("name") .isNotNull("email") .ge("age",12);//g:大于;e:等于 userMapper.selectList(wrapper).forEach(System.out::println); } @Test void test2(){ //查询名字为小明 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("name","黑河"); User user = userMapper.selectOne(wrapper);//selectOne:查询一个用户;查询多个时用:List或Map System.out.println(user); } @Test void test3(){ //查询年龄在20~30岁之间的 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.between("age",13,20);//区间 Integer count = userMapper.selectCount(wrapper);//查询结果数 System.out.println(count); } }
根据数据库的表,进行配置第四步的
strategy.setInclude("user")//user表
只改这一个地方就行!
package com.example.demo09; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.po.TableFill; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import java.util.ArrayList; //代码自动生成器 public class WskCode { public static void main(String[] args) { //我们需要构建一个代码生成器对象 AutoGenerator mpg = new AutoGenerator(); //怎么样去执行,配置策略 //1、全局配置 GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir");//获取当前目录 gc.setOutputDir(projectPath+"/src/main/java");//输出到哪个目录 gc.setAuthor("wsk"); gc.setOpen(false); gc.setFileOverride(false);//是否覆盖 gc.setServiceName("%sService");//去Service的I前缀 gc.setIdType(IdType.ID_WORKER); gc.setDateType(DateType.ONLY_DATE); gc.setSwagger2(true); mpg.setGlobalConfig(gc); //2、设置数据源 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUsername("root"); dsc.setPassword("123456"); dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc); //3、包的配置 PackageConfig pc = new PackageConfig(); pc.setModuleName("study"); pc.setParent("com.wsk"); pc.setEntity("pojo"); pc.setMapper("mapper"); pc.setService("service"); pc.setController("controller"); mpg.setPackageInfo(pc); //4、策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user");//设置要映射的表名,只需改这里即可;我只有一个user表 strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true);//是否使用lombok开启注解 strategy.setLogicDeleteFieldName("deleted"); //自动填充配置 TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT); TableFill gmtUpdate = new TableFill("gmt_update", FieldFill.INSERT_UPDATE); ArrayListtableFills = new ArrayList<>(); tableFills.add(gmtCreate); tableFills.add(gmtUpdate); strategy.setTableFillList(tableFills); //乐观锁配置 strategy.setVersionFieldName("version"); strategy.setRestControllerStyle(true);//开启驼峰命名 strategy.setControllerMappingHyphenStyle(true);//localhost:8080/hello_id_2 mpg.setStrategy(strategy); mpg.execute();//执行 } }