Source public account: Zhao Xiake
1. Basic functions of Mybatis-plus
1.1 Mybatis-plus built-in methods
Mybatis-plus
It has built many wheels for us so that we can use them out of the box. BaseMapper
There are 19 commonly used methods for operating databases, such as Insert()
, deleteById()
, updateById()
, selectById()
etc.
When developing, we only need to inherit our UserMapper
inheritance BaseMapper
to obtain these common methods for operating the database. We do not need to rewrite these methods again, which is more convenient.
@Repository
public interface UserMapper extends BaseMapper<User> {
}
Mybatis-plus IService
provides us with more and richer methods of operating databases. UserServiceImpl
When we use it, we only need to inherit ours ServiceImpl
and implement IService
the interface to easily obtain these methods.
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IService {
}
1.2 Problems
Mybatis-plus
It does provide us with many methods, but also limits our needs. For example, I have some very common needs:
-
When logically deleting data, the operator is recorded in the database. If you use
Mybatis-plus
thisremoveById(1L)
method, this method can only set the database logical bit to the deleted state, and the operator cannot record it into the database. -
Each table has a tenant_id. I want to find out the ID in the table through tenant_id ,
Mybatis-plus
but there is noselectIdByTenantId()
way. Then we can only write one for each tableselectIdByTenantId
, and the code is indeed a bit redundant.So in response to the above existing problems, we can
Mybatis-plus
add a little more plus.
2. Add a few plus to BaseMapper
2.1 Add some methods to BaseMapper
Mybatis-plus
The built-in methods are inheritedAbstractMethod
public class DeleteById extends AbstractMethod {
public DeleteById() {
super("deleteById");
}
}
So we can write a DeleteAndUpdateById
class and then imitate UpdateById
the writing method to update the fields in our entity to the database and set the tombstone bit to the deleted state.
public class DeleteAndUpdateById extends AbstractMethod {
/**
* 注入自定义 MappedStatement
* 根据id逻辑删除,顺带更新数据
*
* @param mapperClass mapper 接口
* @param modelClass mapper 泛型
* @param tableInfo 数据库表反射信息
* @return MappedStatement
*/
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String methodName = CustomSqlMethod.DELETE_AND_UPDATE_BY_ID.getMethod();
String logicSql = CustomSqlMethod.DELETE_AND_UPDATE_BY_ID.getSql();
final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true);
logicSql = String.format(logicSql,
tableInfo.getTableName(),
sqlSet(false, false, tableInfo, false, ENTITY, ENTITY_DOT),
tableInfo.getKeyColumn(),
ENTITY_DOT + tableInfo.getKeyProperty(),
additional);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, logicSql, modelClass);
return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource);
}
/**
* SQL 更新 set 语句
*
* @param logic 是否逻辑删除注入器
* @param ew 是否存在 UpdateWrapper 条件
* @param table 表信息
* @param judgeAliasNull
* @param alias 别名
* @param prefix 前缀
* @return sql
*/
@Override
protected String sqlSet(boolean logic, boolean ew, TableInfo table, boolean judgeAliasNull, String alias, String prefix) {
StringBuilder sqlScriptBuilder = new StringBuilder();
// 添加删除的sql
sqlScriptBuilder.append(table.getLogicDeleteSql(false, false))
.append(DOT_NEWLINE);
// 添加更新的sql
sqlScriptBuilder.append(table.getAllSqlSet(true, prefix));
String sqlScript = sqlScriptBuilder.toString();
if (judgeAliasNull) {
sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", alias), true);
}
if (ew) {
sqlScript += NEWLINE;
sqlScript += convertIfEwParam(U_WRAPPER_SQL_SET, false);
}
sqlScript = SqlScriptUtils.convertSet(sqlScript);
return sqlScript;
}
}
Then we need to DeleteAndUpdateById
add the method to DefaultSqlInjector
.
@Component
public class CustomSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new DeleteAndUpdateById());
return methodList;
}
}
Write one CustomBaseMapper
, inherit it BaseMapper
, and add our deleteAndUpdateById
methods
public interface CustomBaseMapper<T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {
/**
* 根据id做逻辑删除,并同时修改内容
*
* @param entity
* @return
*/
int deleteAndUpdateById(@Param(Constants.ENTITY) T entity);
}
Finally, it will UserMapper
be inherited CustomBaseMapper
so that UserMappe
r has deleteAndUpdateById
a method.
@Repository
public interface UserMapper extends CustomBaseMapper<User> {
}
2.2 Add some methods to IServce
Define ICustomService
method inheritanceIService
public interface ICustomService<T> extends IService<T> {
List<Long> selectByTenantIds(List<Long> tenantIds);
int deleteAndUpdateById(@Param(Constants.ENTITY) T entity);
}
Then create the method in CustomBaseServiceImpl
the implementationICustomService
public class CustomBaseServiceImpl<M extends CustomBaseMapper<T>, T extends BaseDomain> extends ServiceImpl<M, T> {
/**
* 删除并更新内容 根据ID
*
* @param entity 对象
* @return
*/
public int deleteAndUpdateById(T entity) {
return baseMapper.deleteAndUpdateById(entity);
}
public List<Long> selectByTenantIds(List<Long> tenantIds) {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.select("id");
queryWrapper.in(!tenantIds.contains(0L), "tenant_id", tenantIds);
return listObjs(queryWrapper, id -> Long.valueOf(id.toString()));
}
}
Finally, change ours UserService
to inherit our own ICustomService
,UserServiceImpl
public interface ICustomService<T> extends IService<T> {
List<Long> selectByTenantIds(List<Long> tenantIds);
int deleteAndUpdateById(@Param(Constants.ENTITY) T entity);
}
3. Test
3.1 Test method
Through the above transformation, all our services have deleteAndUpdateById()
methods and selectByTenantIds()
methods.
class ApplicationTests {
@Resource
private UserService userService;
@Test
void testDeleteAndUpadteById() {
User user = userService.getById(1L);
user.setModifiedBy("赵侠客");
user.setModifiedAt(LocalDateTime.now());
userService.deleteAndUpdateById(user);
User dbUser = userService.getById(1L);
Assert.isTrue(dbUser == null, "删除成功");
}
@Test
void test() {
var userIds = userService.selectByTenantIds(List.of(1L));
log.info("userIds:{}", userIds);
Assert.isTrue(userIds != null);
}
}
4. Summary
Here I just Mybatis-plus
added two plus functions. More functions can be added in CustomBaseMapper
and according to your own needs ICustomService
. The main plus points that can be expanded are as follows:
- Rewrite the built-in methods of Mybatis-plus that cannot meet our actual needs
- Many common methods in the code can be extracted into Plus public functions
Source code address: https://gitee.com/whzhaochao/mybatis-plus-plus
Original address: https://mp.weixin.qq.com/s/JnS9pmZvlvTvnutnpdYAwA