MybatisPlus
版本冲突巨坑!!!
Mybatis-Plus依赖
springboot整合mybatisplus文件时,搭建程序时,不要勾选mybatis的的起步依赖,直接在搭建好的程序的pom.xml文件中添加mybatis-plus 依赖,注意spring-boot的版本如果是最新的,mybatis-plus的版本也必须是最新的,否则在调用BaseMyBatis方法时就会报错,无法运行
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
yml配置文件
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: 160250dgs
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-location: TliasStudy\src\main\java\com\itsen\mapper (mapper的相对路径)
#日志输出
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Mybatis单表的CRUD
- 新增
@Test
public void insertTest()
{
User user=new User("张三",23,"666@qq.com");
int result = userMapper.insert(user);
System.out.println(result);
System.out.println(user.getId());
}
- 删除
@Test
public void deleteTest()
{
// //根据id进行删除
// int result = userMapper.deleteById("1681587419472297985");
// System.out.println("result:"+result);
//传入集合批量删除
// List<Long> list = Arrays.asList(1L, 2L, 3L);
// int result = userMapper.deleteBatchIds(list);
// System.out.println("result:"+result);
//传入map来进行删除
Map<String,Object> map=new HashMap<>();
map.put("name","sandy");
map.put("age",21);
int result = userMapper.deleteByMap(map);
System.out.println("result:"+result);
}
- 修改
根据id进行修改
@Test
public void updateTest()
{
User user=new User();
user.setId(5L);
user.setAge(18);
user.setName("小花");
userMapper.updateById(user);
}
- 查询
@Test
public void selectTest()
{
//根据id查询用户信息
// User user = userMapper.selectById(1681645506614853633L);
// System.out.println(user);
//根据多个id查询多个用户信息
// List<Long> list = Arrays.asList(1681641507497021441L, 1681645506614853633L, 1681645629482741761L);
// List<User> userList = userMapper.selectBatchIds(list);
// userList.forEach(System.out::println);
// //根据map中的集合条件来进行查询
// Map<String,Object> userMap=new HashMap<>();
// userMap.put("name","张三");
// userMap.put("age",23);
// List<User> userList = userMapper.selectByMap(userMap);
// userList.forEach(System.out::println);
// selectList()方法进行查询
// List<User> userList = userMapper.selectList(null);
// userList.forEach(System.out::println);
//自定义xml映射文件进行查询
Map<String, Object> stringObjectMap = userMapper.selectMapById(1681645629482741761L);
System.out.println(stringObjectMap);
}
Service CRUD接口
举例:为表中插入多组数据
多组数据的插入仅在IService接口中有,BaseMapper接口中只有单条数据的插入方法
UserService接口代码
public interface UserService extends IService<User> {
}
UserServiceImpl接口实现类代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
}
插入多组数据测试代码
@Autowired
private UserService userService;
@Test
public void testInsertMore()
{
List<User> list=new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user =new User();
user.setName("sen"+i);
user.setAge(20+i);
list.add(user);
}
boolean b = userService.saveBatch(list);
System.out.println(b);
}
实体类与对应表的映射注解
@TableName(“表名”)
- 1.可以在实体类上@TableName(“表名”)
- 在.yml文件中添加配置,确定统一前缀,后缀与实体类名相同
配置代码如下
global-config:
db-config:
table-prefix: t_
@TableId
@TableId
雪花算法默认只给属性名为id的值进行赋值,加入将属性名id改为uid就不会给id进行赋值,解决方法就是在想成为主键的属性上加上@TableId 注解进行修饰
@TableId注解中的value和type属性
当实体类中的属性名与表中的字段名不一样的时候,需要使用value属性进行绑定,主键id自动生成策略为雪花算法,也是常用的算法,如果想要使用其他的主键生成策略可以使用type属性进行指定,如图中的AUTO为自动递增
将主键生成策略换成Auto需要将数据库进行截断操作
注意:
- 1.如果主动设置了id雪花算法就不会自动生成id
- 2也可以在yml文件中设置统一的主键生成策略
雪花算法
简单了解就行
TableField(“指定属性所对应的字段名”)
@TableLogic
逻辑删除:假删除,将对应数据中代表是否被删除的字段的状态修改为"被删除状态",之后数据库中仍能依旧看到此条数据记录
使用场景:可以进行数据恢复
操作
- 给表设置表示删除状态的字段,默认值为0表示成功,
- 在实体类中添加删除状态的属性,用@TableLogic来进行修饰
这样再进行删除操作的时候就不是delete真实删除了,而是update修改操作,将删除状态默认改为1,表示删除,查询的时候只会默认查询删除状态字段默认值为0 的数据
Wapper条件构造器
举例:
组装查询条件
@Test
public void wapperTest()
{
//利用条件构造器查询用户名包含s,年龄在20到30之间的用户信息
//sql语句SELECT id,name,age,email,delete_id FROM user WHERE delete_id=0 AND (name LIKE ? AND age BETWEEN ? AND ?)
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.like("name","s")
.between("age",20,30);
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
用传入条件构造器和实体类进行修改操作
@Test
public void updateQueryWrapper()
{
//将年龄大于20并且用户名中包含s或邮箱为null的用户信息修改
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.gt("age",20)
.like("name","xiao")
.or()
.isNull("email");
User user=new User();
user.setName("小明");
user.setEmail("jfkdjfl@.com");
int update = userMapper.update(user, queryWrapper);
System.out.println("result:"+update);
}
查询指定的字段的字段
@Test
public void selecTest()
{
//select方法查询指定对应的查询字段
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.select("name","age","email");
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);
}
构建子查询inSql(“字段名”,“子查询语句”)
UpdateWrapper修改条件构造器
@Test
public void updateWrapperTest()
{
//将用户名中包含有"小"并且(年龄大于20或邮箱为null)的用户信息修改
UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
updateWrapper.like("name","小")
.and(i->i.gt("age",20).or().isNull("email"));
updateWrapper.set("name","小黑").set("email","abc@qq.com");
int result = userMapper.update(null, updateWrapper);
System.out.println("result:"+result);
}
对服务端传来的条件添加判断条件进行判断来组装条件
LambdaQueryWrapper条件构造器
LambdaQueryWrapper条件构造器
lambda条件构造器与普通的条件构造器区别不大,唯一的区别就是lambda条件构造器能通过实体类来调用属性就行操作,而普通的需要写表中的字段名字符串来进行操作
插件
分页插件
解决报错: mybatis-plus分页selectPage报错org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
一定要在.yml文件配置中加一下培配置扫描mapper层
mapper-location: TliasStudy\src\main\java\com\itsen\mapper (mapper的相对路径)
后面即使删除这个扫描mapper包的配置idea 也会默认找到扫描这个包
配置分页插件类
@Configuration
@MapperScan("com.itsen.mybatisplus.mapper")
public class MybatisPlusConfig {
@Primary
@Bean
public MybatisPlusInterceptor PlusConfig()
{
MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
注意分页插件类的方法名不能写成类名的首字母小写,因为springboot自动配置了一个,使用时会报错bean重复定义
page中有一系列的方法,下图仅展示一部分
自定义分页查询方法
xml映射文件中代码
<select id="selectPageVo" resultType="User">
select id, name, age, email from user where age > #{age}
</select>
测试代码
@Test
public void selectPageTest()
{
Page<User> page =new Page<>(1,3);
Page<User> userPage = userMapper.selectPageVo(page, 20);
System.out.println(userPage);
}
自定义分页查询没有自动判断分页查询
乐观锁
步骤:
- 1.在对应的实体类字段上加上@Version
- 2.在插件配置类中添加乐观锁插件
乐观锁控制修改冲突
通用枚举
枚举类
插件配置中进行配置扫描通用枚举的包
代码生成器
依赖
<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>
自己创一个配置类,配置类代码是固定的,配置类的代码如下
public class FastGeneratorTest {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false", "root", "160250dgs")
.globalConfig(builder -> {
builder.author("baomidou") // 设置作者
// .enableSwagger() // 开启 swagger 模式
//.fileOverride() // 覆盖已生成文件
.outputDir("E://javaCode//mybatis-plus//mybatis-plus"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.itsen") // 设置父包名
.moduleName("mybatisplus") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, "E://javaCode//mybatis-plus//mybatis-plus")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("user") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
多数据源
yml文件配置
指定service层操作的数据源
@DS()也可以添加在方法上来进行修饰,指定某一个方法所对应的数据源
读写分离:写是作用于主数据源,读数据是作用于从数据源
MyBatisX插件
可以使用MybatisX插件通过表来生成代码
代码生成流程图
-
1
-
2
- 3
插件自动生成映射文件中的代码