1、Sql 注⼊器
在MP中,通过AbstractSqlInjector将BaseMapper中的⽅法注⼊到了Mybatis容器,这样这些⽅法才可以正常执⾏。
那么,如果我们需要扩充BaseMapper中的⽅法,⼜该如何实现呢?
下⾯以扩展findAll⽅法为例进⾏演示。
1.1、编写MyBaseMapper
/**
* 通用mapper接口,以后创建其他mapper接口时,不再继承BaseMapper,而是继承MyBaseMapper
* @param <T>
*/
public interface MyBaseMapper<T> extends BaseMapper<T> {
/*
查询所有用户
*/
public List<User> findAll();
}
其他的Mapper都可以继承该Mapper,这样实现了统⼀的扩展。
如:
public interface UserMapper extends MyBaseMapper<User> {
/*
自定义findById方法
*/
public User findById(Long id);
}
1.2、编写MySqlInjector
如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的⽅法将失效,所以选择继承 DefaultSqlInjector进⾏扩展。
/**
* 自定义Ssl注入器
*/
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList() {
List<AbstractMethod> methodList = super.getMethodList();
//扩充自定义方法
methodList.add(new FindAll());
return methodList;
}
}
1.3、编写FindAll
public class FindAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql = "select * from " + tableInfo.getTableName();
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addSelectMappedStatement(mapperClass, "findAll", sqlSource, modelClass, tableInfo);
}
}
1.4、注册到Spring容器
/*
自定义sql注入器
*/
@Bean
public MySqlInjector mySqlInjector(){
return new MySqlInjector();
}
1.5、测试
/*
自定义sql注入器测试
*/
@Test
public void testFindAll(){
List<User> all = userMapper.findAll();
for (User user : all) {
System.out.println(user);
}
}
输出的SQL:
Time:10 ms - ID:com.tao.mapper.UserMapper.findAll
Execute SQL:
select
*
from
user
2、⾃动填充功能
有些时候我们可能会有这样的需求,插⼊或者更新数据时,希望有些字段可以⾃动填充数据,⽐如密码、version 等。在MP中提供了这样的功能,可以实现⾃动填充。
2.1、添加@TableField注解
@TableField(fill = FieldFill.INSERT) //插⼊数据时进⾏填充
private String version;
为 version 添加⾃动填充功能,在新增数据时有效。
FieldFill提供了多种模式选择:
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插⼊时填充字段
*/
INSERT,
/**
* 更新时填充字段
*/
UPDATE,
/**
* 插⼊和更新时填充字段
*/
INSERT_UPDATE
}
2.2、编写MyMetaObjectHandler
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Object version = getFieldValByName("version", metaObject);
if (null == version){
//该属性为空,可以进行填充
setFieldValByName("version",1,metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
2.3、测试
@Test
public void testInsert(){
User user = new User();
user.setName("小七333");
user.setAge("18");
user.setMail("xiaoqi@163.com");
//返回值是数据库中影响的行数
int result = userMapper.insert(user);
System.out.println(result);
System.out.println("id值为:" + user.getId());
}
打印sql:
Time:15 ms - ID:com.tao.mapper.UserMapper.insert
Execute SQL:
INSERT
INTO
user
( name, age, email, version )
VALUES
( '小七333', '18', 'xiaoqi@163.com', 1 )
结果:
3、逻辑删除
开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,⽽并⾮真正的物理删除(⾮DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的⽬的就是避免数据被真正的删除。
MP提供了这样的功能,⽅便我们使⽤:
3.1、修改表结构
为user表增加deleted字段,⽤于表示数据是否被删除,1代表删除,0代表未删除。
ALTER TABLE `user`
ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER `version`;
同时,也修改User实体,增加deleted属性并且添加@TableLogic注解:
@TableLogic
private Integer deleted;
3.2、配置
application.properties:
# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
3.3、测试
@Test
public void testDeleteById(){
int i = userMapper.deleteById(6L);
System.out.println(i);
}
执⾏的SQL:
Time:4 ms - ID:com.tao.mapper.UserMapper.deleteById
Execute SQL:
UPDATE
user
SET
deleted=1
WHERE
id=6
AND deleted=0
测试查询:
@Test
public void testSelectById(){
User user = userMapper.selectById(6L);
System.out.println(user);
}
执⾏的SQL:
Time:6 ms - ID:com.tao.mapper.UserMapper.selectById
Execute SQL:
SELECT
id,
name,
age,
email AS mail,
version,
deleted
FROM
user
WHERE
id=6
AND deleted=0
null
可⻅,已经实现了逻辑删除。