赞
踩
Mybatis本来就是简化JDBC操作的!
官网:https://baomidou.com/ MybatisPlus,为简化开发而生
MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
建立数据库和表
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) ); -- 真实开发中,version(乐观锁),deleted(逻辑删除)、gmt_create、gem_mo 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');
导入依赖
<!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mybatis-plus 是自己开发的,非官方的!--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.1</version> </dependency>
application.properties
# mysql 5 驱动不同 com.mysql.jdbc.Driver
# mysql 8 驱动不同 com.mysql.cj.jdbc.Driver、需要增加时区的配置
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
application.yaml
# 配置日志(默认控制台输出)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
编写实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private int age;
private String email;
}
主入口扫描所有mapper接口
@MapperScan("com.luffy.mybatisplus.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
编写测试类
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
SnowFlake 中文意思为雪花,故称为雪花算法。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID。在2014年开源 scala 语言版本。
优点:
缺点:
雪花算法的原理就是生成一个的 64 位比特位的 long 类型的唯一 id。
@TableId注解是专门用在主键上的注解,如果数据库中的主键字段名和实体中的属性名,不一样且不是驼峰之类的对应关系,可以在实体中表示主键的属性上加@Tableid注解,并指定@Tableid注解的value属性值为表中主键的字段名既可以对应上。
使用方式
参数类型 | 作用 |
---|---|
AUTO | 数据库自增 |
NONE | MP set主键,雪花算法实现 |
INPUT | 需要手动赋值 |
ASSIGN_ID | MP分配ID,Long、Integer、String |
ASSIGN_UUID | 分配UUID,String |
实例
// 对应数据库的主键(uuid,自增id,雪花算法,redis,zookeeper)
@TableId(type = IdType.AUTO)
private Long id;
创建时间、修改时间!这些个操作一遍都是自动化完成,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create\gmt_modified几乎所有的表都要配置上!而且需要自动化
方式一:数据库级别 (这种方法不支持,因为大公司不会让改动数据库)
在表中新增字段 create_time 、update_time(默认CURRENT_TIMESIAMP)
注意:mysql5.5的日期函数是now()
mysql5.6以上的支持CURRENT_TIMESIAMP
方式二:代码级别
实体类上的属性需要增加注解@TableField
把数据库的默认值删除
实体类注解例子
//创建时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//更新时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
编写处理器来处理这个注释
@Slf4j @Component //把处理器加到IOC容器中 public class MyMetaObjectHandler implements MetaObjectHandler { //插入时的填充策略 @Override public void insertFill(MetaObject metaObject) { log.info("Start insert fill.... "); this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } //更新时的填充策略 @Override public void updateFill(MetaObject metaObject) { log.info("Start update fill.... "); this.setFieldValByName("updateTime",new Date(),metaObject); } }
乐观锁:顾名思义十分乐观,它总是被认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新测试
悲观锁:顾名思义十分悲观,它总是出现问题,无论干什么都会上锁!再去操作!
乐观锁执行流程
测试乐观锁
数据库增加Version字段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Z4iCnPu-1662874822525)(C:\Users\22341\AppData\Roaming\Typora\typora-user-images\image-20220906162216347.png)]
实体类对应数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K1HgKKX0-1662874822525)(C:\Users\22341\AppData\Roaming\Typora\typora-user-images\image-20220906162239568.png)]
编写乐观锁配置类
@MapperScan("com.luffy.mybatisplus.mapper") @Configuration//配置类 @EnableTransactionManagement//事务 public class MyBatisPlusConfig{ //mybatisPlus3.4.3.1写法 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //注册乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }
测试
//测试乐观锁 线程下 更新一次后 version就会变成2 @Test void OptimisticLocker() { //单线程 //查询用户信息 User user=userMapper.selectById(1L); //修改用户信息 user.setName("xioajj"); user.setAge(21); //执行更新操作 userMapper.updateById(user); } //测试乐观锁 多线程下 @Test void OptimisticLockerD() { //第一线程 //查询用户信息 User user=userMapper.selectById(1L); //修改用户信息 user.setName("xioa2"); user.setAge(21); //第二线程 模拟另外一个线程执行插队操作 //查询用户信息 User user1=userMapper.selectById(1L); //修改用户信息 user1.setName("xiao3"); user1.setAge(21); userMapper.updateById(user1); //自旋锁来多次尝试提交 userMapper.updateById(user); //如果没有乐观锁 就会覆盖插队线程的值 }
//查询全部 @Test void contextLoads() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } //测试批量查询 @Test public void testSelectByBatchId(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); } //按条件查询之一使用map操作 @Test public void testSelectByBatchIds(){ HashMap<String,Object> hashMap = new HashMap<>(); hashMap.put("name","我是路飞"); hashMap.put("age","19"); List<User> users = userMapper.selectByMap(hashMap); users.forEach(System.out::println); }
MyBatisPlusConfig类
@MapperScan("com.luffy.mybatisplus.mapper") @Configuration//配置类 @EnableTransactionManagement//事务 public class MyBatisPlusConfig{ //mybatisPlus3.4.3.1写法 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //注册乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); //分页插件 我们使用的是mysql数据库 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
测试方法
//测试分页查询
@Test
public void testPage(){
Page<User> userPage = new Page<>(1,5);
userMapper.selectPage(userPage,null);
//获取查出的记录
List<User> records = userPage.getRecords();
records.forEach(System.out::println);
//获取总数
System.out.println(userPage.getTotal());
}
//测试删除 @Test public void testDeleteById(){ userMapper.deleteById(1L); } //通过id批量删除 @Test public void testDeleteBatchId(){ userMapper.deleteBatchIds(Arrays.asList("1566981460006752259","1566981460006752260")); } //通过map删除 @Test public void testDeleteMap(){ HashMap<String,Object> hashMap = new HashMap<>(); hashMap.put("name","xiao3"); userMapper.deleteByMap(hashMap); }
管理员可以查看被删除的记录!防止数据的丢失!类似于回收站!
物理删除:从数据库中直接移除
逻辑删除:在数据库中没有被移除,而是通过一个变量让他生效!deleted=0 --> deleted=1
在数据库表中增加一个deleted字段(默认值为0)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-McFXEjSX-1662874822526)(C:\Users\22341\AppData\Roaming\Typora\typora-user-images\image-20220911111424437.png)]
实体类中添加属性
@TableLogic // 逻辑删除
private Integer deleted;
application.yaml
mybatis-plus:
# 配置逻辑删除
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置实体类字段上加上@TableLogic注解)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
删除测试(走的是更新操作,不是删除操作,会将deleted字段设置为1,逻辑上删除)
//测试删除
@Test
public void testDeleteById(){
userMapper.deleteById(1L);
}
MP也提供了性能分析插件,如果超过这个时间就停止运行!(测试慢sql)
该插件只用于开发环境,不建议生产环境使用
旧版本使用方法(新版本另寻)
使用步骤
导入插件
/**
* SQL执行效率插件
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);// ms 设置sql执行的最大时间,如果超过就停止
performanceInterceptor.setFormat(true);
return new PerformanceInterceptor();
}
测试
@Test
void contextLoads(){
//参数是一个Wrapper,条件结构器,这里先不用,填null
//查询全部用户
List<User> users =userMapper.selectList(null);
user.forEach(System.out::println);
}
输出
wrapper(我们写一些复杂的sql就可以使用它来代替)
@SpringBootTest public class WrapperTest { @Autowired private UserMapper userMapper; //查询name和邮箱不为空,年龄大于12岁的用户 @Test void testGe() { QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.isNotNull("name").isNotNull("email").ge("age",12); userMapper.selectList(userQueryWrapper).forEach(System.out::println); } //查询名字为我是索隆 @Test public void testEq() { QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("name","我是索隆"); System.out.println(userMapper.selectOne(userQueryWrapper)); } //查询年龄在10-20岁之间 @Test void testBetWeen() { QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.between("age",10,20); userMapper.selectList(userQueryWrapper); } //模糊查询 @Test public void testLike() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.likeLeft("name", "索隆"); //name like '%索隆' List<User> userList = this.userMapper.selectList(wrapper); for (User user : userList) { System.out.println(user); } } //内查询(可以多表联查) @Test public void testInSql() { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.inSql("id", "select id from user where id < 5"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } //排序 @Test public void testOrderBy() { QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.orderByDesc("id"); userMapper.selectList(userQueryWrapper).forEach(System.out::println); } }
好离谱
写完前端页面、数据库,使用代码生成器一键生成所有后端初始代码
pom.xml
<!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mybatis-plus 是自己开发的,非官方的!--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.1</version> </dependency> <!--MybatisPlus代码生成器 依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.1</version> </dependency> <!--velocity依赖--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.0</version> </dependency> <!--swagger依赖--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> <!--3.0.7版本移除 对 mybatis-plus-generator 包的依赖,自己按需引入,尽在还需要导入模板依赖,--> <!--generator依赖--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> <scope>test</scope> </dependency>
生成代码
public class LuffyCode { 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("Luffy");//设置作者 gc.setOpen(false);//是否打开资源管理器 gc.setFileOverride(false);// 是否覆盖原来生成的 gc.setServiceName("%sService");// 去Service的I前缀 gc.setIdType(IdType.ASSIGN_ID);//雪花算法自动生成id gc.setDateType(DateType.ONLY_DATE);//日期格式 gc.setSwagger2(true);//配置swagger mpg.setGlobalConfig(gc);//全局配置 //2、设置数据源 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/mp?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("root"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc);//设置全局配置 //3、包的配置 PackageConfig pc = new PackageConfig(); //只需要改实体类名字 和包名 还有 数据库配置即可 pc.setModuleName("MybatisPlus"); pc.setParent("com.luffy"); pc.setEntity("entity"); pc.setMapper("mapper"); pc.setService("service"); pc.setController("controller"); mpg.setPackageInfo(pc);//全局配置 //4、策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user");//设置要映射的表名(逗号多配置) strategy.setNaming(NamingStrategy.underline_to_camel);//下划线转驼峰命名 strategy.setColumnNaming(NamingStrategy.underline_to_camel);//下划线转驼峰命名 strategy.setEntityLombokModel(true);// 自动lombok; strategy.setLogicDeleteFieldName("deleted");//逻辑删除字段 // 时间自动填充配置 TableFill createTime = new TableFill("create_time", FieldFill.INSERT); TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE); ArrayList<TableFill> tableFills = new ArrayList<>(); tableFills.add(createTime); tableFills.add(updateTime); strategy.setTableFillList(tableFills); // 乐观锁 strategy.setVersionFieldName("version"); strategy.setRestControllerStyle(true);//controller是Restful风格 strategy.setControllerMappingHyphenStyle(true);// localhost:8080/hello_id_2 mpg.setStrategy(strategy);//全局配置 //执行全局配置 mpg.execute(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。