MyBatisPlus
入门#
安装MySQL依赖的时候出现问题,可以通过添加版本号的方式解决。参考链接
lombok依赖可以用于简化实体类的开发,使用前需要下载lombok插件。
要十分注意版本的适配问题,目前比较推荐使用SpringBoot2版本。
MyBatisPlus生成Sql语句是根据实体类及其属性。
在删除的时候传入id超过int类型的时候,可以在数字后面加上L
说明是long型的数据。
依赖文件#
<?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.7.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.atguigu</groupId>
<artifactId>MyBatisPlus-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>MyBatisPlus-demo</name>
<description>MyBatisPlus-demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置application.yml#
- 驱动类driver-class-name:spring boot.2.0(内置jdbc5驱动),驱动类使用:
driver-class-name:com.mysql.jdbc.Driver
。spring boot2.1及以上(内置jdbc8驱动),驱动类使用:driver-class-name:com.mysql.cj.jdbc.Driver
。否则运行测试用例的时候会有WARN信息。 - 连接地址url MySQL5.7版本的
url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
。MySQL8.0版本的url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
。否则运行测试用例报告如下错误:java.sql.SQLException:The server time zone value 'ODutexE+a'is unrecognized or represents more
。 - 注意冒号后面空一格。
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
username: root
password: 159123zxc
SpringBoot启动类#
启动类中指定Mapper所在位置。
@SpringBootApplication
@MapperScan("com.atguigu.mybatisplusdemo.Mapper")
public class MyBatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MyBatisPlusDemoApplication.class, args);
}
}
POJO实体类#
使用lombok依赖后,可以直接使用@Data
注解实现无参构造、get和set方法还有equal和hash方法的实现。
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
Mapper接口#
Mapper接口实现BaseMapper接口后就可以使用里面的方法了。
public interface UserMapper extends BaseMapper<User> {
}
测试文件#
@SpringBootTest
public class MyBatisPlusTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList(){
List<User> list = userMapper.selectList(null);
list.forEach(System.out::println);
}
}
批量删除和批量查询#
//批量删除
public void testDelete(){
List<Long> idLists = Arrays.asList(1L, 2L, 3L);
int result = userMapper.deleteBatchIds(idLists);
}
//批量添加
public void testSelect(){
List<Long> idLists = Arrays.asList(1L, 2L, 3L);
List<User> result = userMapper.selectBatchIds(idLists);
result.forEach(System.out::println);
}
通用service#
通用Service CRUD封装Service接口,进一步封装CRUD采用get查询单行
,remove删除
,Iist查询集合
,page分页
前缀命名方式区分Mapper
层避免混淆。
MyBatis-Plus中有一个接口IService
和其实现类Servicelmpl
,封装了常见的业务层逻辑。
UserService#
public interface UserService extends IService<User> {
}
UserServiceImpl#
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
测试#
public class MyBatisPlusServiceTest {
@Autowired
private UserService userService;
@Test
public void testGetCount(){
long count = userService.count();
System.out.println("总记录数:"+count);
}
}
批量添加#
public void testInsertMore(){
List<User> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
User user = new User();
user.setName("ybc"+i);
user.setAge(20+i);
list.add(user);
}
boolean b = userService.saveBatch(list);
System.out.println(b);
}
常用注解#
雪花算法#
雪花算法能够保证不同表的主键的不重复性,以及相同表的主键的有序性,非常适合分布式系统。
雪花算法总共64bit(一个long型),优点是整体上按照时间递增,并且整个分布式系统内不会产生ID碰撞,并且效率较高。
@TableName#
作用于实体类中,用于解决实体类名和数据库表名不一致的问题。
@TableName("t_user")
public class User {
private Long id;
private String name;
}
全局配置#
在application.yml
文件中配置统一的前缀,统一的主键生成策略。
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#配置mybatisPlus的全局配置
global-config:
db-config:
table-prefix: t_
id-type: auto
@TableId#
MyBatisPlus默认的主键是id,如果需要修改主键,只需将该注解加到属性上,将该属性指定为主键。
@TableId注解的value属性用于解决数据库字段名不一致的问题,type属性是设置主键策略,默认是雪花算法,可以设置为自增,需要先使用truncate table users;
命令截断原来的表,并设置为自增才会有效。值得注意的是截断和清空表是不一样的。
public class User {
@TableId(value = "uid",type = IdType.AUTO)
private Long id;
private String name;
}
@TableField#
MyBatisPlus会自动将下划线和驼峰命名进行转换。如果是其他情况则需要使用该字段来指定属性所对应的字段名。
public class User {
private Long id;
@TableField("user_name")
private String name;
}
@TableLogic#
逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录。
在添加了该注解后,删除是假删除,只是将该位置的值设置为1,可以在数据库中看到该数据。
public class User {
private String email;
@TableLogic()
private Integer isDeleted;
}
条件构造器#
Wrapper#
- Wrapper:条件构造器抽象类,最顶端父类
- AbstractWrapper:用于查询条件封装,生成sql的where条件。
- QueryWrapper:查询和删除条件封装
- UpdateWrapper:更新条件封装
- AbstractLambdaWrapper:使用Lambda语法
- LambdaQueryWrapper:用于Lambda语法使用的查询Wrapper
- LambdaUpdateWrapper:Lambda更新封装Wrapper
- AbstractWrapper:用于查询条件封装,生成sql的where条件。
组装查询条件#
public void test01(){
//查询用户名包含a,年龄在20到30之间,邮箱信息不为uLL的用户信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name","a")
.between("age",20,30)
.isNotNull("email");
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
条件优先级#
lambda表达式中的条件优先执行。
public void test05(){
//将用户名中包含有a并且(年龄大于20或邮箱为NULL)的用户信息修改
//lambda表达式中的条件优先执行
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name","a")
.and(i->i.gt("age",20).or().isNull("email"));
User user = new User();
user.setName("小红");
user.setEmail("test@qq.com");
int result = userMapper.update(user, queryWrapper);
System.out.println("result"+result);
}
子查询#
public void test07(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("uid","select uid from t_user where uid <=100");
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
修改数据#
UpdateWrapper可以设置查询条件和设置需要修改的内容。
public void test08(){
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.like("user_name","a")
.and(i->i.gt("age",20).or().isNull("email"));
updateWrapper.set("user_name","小黑").set("email","abc@qq.com");
int result = userMapper.update(null, updateWrapper);
System.out.println("result"+result);
}
使用condition组装条件#
在方法在填入条件,只有在满足条件后才会进行组装。
public void test09(){
String username = "";
Integer ageBegin = 20;
Integer ageEnd = 30;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username),"username",username)
.ge(ageBegin!=null,"age",ageBegin)
.le(ageEnd!=null,"age",ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
使用LambdaQueryWrapper#
因为类的属性名可能与数据库的字段名不一致,所以使用lambda表达式可以减少写错属性的情况。
public void test11(){
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
.ge(ageBegin!=null,User::getAge,ageBegin)
.le(ageEnd!=null,User::getAge,ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
插件#
分页插件#
配置文件#
@Configuration
@MapperScan("com.atguigu.mybatisplusdemo.Mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//增加分页监视器,并指定数据库类型
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
分页使用#
public void testPage(){
//指定起始页和每页展示的条数
Page<User> page = new Page<>(1,3);
userMapper.selectPage(page,null);
}
自定义分页#
自定义分页只需设置函数的第一个参数和返回值为Page<T>
类型,则可以自动完成分页操作。
<!-- Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
<select id="selectPageVo" resultType="User">
select uid,user_name,age,email from t_user where age > #{age}
</select>
乐观锁插件#
乐观锁实现步骤:在数据库中添加version字段,取出记录时,获取当前version,更新时,version+1,如果where语句中的version版本不对,则更新失败。
在配置文件中的监视器增加乐观锁插件:interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
,并且在实体类的version属性上添加@Version
注解。
通用枚举#
当使用枚举类型时需要添加@EnumValue
注解,将注解所标识的属性的值存储到数据库中,还需要在application.yml文件中配置扫描通用枚举的包:type-enums-package: com.atguigu.mybatisplusdemo.enums
。
代码生成器#
引入依赖#
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
快速生成#
public class FastAutoGeneratorTest {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false", "root", "159123zxc")
.globalConfig(builder -> {
builder.author("xiqin") // 设置作者
//.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://mybatis_plus"); // 指定输出目录
})
// .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
// int typeCode = metaInfo.getJdbcType().TYPE_CODE;
// if (typeCode == Types.SMALLINT) {
// // 自定义类型转换
// return DbColumnType.INTEGER;
// }
// return typeRegistry.getColumnType(metaInfo);
//
// }))
.packageConfig(builder -> {
builder.parent("com.atguigu") // 设置父包名
.moduleName("MyBatisPlusdemo") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_user") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
MyBatisX插件#
MyBatis-Plus为我们提供了强大的mapper和service模版,能够大大的提高开发效率。但是在真正开发过程中,MyBatis-Plus并不能为我们解决所有问题,例如一些复杂的SQL,多表联查,我们就需要自己去编写代码和SQL语句,这个时候可以使用MyBatisX插件MyBatisX,一款基于IDEA的快速开发插件,为效率而生。
点击小鸟图标可以在接口和对应的xml文件之间快速跳转。
使用的时候首先登录idea自带的database,然后打开对应的表,右键选择MyBatisX-Generator,然后填写参数即可。
编写方法也十分方便,只需在接口中声明有小鸟图标的方法,然后ALT+enter
选择生成即可。
作者:xiqin
出处:https://www.cnblogs.com/xiqin-huang/p/17898649.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通