背景
mybatis-plus使用的时候,每个表对应一个实体类,然后对应实体类会分出Service、Impl、Dao几个文件,然后才能注入对应的Service使用。但是在分布式开发,有时候仅仅只是想调用一下getById,要增加多个文件太麻烦,又或者是想封装通用的组件,不想特意的增加这么多文件。所以希望能实现一个工具类,传入实体类Class即可快速调用getById等接口。
实现
package com.meal.base.common;
import com.baomidou.mybatisplus.extension.service.IService;
import com.meal.BaseEntity;
import com.meal.common.dto.PageDto;
import com.meal.common.vo.PageVo;
public interface EntityService<T> extends IService<T> {
/**
* 保存或更新
* id为空则是新增数据
* id不为空是更新数据
*
* @param entity 实体类
* @return 返回实体类的ID
*/
Long saveOne(T entity);
/**
* 逻辑删除 只修改delFlag字段
*
* @param id id
* @return 返回实体类的ID
*/
Long delete(Long id);
}
package com.meal.crud.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.meal.BaseEntity;
import com.meal.base.common.EntityService;
import com.meal.common.dto.PageDto;
import com.meal.common.vo.PageVo;
import java.time.LocalDateTime;
public class EntityCrudServiceImpl<T> extends ServiceImpl<BaseMapper<T>, T> implements EntityService<T> {
public void setBaseMapper(BaseMapper<T> baseMapper) {
this.baseMapper = baseMapper;
}
@Override
public BaseMapper<T> getBaseMapper() {
return baseMapper;
}
@Override
public Long saveOne(T entity) {
if (entity instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) entity;
if (baseEntity.isNewRecord()) {
return this.save(entity) ? baseEntity.getId() : 0L;
} else {
return this.updateById(entity) ? baseEntity.getId() : 0L;
}
} else {
return (long) this.baseMapper.insert(entity);
}
}
@Override
public Long delete(Long id) {
T entity = this.getById(id);
if (entity != null) {
if (entity instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) entity;
baseEntity.setUpdateTime(LocalDateTime.now());
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", id);
this.baseMapper.delete(queryWrapper);
return id;
} else {
this.baseMapper.deleteById(id);
return id;
}
}
return 0L;
}
}
package com.meal.utils;
import cn.hutool.core.collection.ConcurrentHashSet;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.meal.BaseEntity;
import com.meal.base.BaseDao;
import com.meal.base.common.EntityDao;
import com.meal.crud.dao.EntityCrudDao;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.meal.crud.service.impl.EntityCrudServiceImpl;
import com.meal.system.entity.SysUser;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
public class EntityCrudServiceUtil {
private final static Set<String> classSet = new ConcurrentSkipListSet<>();
private static synchronized <T> void checkAutoCreateMapper(Class<T> clazz) {
if (classSet.contains(clazz.getName()))
return;
String mapperClassName = "com.meal.utils.mapper" + "." + clazz.getSimpleName() + "Mapper";
Class<?> mapperClass = new ByteBuddy()
.makeInterface(TypeDescription.Generic.Builder.parameterizedType(EntityCrudDao.class, clazz).build())
.name(mapperClassName)
.annotateType(AnnotationDescription.Builder.ofType(Mapper.class).build())
.make()
.load(clazz.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
SqlSessionFactory sqlSessionFactory = SpringUtil.getBean(SqlSessionFactory.class);
MapperFactoryBean<?> factoryBean = new MapperFactoryBean<>(mapperClass);
factoryBean.setSqlSessionFactory(sqlSessionFactory);
sqlSessionFactory.getConfiguration().addMapper(mapperClass);
classSet.add(clazz.getName());
}
private static <T> SqlSession getSqlSession(Class<T> clazz) {
SqlSession sqlSession = null;
try {
sqlSession = SqlHelper.sqlSession(clazz);
} catch (Exception e) {
}
if (sqlSession == null) {
checkAutoCreateMapper(clazz);
sqlSession = SqlHelper.sqlSession(clazz);
}
return sqlSession;
}
public static <T> T getOne(Class<T> clazz, QueryWrapper<T> queryWrapper) {
SqlSession sqlSession = getSqlSession(clazz);
try{
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
return entityCrudService.getOne(queryWrapper);
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> List<T> list(Class<T> clazz, QueryWrapper<T> queryWrapper) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
if(queryWrapper == null)
return entityCrudService.list();
return entityCrudService.list(queryWrapper);
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> T getById(Class<T> clazz, Serializable id) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
return entityCrudService.getById(id);
}finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> boolean updateById(T entity) {
Class<T> clazz = (Class<T>) entity.getClass();
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
return entityCrudService.updateById(entity);
}finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> Long saveOne(T entity) {
Class<T> clazz = (Class<T>) entity.getClass();
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
return entityCrudService.saveOne(entity);
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> boolean saveBatch(Class<T> clazz, Collection<T> entityList) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
return entityCrudService.saveBatch(entityList);
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> boolean insertBatch(Class<T> clazz, List<T> entityList) {
return insertBatch(clazz,entityList,10000);
}
public static <T> boolean insertBatch(Class<T> clazz, List<T> entityList, int batchSize) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
int len = entityList.size();
int i =0;
while (i<len){
int end = Math.min(i+batchSize,len);
List<T> list = new CopyOnWriteArrayList<>(entityList.subList(i,end));
i+=batchSize;
if(baseMapper instanceof EntityDao){
((EntityDao<T>)baseMapper).insertBatchSomeColumn(list) ;
} else{
((BaseDao)baseMapper).insertBatchSomeColumn(list);
}
}
return true;
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> Boolean delete(Class<T> clazz, Long id) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
EntityCrudServiceImpl<T> entityCrudService = new EntityCrudServiceImpl<>();
entityCrudService.setBaseMapper(baseMapper);
return entityCrudService.delete(id) >= 1;
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
//接口过于危险 不开放
private static <T> Boolean delete(Class<T> clazz, QueryWrapper<T> queryWrapper) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
int flag = baseMapper.delete(queryWrapper);
return flag >= 1;
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> Boolean delete(Class<T> clazz, SFunction<T, ?> fn, Object val) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(fn, val);
int flag = baseMapper.delete(queryWrapper);
return flag >= 1;
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
public static <T> Boolean delete(Class<T> clazz, SFunction<T, ?> fn, List val) {
SqlSession sqlSession = getSqlSession(clazz);
try {
BaseMapper<T> baseMapper = SqlHelper.getMapper(clazz, sqlSession);
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().in(fn, val);
int flag = baseMapper.delete(queryWrapper);
return flag >= 1;
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
}
}
}
使用
OrderInfo orderInfo = EntityCrudServiceUtil.getById(OrderInfo.class, orderId);