Merge branch 'develop' of https://github.com/dibo-software/diboot-v2 into develop
This commit is contained in:
commit
3c31879fc8
|
@ -18,6 +18,7 @@ package com.diboot.core.starter;
|
|||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import com.diboot.core.config.Cons;
|
||||
import com.diboot.core.util.DateConverter;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
|
@ -72,7 +73,7 @@ public class CoreAutoConfiguration implements WebMvcConfigurer {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(HttpMessageConverters.class)
|
||||
@ConditionalOnMissingBean
|
||||
public HttpMessageConverters fastJsonHttpMessageConverters() {
|
||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
|
||||
converter.setDefaultCharset(Charset.forName(Cons.CHARSET_UTF8));
|
||||
|
@ -90,6 +91,16 @@ public class CoreAutoConfiguration implements WebMvcConfigurer {
|
|||
return new HttpMessageConverters(httpMsgConverter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mybatis-plus分页插件
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
|
||||
return paginationInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认支持String-Date类型转换
|
||||
* @param registry
|
||||
|
@ -98,4 +109,5 @@ public class CoreAutoConfiguration implements WebMvcConfigurer {
|
|||
public void addFormatters(FormatterRegistry registry) {
|
||||
registry.addConverter(new DateConverter());
|
||||
}
|
||||
|
||||
}
|
|
@ -16,12 +16,15 @@
|
|||
package com.diboot.core.binding.parser;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.diboot.core.binding.query.BindQuery;
|
||||
import com.diboot.core.binding.query.dynamic.AnnoJoiner;
|
||||
import com.diboot.core.exception.BusinessException;
|
||||
import com.diboot.core.util.BeanUtils;
|
||||
import com.diboot.core.util.ContextHelper;
|
||||
import com.diboot.core.util.S;
|
||||
import com.diboot.core.util.V;
|
||||
import com.diboot.core.vo.Status;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
@ -54,9 +57,9 @@ public class ParserCache {
|
|||
*/
|
||||
private static Map<String, String> entityClassTableCacheMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* entity类小驼峰-entity类
|
||||
* entity类小驼峰实例名-entity类
|
||||
*/
|
||||
private static Map<String, Class<?>> entityLowerCaseCamelEntityClassCacheMap = new ConcurrentHashMap<>();
|
||||
private static Map<String, Class<?>> entityName2EntityClassCacheMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* dto类-BindQuery注解的缓存
|
||||
*/
|
||||
|
@ -121,7 +124,7 @@ public class ParserCache {
|
|||
Class<?> entityClass = Class.forName(entityClassName);
|
||||
TableLinkage linkage = new TableLinkage(entityClass, m);
|
||||
tableToLinkageCacheMap.put(linkage.getTable(), linkage);
|
||||
entityLowerCaseCamelEntityClassCacheMap.put(entityClass.getSimpleName(), entityClass);
|
||||
entityName2EntityClassCacheMap.put(entityClass.getSimpleName(), entityClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,14 +177,27 @@ public class ParserCache {
|
|||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据类的entity小驼峰获取EntityClass
|
||||
* 根据entity类获取mapper实例
|
||||
* @return
|
||||
*/
|
||||
public static Class<?> getEntityClassByEntityLowerCaseCamel(String table){
|
||||
public static BaseMapper getMapperInstance(Class<?> entityClass){
|
||||
String tableName = getEntityTableName(entityClass);
|
||||
TableLinkage linkage = getTableLinkage(tableName);
|
||||
if(linkage == null){
|
||||
throw new BusinessException(Status.FAIL_INVALID_PARAM, "未找到 "+entityClass.getName()+" 的Mapper定义!");
|
||||
}
|
||||
BaseMapper mapper = (BaseMapper) ContextHelper.getBean(linkage.getMapperClass());
|
||||
return mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类的entity类名获取EntityClass
|
||||
* @return
|
||||
*/
|
||||
public static Class<?> getEntityClassByClassName(String className){
|
||||
initTableToLinkageCacheMap();
|
||||
return entityLowerCaseCamelEntityClassCacheMap.get(table);
|
||||
return entityName2EntityClassCacheMap.get(className);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
package com.diboot.core.binding.parser;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.diboot.core.config.Cons;
|
||||
import com.diboot.core.entity.BaseEntity;
|
||||
import com.diboot.core.util.BeanUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.lang.annotation.*;
|
|||
|
||||
/**
|
||||
* 绑定管理器
|
||||
* @author Xieshuang
|
||||
* @author mazc@dibo.ltd
|
||||
* @version v2.0
|
||||
* @date 2019/7/18
|
||||
*/
|
||||
|
|
|
@ -76,6 +76,17 @@ public interface BaseService<T> {
|
|||
*/
|
||||
<RE, R> boolean createEntityAndRelatedEntities(T entity, List<RE> relatedEntities, ISetter<RE, R> relatedEntitySetter);
|
||||
|
||||
/**
|
||||
* 创建或更新n-n关联
|
||||
* (在主对象的service中调用,不依赖中间表service实现中间表操作)
|
||||
* @param driverIdGetter 驱动对象getter
|
||||
* @param driverId 驱动对象ID
|
||||
* @param followerIdGetter 从动对象getter
|
||||
* @param followerIdList 从动对象id集合
|
||||
* @return
|
||||
*/
|
||||
<R> boolean createOrUpdateN2NRelations(SFunction<R, ?> driverIdGetter, Object driverId, SFunction<R, ?> followerIdGetter, List<? extends Serializable> followerIdList);
|
||||
|
||||
/**
|
||||
* 更新Entity实体
|
||||
* @param entity
|
||||
|
|
|
@ -19,10 +19,10 @@ import com.baomidou.mybatisplus.annotation.DbType;
|
|||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.diboot.core.binding.Binder;
|
||||
|
@ -32,11 +32,13 @@ import com.diboot.core.binding.binder.FieldBinder;
|
|||
import com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper;
|
||||
import com.diboot.core.config.BaseConfig;
|
||||
import com.diboot.core.config.Cons;
|
||||
import com.diboot.core.exception.BusinessException;
|
||||
import com.diboot.core.mapper.BaseCrudMapper;
|
||||
import com.diboot.core.service.BaseService;
|
||||
import com.diboot.core.util.*;
|
||||
import com.diboot.core.vo.KeyValue;
|
||||
import com.diboot.core.vo.Pagination;
|
||||
import com.diboot.core.vo.Status;
|
||||
import org.apache.ibatis.reflection.property.PropertyNamer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -80,6 +82,7 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public <RE, R> boolean createEntityAndRelatedEntities(T entity, List<RE> relatedEntities, ISetter<RE, R> relatedEntitySetter) {
|
||||
boolean success = createEntity(entity);
|
||||
if(!success){
|
||||
|
@ -89,13 +92,7 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
if(V.isEmpty(relatedEntities)){
|
||||
return success;
|
||||
}
|
||||
Class relatedEntityClass = BeanUtils.getTargetClass(relatedEntities.get(0));
|
||||
// 获取关联对象对应的Service
|
||||
BaseService relatedEntityService = ContextHelper.getBaseServiceByEntity(relatedEntityClass);
|
||||
if(relatedEntityService == null){
|
||||
log.error("未能识别到Entity: {} 的Service实现,请检查!", relatedEntityClass.getName());
|
||||
return false;
|
||||
}
|
||||
Class relatedEntityClass = relatedEntities.get(0).getClass();
|
||||
// 获取主键
|
||||
Object pkValue = getPrimaryKeyValue(entity);
|
||||
String attributeName = BeanUtils.convertToFieldName(relatedEntitySetter);
|
||||
|
@ -103,8 +100,21 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
relatedEntities.stream().forEach(relatedEntity->{
|
||||
BeanUtils.setProperty(relatedEntity, attributeName, pkValue);
|
||||
});
|
||||
// 获取关联对象对应的Service
|
||||
BaseService relatedEntityService = ContextHelper.getBaseServiceByEntity(relatedEntityClass);
|
||||
if(relatedEntityService != null){
|
||||
return relatedEntityService.createEntities(relatedEntities);
|
||||
}
|
||||
else{
|
||||
// 查找mapper
|
||||
BaseMapper mapper = ContextHelper.getBaseMapperByEntity(entity.getClass());
|
||||
// 新增关联,无service只能循环插入
|
||||
for(RE relation : relatedEntities){
|
||||
mapper.insert(relation);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
@ -143,6 +153,7 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateEntities(Collection<T> entityList) {
|
||||
if(V.isEmpty(entityList)){
|
||||
return false;
|
||||
|
@ -168,6 +179,67 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
return super.saveOrUpdateBatch(entityList, BaseConfig.getBatchSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新n-n关联
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public <R> boolean createOrUpdateN2NRelations(SFunction<R, ?> driverIdGetter, Object driverId,
|
||||
SFunction<R, ?> followerIdGetter, List<? extends Serializable> followerIdList)
|
||||
{
|
||||
if(driverId == null){
|
||||
throw new BusinessException(Status.FAIL_INVALID_PARAM, "主动ID值不能为空!");
|
||||
}
|
||||
// 从getter中获取class和fieldName
|
||||
com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda lambda = LambdaUtils.resolve(driverIdGetter);
|
||||
Class<R> middleTableClass = (Class<R>) lambda.getImplClass();
|
||||
// 获取主动从动字段名
|
||||
String driverFieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
|
||||
String followerFieldName = convertGetterToFieldName(followerIdGetter);
|
||||
List<R> n2nRelations = null;
|
||||
if(V.notEmpty(followerIdList)){
|
||||
n2nRelations = new ArrayList<>(followerIdList.size());
|
||||
try{
|
||||
for(Serializable followerId : followerIdList){
|
||||
R relation = middleTableClass.newInstance();
|
||||
BeanUtils.setProperty(relation, driverFieldName, driverId);
|
||||
BeanUtils.setProperty(relation, followerFieldName, followerId);
|
||||
n2nRelations.add(relation);
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
throw new BusinessException(Status.FAIL_EXCEPTION, e);
|
||||
}
|
||||
}
|
||||
// 删除已有关联
|
||||
LambdaQueryWrapper<R> queryWrapper = new QueryWrapper<R>().lambda()
|
||||
.eq(driverIdGetter, driverId);
|
||||
// 查找service
|
||||
BaseService baseService = ContextHelper.getBaseServiceByEntity(middleTableClass);
|
||||
if(baseService != null){
|
||||
// 条件为空,不删除
|
||||
baseService.deleteEntities(queryWrapper);
|
||||
// 添加
|
||||
if(V.notEmpty(n2nRelations)){
|
||||
baseService.createEntities(n2nRelations);
|
||||
}
|
||||
}
|
||||
else{
|
||||
// 查找mapper
|
||||
BaseMapper mapper = ContextHelper.getBaseMapperByEntity(middleTableClass);
|
||||
// 条件为空,不删除
|
||||
mapper.delete(queryWrapper);
|
||||
// 新增关联,无service只能循环插入
|
||||
if(V.notEmpty(n2nRelations)){
|
||||
for(R relation : n2nRelations){
|
||||
mapper.insert(relation);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public <RE,R> boolean updateEntityAndRelatedEntities(T entity, List<RE> relatedEntities, ISetter<RE,R> relatedEntitySetter) {
|
||||
|
@ -269,6 +341,7 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteEntities(Collection<? extends Serializable> entityIds) {
|
||||
if(V.isEmpty(entityIds)){
|
||||
return false;
|
||||
|
@ -323,8 +396,7 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
*/
|
||||
@Override
|
||||
public <FT> List<FT> getValuesOfField(Wrapper queryWrapper, SFunction<T, ?> getterFn){
|
||||
SerializedLambda lambda = LambdaUtils.resolve(getterFn);
|
||||
String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
|
||||
String fieldName = convertGetterToFieldName(getterFn);
|
||||
String columnName = S.toSnakeCase(fieldName);
|
||||
// 优化SQL,只查询当前字段
|
||||
if(queryWrapper instanceof QueryWrapper){
|
||||
|
@ -559,6 +631,18 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
|
|||
return BeanUtils.getProperty(entity, pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换SFunction为属性名
|
||||
* @param getterFn
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
private <T> String convertGetterToFieldName(SFunction<T, ?> getterFn) {
|
||||
com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda lambda = LambdaUtils.resolve(getterFn);
|
||||
String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
/***
|
||||
* 打印警告信息
|
||||
* @param method
|
||||
|
|
|
@ -18,8 +18,10 @@ package com.diboot.core.util;
|
|||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||
import com.diboot.core.binding.parser.ParserCache;
|
||||
import com.diboot.core.config.Cons;
|
||||
import com.diboot.core.service.BaseService;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
|
@ -88,6 +90,9 @@ public class ContextHelper implements ApplicationContextAware {
|
|||
if (APPLICATION_CONTEXT == null){
|
||||
APPLICATION_CONTEXT = ContextLoader.getCurrentWebApplicationContext();
|
||||
}
|
||||
if(APPLICATION_CONTEXT == null){
|
||||
log.warn("无法获取ApplicationContext,请在Spring初始化之后调用!");
|
||||
}
|
||||
return APPLICATION_CONTEXT;
|
||||
}
|
||||
|
||||
|
@ -200,11 +205,20 @@ public class ContextHelper implements ApplicationContextAware {
|
|||
}
|
||||
BaseService baseService = ENTITY_BASE_SERVICE_CACHE.get(entity.getName());
|
||||
if(baseService == null){
|
||||
log.error("未能识别到Entity: "+entity.getName()+" 的Service实现!");
|
||||
log.info("未能识别到Entity: "+entity.getName()+" 的Service实现!");
|
||||
}
|
||||
return baseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Entity获取对应的BaseMapper实现
|
||||
* @param entityClass
|
||||
* @return
|
||||
*/
|
||||
public static BaseMapper getBaseMapperByEntity(Class entityClass){
|
||||
return ParserCache.getMapperInstance(entityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Entity主键
|
||||
* @return
|
||||
|
|
|
@ -141,6 +141,18 @@ public class D extends DateUtils{
|
|||
return sdf.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日期的下一天
|
||||
* @param date 基准日期
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static Date nextDay(Date date){
|
||||
if(date == null){
|
||||
return null;
|
||||
}
|
||||
return addDays(date, 1);
|
||||
}
|
||||
|
||||
/***
|
||||
* 获取格式化的日期时间
|
||||
* @param date
|
||||
|
|
|
@ -27,11 +27,6 @@ import org.springframework.core.env.Environment;
|
|||
@Slf4j
|
||||
public class PropertiesUtils {
|
||||
|
||||
/**
|
||||
* Spring配置环境变量
|
||||
*/
|
||||
private static Environment environment;
|
||||
|
||||
/***
|
||||
* 读取配置项的值
|
||||
* @param key
|
||||
|
@ -39,11 +34,9 @@ public class PropertiesUtils {
|
|||
*/
|
||||
public static String get(String key){
|
||||
// 获取配置值
|
||||
Environment environment = ContextHelper.getApplicationContext().getEnvironment();
|
||||
if(environment == null){
|
||||
environment = ContextHelper.getApplicationContext().getEnvironment();
|
||||
}
|
||||
if(environment == null){
|
||||
log.warn("无法获取上下文Environment !");
|
||||
log.warn("无法获取上下文Environment,请在Spring初始化之后调用!");
|
||||
return null;
|
||||
}
|
||||
String value = environment.getProperty(key);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class TestEntityBinder {
|
|||
// 加载测试数据
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(User::getId, 1001L, 1002L);
|
||||
List<User> userList = userService.list(queryWrapper);
|
||||
List<User> userList = userService.getEntityList(queryWrapper);
|
||||
// 自动绑定
|
||||
List<EntityBinderVO> voList = Binder.convertAndBindRelations(userList, EntityBinderVO.class);
|
||||
// 验证绑定结果
|
||||
|
|
|
@ -95,7 +95,7 @@ public class TestEntityListBinder {
|
|||
// 加载测试数据
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(User::getId, 1001L, 1002L);
|
||||
List<User> userList = userService.list(queryWrapper);
|
||||
List<User> userList = userService.getEntityList(queryWrapper);
|
||||
// 自动绑定
|
||||
List<EntityListComplexBinderVO> voList = Binder.convertAndBindRelations(userList, EntityListComplexBinderVO.class);
|
||||
// 验证绑定结果
|
||||
|
|
|
@ -57,7 +57,7 @@ public class TestFieldBinder {
|
|||
// 加载测试数据
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(User::getId, 1001L, 1002L);
|
||||
List<User> userList = userService.list(queryWrapper);
|
||||
List<User> userList = userService.getEntityList(queryWrapper);
|
||||
// 自动绑定
|
||||
List<FieldBinderVO> voList = Binder.convertAndBindRelations(userList, FieldBinderVO.class);
|
||||
// 验证绑定结果
|
||||
|
@ -79,7 +79,7 @@ public class TestFieldBinder {
|
|||
// 加载测试数据
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(User::getId, 1001L, 1002L);
|
||||
List<User> userList = userService.list(queryWrapper);
|
||||
List<User> userList = userService.getEntityList(queryWrapper);
|
||||
// 自动绑定
|
||||
List<UserVO> voList = Binder.convertAndBindRelations(userList, UserVO.class);
|
||||
if(V.notEmpty(voList)){
|
||||
|
|
|
@ -84,7 +84,7 @@ public class TestFieldListBinder {
|
|||
// 加载测试数据
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(User::getId, 1001L, 1002L);
|
||||
List<User> userList = userService.list(queryWrapper);
|
||||
List<User> userList = userService.getEntityList(queryWrapper);
|
||||
// 自动绑定
|
||||
List<EntityListComplexBinderVO> voList = Binder.convertAndBindRelations(userList, EntityListComplexBinderVO.class);
|
||||
// 验证绑定结果
|
||||
|
|
|
@ -59,7 +59,7 @@ public class TestJoinQuery {
|
|||
public void testDateCompaire(){
|
||||
Department example = departmentService.getSingleEntity(null);
|
||||
DepartmentDTO departmentDTO = new DepartmentDTO();
|
||||
departmentDTO.setBegin(example.getCreateTime());
|
||||
departmentDTO.setCreateTime(example.getCreateTime());
|
||||
QueryWrapper<Department> queryWrapper = QueryBuilder.toQueryWrapper(departmentDTO);
|
||||
List<Department> list = departmentService.getEntityList(queryWrapper);
|
||||
Assert.assertTrue(list.size() >= 1);
|
||||
|
|
|
@ -59,15 +59,15 @@ public class DepartmentDTO extends Department {
|
|||
@DataAccessCheckpoint(type = CheckpointType.ORG)
|
||||
private Long orgId;
|
||||
|
||||
// 查询单个日期
|
||||
@BindQuery(comparison = Comparison.GE, field = "createTime")
|
||||
private Date begin;
|
||||
private Date createTime;
|
||||
|
||||
@BindQuery(comparison = Comparison.LT, field = "createTime")
|
||||
private Date end;
|
||||
private Date createTimeEnd;
|
||||
|
||||
public void setBegin(Date date){
|
||||
this.begin = date;
|
||||
this.end = D.addDays(date, 1);
|
||||
private Date getCreateTimeEnd(){
|
||||
return D.nextDay(createTime);
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,8 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户角色
|
||||
* @author mazc@dibo.ltd
|
||||
|
@ -33,6 +35,9 @@ import lombok.experimental.Accessors;
|
|||
public class UserRole extends BaseEntity {
|
||||
private static final long serialVersionUID = 3030761344045195972L;
|
||||
|
||||
@TableField(exist = false)
|
||||
private Long id;
|
||||
|
||||
@TableField
|
||||
private Long userId;
|
||||
|
||||
|
@ -42,4 +47,7 @@ public class UserRole extends BaseEntity {
|
|||
@TableField(exist = false)
|
||||
private boolean deleted;
|
||||
|
||||
@TableField(exist = false)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package diboot.core.test.binder.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.diboot.core.service.BaseService;
|
||||
import diboot.core.test.binder.entity.User;
|
||||
|
||||
/**
|
||||
|
@ -24,6 +25,6 @@ import diboot.core.test.binder.entity.User;
|
|||
* @version v2.0
|
||||
* @date 2019/1/5
|
||||
*/
|
||||
public interface UserService extends IService<User> {
|
||||
public interface UserService extends BaseService<User> {
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package diboot.core.test.binder.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.diboot.core.service.impl.BaseServiceImpl;
|
||||
import diboot.core.test.binder.entity.User;
|
||||
import diboot.core.test.binder.mapper.UserMapper;
|
||||
import diboot.core.test.binder.service.UserService;
|
||||
|
@ -27,6 +28,6 @@ import org.springframework.stereotype.Service;
|
|||
* @version 2018/12/23
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements UserService {
|
||||
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ import java.util.List;
|
|||
*/
|
||||
@TestConfiguration
|
||||
@ComponentScan(basePackages={"com.diboot", "diboot.core"})
|
||||
@MapperScan({"com.diboot.**.mapper", "diboot.**.mapper"})
|
||||
@MapperScan({"com.diboot.core.mapper", "diboot.core.**.mapper"})
|
||||
public class SpringMvcConfig implements WebMvcConfigurer{
|
||||
private static final Logger log = LoggerFactory.getLogger(SpringMvcConfig.class);
|
||||
|
||||
|
@ -63,7 +63,6 @@ public class SpringMvcConfig implements WebMvcConfigurer{
|
|||
// 设置fastjson的序列化参数:禁用循环依赖检测,数据兼容浏览器端(避免JS端Long精度丢失问题)
|
||||
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,
|
||||
SerializerFeature.BrowserCompatible);
|
||||
fastJsonConfig.setDateFormat(D.FORMAT_DATETIME_Y4MDHM);
|
||||
converter.setFastJsonConfig(fastJsonConfig);
|
||||
|
||||
HttpMessageConverter<?> httpMsgConverter = converter;
|
||||
|
|
|
@ -30,6 +30,8 @@ import com.diboot.core.util.JSON;
|
|||
import com.diboot.core.util.V;
|
||||
import com.diboot.core.vo.*;
|
||||
import diboot.core.test.StartupApplication;
|
||||
import diboot.core.test.binder.entity.UserRole;
|
||||
import diboot.core.test.binder.service.UserService;
|
||||
import diboot.core.test.config.SpringMvcConfig;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -56,6 +58,9 @@ public class BaseServiceTest {
|
|||
@Autowired
|
||||
DictionaryServiceImpl dictionaryService;
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
@Test
|
||||
public void testGet(){
|
||||
// 查询总数
|
||||
|
@ -312,4 +317,33 @@ public class BaseServiceTest {
|
|||
voList = dictionaryService.getViewObjectList(queryWrapper, pagination, DictionaryVO.class);
|
||||
Assert.assertTrue(voList.size() == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试n-n的批量新建/更新
|
||||
*/
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateUpdateN2NRelations(){
|
||||
Long userId = 10001L;
|
||||
LambdaQueryWrapper<UserRole> queryWrapper = new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, userId);
|
||||
|
||||
// 新增
|
||||
List<Long> roleIdList = Arrays.asList(10L, 11L, 12L);
|
||||
userService.createOrUpdateN2NRelations(UserRole::getUserId, userId, UserRole::getRoleId, roleIdList);
|
||||
List<UserRole> list = ContextHelper.getBaseMapperByEntity(UserRole.class).selectList(queryWrapper);
|
||||
Assert.assertTrue(list.size() == roleIdList.size());
|
||||
|
||||
// 更新
|
||||
roleIdList = Arrays.asList(13L);
|
||||
userService.createOrUpdateN2NRelations(UserRole::getUserId, userId, UserRole::getRoleId, roleIdList);
|
||||
list = ContextHelper.getBaseMapperByEntity(UserRole.class).selectList(queryWrapper);
|
||||
Assert.assertTrue(list.size() == 1);
|
||||
|
||||
// 删除
|
||||
roleIdList = null;
|
||||
userService.createOrUpdateN2NRelations(UserRole::getUserId, userId, UserRole::getRoleId, roleIdList);
|
||||
list = ContextHelper.getBaseMapperByEntity(UserRole.class).selectList(queryWrapper);
|
||||
Assert.assertTrue(list.size() == 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -187,6 +187,26 @@ boolean updateEntityAndRelatedEntities(T entity, List<RE> relatedEntities, ISett
|
|||
boolean deleteEntityAndRelatedEntities(T entity, List<RE> relatedEntities, ISetter<RE, R> relatedEntitySetter);
|
||||
~~~
|
||||
|
||||
### createOrUpdateN2NRelations 创建或更新n-n关联
|
||||
* since v2.1.0
|
||||
```java
|
||||
/**
|
||||
* 创建或更新n-n关联
|
||||
* (在主动对象的service中调用,不要求中间表有service)
|
||||
* @param driverIdGetter 驱动对象getter
|
||||
* @param driverId 驱动对象ID
|
||||
* @param followerIdGetter 从动对象getter
|
||||
* @param followerIdList 从动对象id集合
|
||||
*/
|
||||
<R> boolean createOrUpdateN2NRelations(SFunction<R, ?> driverIdGetter, Object driverId, SFunction<R, ?> followerIdGetter, List<? extends Serializable> followerIdList);
|
||||
```
|
||||
使用示例:
|
||||
~~~java
|
||||
List<Long> roleIdList = Arrays.asList(10L, 11L, 12L);
|
||||
// 新增/修改/删除(集合为空) 中间表关联关系
|
||||
userService.createOrUpdateN2NRelations(UserRole::getUserId, userId, UserRole::getRoleId, roleIdList);
|
||||
~~~
|
||||
|
||||
### deleteEntity
|
||||
```java
|
||||
boolean deleteEntity(Serializable id);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package com.diboot.file.excel.cache;
|
||||
|
||||
import com.diboot.core.binding.annotation.BindDict;
|
||||
import com.diboot.core.config.BaseConfig;
|
||||
import com.diboot.core.service.DictionaryService;
|
||||
import com.diboot.core.util.BeanUtils;
|
||||
import com.diboot.core.util.ContextHelper;
|
||||
|
@ -215,7 +216,12 @@ public class DictTempCache {
|
|||
if (cacheTime == null) {
|
||||
return true;
|
||||
}
|
||||
return (System.currentTimeMillis() - cacheTime) > 600000;
|
||||
// 过期分钟数
|
||||
int expiredMinutes = BaseConfig.getInteger("system.dict.expire", 0);
|
||||
if(expiredMinutes == 0){
|
||||
return true;
|
||||
}
|
||||
return (System.currentTimeMillis() - cacheTime) > (expiredMinutes * 60000);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue