1.快速开始
引入依赖
<!-- mybatisPlus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
启动类上添加扫描文件:
@MapperScan(basePackages = "com.nbcb.mapper")
@SpringBootApplication
public class DpcdApplication {
public static void main(String[] args) {
SpringApplication.run(DpcdApplication.class, args);
}
}
配置文件
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
该配置可以把sql语句和查询结果输出到控制台
定义实体类(类名与表名相同)
@Data
@ToString
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
编写mapper接口(实现BaseMapper,泛型填写实体类)
@Repository
public interface DpcdMapper extends BaseMapper<User> {
}
注意
mybatis-plus相比于传统mybatis的区别点之一就是,不必再写对应的接口方法和xml语句,BaseMapper里面已经相应实现了方法,直接调用即可,节省时间。
测试
@SpringBootTest
class DpcdApplicationTests {
@Autowired
DpcdMapper dpcdMapper;
@Test
void contextLoads() {
List<User> list = dpcdMapper.selectList(null);
for (User user : list) {
System.out.println(user);
}
}
}
疑点
1.配置文件中只写了数据库名,并没有写具体的表名,mp是如何找到对应的表的?
答:后经测试发现,当改变实体类名字为Info时报以下错误:
### Cause: java.sql.SQLSyntaxErrorException: Table 'dpcd.info' doesn't exist
所以mp是根据实体类名字来找对应的表名,如果要另起别名,就需要在实体类上面添加注解@TableName(“user”),这样无论实体类叫什么名字都无所谓了。
2.注解解释
@TableName
标记在类名上,有了该注解,类名不必在于表名一致,可以任意取名
@TableId
标记在属性名上,使用@TableId(“id”)表示该属性是映射主键,属性名不必再与字段名一致,可任意取名,只需括号内是字段名即可。
如:
@TableId("id")
private Long zhujian;
查询时会自动变为
SELECT id AS zhujian,name,age,email FROM info
注意:即使该字段不是主键,只要在实体属性上加上该注解,那么使用BaseMapper自带的selectById,deleteById,updateById等方法时会把该字段当成id来使用。
@TableField
标记在属性名上,表示普通字段名。属性名不必再与字段名一致,可任意取名,只需括号内是字段名即可。
@Version
- 描述:乐观锁注解、标记
@Verison
在字段上
@EnumValue
- 描述:通枚举类注解(注解在枚举字段上)
@TableLogic
- 描述:表字段逻辑处理注解(逻辑删除)
1.实体类中属性加上@TableLogic,
@TableLogic
private Integer dataStatus;
2.调用BaseMapper的deleteById(id)或者调用IService的removeById(id)
效果:
没有@TableLogic注解调用deleteById/removeById,直接删除数据。
SQL:delete from table where id = 1
有注解走Update方法
SQL:Update table set isDelete = 1 where id = 1
3.@TableLogic注解参数
value = "" 未删除的值,默认值为0
delval = "" 删除后的值,默认值为1
@TableLogic(value="原值",delval="改值")
扩展
当使用了@TableLogic注解,调用update方法是并不会将该字段放入修改字段中,而是在条件字段中。即使你给dataStatus赋值也不会修改。
SQL: Update table set 字段1 = 值1,字段2 = 值2 where id = 1 and data_status = 0
@OrderBy
-
描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
标记在属性名上,表示按照该属性名倒序排序,如果有多个排序条件,只需在@OrderBy(sort=**)括号内填入数字即可,数字越小,条件越靠前。
3.自动填充
1.添加两个字段:创建时间,更新时间
@TableField(value = "CREATETIME",fill = FieldFill.INSERT)
private String createTime;
@TableField(value = "UPDATETIME",fill = FieldFill.UPDATE)
private String updateTime;
fill的值有:
FieldFill.DEFAULT,默认不处理
FieldFill.INSERT,插入时填充
FieldFill.UPDATE,更新时填充
FieldFill.INSERT_UPDATE;插入更新时都填充
2.实现接口
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
@Component
@Slf4j
public class MyHandle implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始插入填充......");
this.strictInsertFill(metaObject, "createTime", String.class,DateUtil.now());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("开始更新填充......");
this.strictUpdateFill(metaObject, "updateTime", String.class, DateUtil.now());
}
}
注意
strictInsertFill方法的第二个参数填充字段名是不能填写@TableField括号里的值,要填写属性名的值。比如不能填写CREATETIME,只能填写createTime
第三个参数是该字段是什么类型,第四个 参数为要填入的值.
测试
@Test
void contextLoads() {
Info info = new Info();
info.setId(456l);
info.setName("张三");
info.setAge(15);
info.setEmail("123525");
dpcdMapper.insert(info);
}
4.乐观锁
控制高并发的一种手段,还有悲观锁。
区别
- 悲观锁认为每次查询数据都有人和它竞争,每次去拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁。这样别人拿数据的时候就要等待直到锁的释放。[]
实现方式:
select ... for update 加锁
- 乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现[适用于多读的应用类型,这样可以提高吞吐量]
实现方式:
一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功
5.逻辑删除
实现
步骤一:
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
步骤二:
@TableLogic
private Integer deleted;
步骤三:
运行BaseMapper自带的delete方法
6.分页查询
步骤一:
@Configuration
public class Myhandle2 {
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
步骤二:
@Test
void contextLoads() {
Page<Info> page = new Page<>(1,2);
Page<Info> infoPage = dpcdMapper.selectPage(page, null);
System.out.println(infoPage.getRecords());
}
结果: