mybatisplus是mybatis的增强版本,对于简单的crud可以无xml启动,且支持主键自动生成等等
引入plus的相关依赖后,不要引入mybatis和mybatis-spring,防止版本差异导致冲突
配置信息
#jdk8使用这个驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#后缀是由于springboot2.1自动集成jdbc8,该版本的jdbc需要加入这个后缀
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
启动类
@MapperScan会在指定包的所有类添加一个@Mapper,该注解会给每个mapper接口动态生成一个代理对象,该代理对象会拦截接口方法,转而去执行MapperStatement(id+sql)所代表的sql
@SpringBootApplication
@MapperScan("com.atguigu.mapper")
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class,args);
}
}
如果mapper接口上什么注解都不加,那么会在引入UserMapper处报错,因为类是动态创建的,找不到注入对象,但是对象可以正确执行,为了避免报错,可以在每个mapper接口上加上一个注入注解,例如@Component
mybatisplus可以不用写xml文件,引用动态封装好的方法即可
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
@SpringBootTest
public class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
System.out.println("----selectAll----");
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
@Test
public void testInsert(){
User user=new User();
user.setName("helen");
user.setAge(18);
user.setEmail("123@qq.com");
int insert = userMapper.insert(user);
System.out.println(insert);
System.out.println(user);
}
@Test
public void testUpdateById(){
User user =new User();
user.setId(1349555182022688769L);
user.setAge(120);
int i = userMapper.updateById(user);
System.out.println(i);
}
}
主键策略
上方插入,plus插入主键id值默认会生成唯一id,不是自增的,即全局唯一ID策略
如何做到id自增?
1)数据表里设置主键自增
2)实体类中id字段配置@TableId(type = IdType.AUTO)
枚举类IdType里还有很多主键策略类型
自动填充
有时候需要用相同方式填充,例如创建时间、更新时间,可以使用自动填充功能
1)实体类上添加注解
@TableField(fill = FieldFill.INSERT)——表示插入数据时执行,把该属性值传给元对象处理器里的insertFill方法进行赋值
@TableField(fill = FieldFill.INSERT_UPDATE)——表示更新和插入数据时执行,把该属性值传给元对象处理器里的updateFill方法进行赋值
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//@TableField(fill = FieldFill.UPDATE)
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
2)实现元对象处理器接口
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//生成本类的logger日志
private static final Logger LOGGER = LoggerFactory.getLogger(MyMetaObjectHandler.class);
@Override
public void insertFill(MetaObject metaObject) {
LOGGER.info("start insert....");
//根据字段名进行赋值,不是create_time,因为mybatis驼峰驼峰式命名规则自动转换,可以省去写ResultMap的步骤
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
LOGGER.info("start update...");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
乐观锁
乐观锁允许多个事务对该数据进行变动,但不代表不负责,乐观锁通常会给数据加一个version字段,当事务操作数据时会顺便把version拿出来,当事务操作完想提交数据时,会将取出来的version和最新的version对比,如果一样则允许更新,否则将让用户重新操作,乐观锁是人为操作,悲观锁是自动操作
1)实体类添加注解
2)元对象处理器version默认值的设置
3)书写乐观锁插件
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
--------
this.setFieldValByName("version",1,metaObject);
-----
@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisPlusConfig {
//乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
查询
1)根据id查询
User user=userMapper.selectById(123);
2)根据id批量查询
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
3)条件查询,map封装查询条件,map里的key是mysql里的字段名(非驼峰形式,按照数据库字段来),value为条件的值
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("user_id", "123");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
分页
mybatisplus自带分页插件,只需简单配置引入即可实现分页功能
//引入插件
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
//简单分页
@Test
public void testSelectPage(){
//页数,大小两个参数
Page<User> page=new Page<>(1,5);
//分页结果在page对象,第二个参数是查询条件,写null则全局查询
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
//page还有对应的一系列属性值,页数,大小等等
}
删除
根据id删除、批量id删除、简单条件删除和查询的操作均差不多
逻辑删除:假删除,当删除时更改数据库字段里的某个字段即可,本质是update
1)数据库添加对应的字段
ALTER TABLE `user` ADD COLUMN `deleted` boolean
2)添加伪删除插件
3)实体类添加对应的字段deleted,并添加对应的注解让插入时自动填充
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
-------
//逻辑删除注解,默认0是未删除,1是删除,也可以自己配
@TableLogic
@TableField(fill=FieldFill.INSERT)
private Integer deleted;
------
this.setFieldValByName("deleted",0,metaObject);
------
//UPDATE user SET deleted=1 WHERE id=? AND deleted=0
int result = userMapper.deleteById(1349611363307102214L);
//plus查询默认也会自动添加逻辑删除字段的判断
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);