Mybatis-plus:对Mybatis做增强,简化开发
DROP TABLE IF EXISTS user;
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)
);
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
dependencies>
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC
username: root
password: 12341234
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl //配置日志
创建实体类
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
创建Mapper接口,继承BaseMapper<泛型>。
在主启动类中加入@MapperScan(“全限定名”),扫描Mapper接口
@SpringBootTest
class MpdemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
}
}
//测试结果:
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
Idea在第一次启动的时候会将代码编译,启动较慢!
代码操作:
@Test
public void addUser(){
User user = new User();
user.setName("Lucy"); //未设置主键值
user.setAge(18);
user.setEmail("[email protected]");
int insert = userMapper.insert(user);
}
通过日志查看执行结果
==> Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1329331831785492482(Long), Lucy(String), 18(Integer), [email protected](String)
<== Updates: 1
ID生成策略具体参考这篇文章:https://www.cnblogs.com/haoxinyue/p/5208136.html
自动增长:AUTO_INCREMENT
UUID:每次生成随机唯一的值
Redis实现
mp自带策略 :snowflake算法
在实体类主键ID上添加注解如下
@Data
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
//AUTO:自动增长
//INPUT:设置id值
//NONE:输入
//ASSGIN_UUID:随机生成值
代码操作:
@Test
public void updateUser(){
User user = new User();
user.setId(2L);
user.setAge(40);
userMapper.updateById(user);
}
通过日志查看执行结果:
==> Preparing: UPDATE user SET age=? WHERE id=?
==> Parameters: 40(Integer), 2(Long)
<== Updates: 1
不需要set到对象里面的值,使用mp方式实现数据添加
准备工作:
1、表中添加两个字段
create_time、update_time
2、添加实体类属性
具体实现过程:
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
创建类,实现接口MetaObjectHandler,并实现方法
//注册到容器中
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//使用mp实现添加方法,该方法执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//使用mp实现修改方法,该方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
丢失更新:多个人修改同一条数据的时候,最后一个提交事务的提交数据会覆盖前面的数据。
乐观锁实现方式:
案例操作:
在数据库中加入version字段
实体类添加version字段,并添加@version注解
@Version
private Integer version;
配置乐观锁插件到spring容器
//乐观锁插件
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
return new OptimisticLockerInnerInterceptor();
}
用自动填充添加version初始值
this.setFieldValByName("version",1,metaObject);
测试结果:
//测试乐观锁,一定要先查再改
@Test
public void testOptimisticLocker(){
User user = userMapper.selectById(1329347964622127105L);
user.setAge(235);
userMapper.updateById(user);
}
version结果+1
@Test
public void testSelectDemo1(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));//传入集合
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSelectDemo2(){
HashMap<String,Object> map = new HashMap<>();
map.put("name","Jone");//传入键值对作为条件
map.put("age","18");
List<User> users = userMapper.selectByMap(map);
for (User user : users) {
System.out.println(user);
}
}
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor page = new PaginationInterceptor();
page.setDialectType("mysql");
return page;
}
@Test
public void testPage(){
//传入两个参数:当前页和每页显示记录数
Page<User> page = new Page<>(1, 3);
//调用mp分页查询方法
//调用mp分页查询过程中,底层封装
//把分页所有数据封装到page中
userMapper.selectPage(page,null);
System.out.println(page.getCurrent()); //获取当前页
System.out.println(page.getRecords()); //每页数据List集合
System.out.println(page.getSize()); //每页显示记录数
System.out.println(page.getTotal()); //总记录数
System.out.println(page.getPages()); //总页数
System.out.println(page.hasNext()); //是否有下一页
System.out.println(page.hasPrevious()); //是否有上一页
}
日志打印:
==> Preparing: SELECT COUNT(1) FROM user
==> Parameters:
<== Columns: COUNT(1)
<== Row: 7
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,? //这里有limit查询
==> Parameters: 3(Long), 3(Long)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 4, Sandy, 21, test4@baomidou.com, null, null, null
<== Row: 5, Billie, 24, test5@baomidou.com, null, null, null
<== Row: 7, Lisa, 235, 412345@qq.com, 2020-11-19 08:37:43, 2020-11-19 09:05:35, 1
<== Total: 3
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@314a31b0]
2
[User{
id=4, name='Sandy', age=21, email='[email protected]', createTime=null, updateTime=null, version=null}, User{
id=5, name='Billie', age=24, email='[email protected]', createTime=null, updateTime=null, version=null}, User{
id=7, name='Lisa', age=235, email='[email protected]', createTime=Thu Nov 19 16:37:43 CST 2020, updateTime=Thu Nov 19 17:05:35 CST 2020, version=1}]
3
7
3
true
true
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
//删除操作,物理删除
@Test
public void testDeleteById(){
//单个删除
userMapper.deleteById(1);
//批量删除
userMapper.deleteBatchIds(Arrays.asList(1,2,3));
}
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态“,之后数据库能看到此条数据。
数据库表中添加逻辑删除字段,对应实体类添加逻辑删除属性
@TableLogic
private Integer deleted;
配置逻辑删除插件
//逻辑删除插件,3.1.1新版本不用配置插件
@Bean
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
添加配置信息
logic-delete-value: 1
logic-not-delete-value: 0 #配置不删除是0,删除是1
执行删除方法!
@Test
public void testDeleteById(){
userMapper.deleteById(1329410275504369665L);
}
日志输出:
==> Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0
==> Parameters: 1329410275504369665(Long)
<== Updates: 1
执行查询方法语句中多一个WHERE deleted=0!!!逻辑删除!!
——使用QuerryWapper构建条件查询
代码详解(注释详细)
//创建QueryWrapper对象
QueryWrapper<User> wrapper = new QueryWrapper<>();
//通过QueryWrapper设置条件
//ge(大于等于)、gt(大于)、le(小于等于)、lt(小于)
//查询大于等于30的人
wrapper.ge("age",100);//参数段名称,值
List<User> users = userMapper.selectList(wrapper);//传入wrapper
System.out.println(users);
//eq(等于)、ne(不等于)
//查询名称是Tom的人
QueryWrapper<User> eq = wrapper.eq("name", "Tom");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
//between(查范围中的值)
//查询年龄20-100中的人
QueryWrapper<User> age = wrapper.between("age", 20, 100);
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
//like(模糊查询)
wrapper.like("name", "a" );
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
//orderByDesc(通过条件排序查询)
wrapper.orderByDesc("id");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
//last(拼接sql语句)
wrapper.last("limit 1");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
//select(查询指定的列)
wrapper.select("name","age");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);