mirror of
https://github.com/hs-web/hsweb-framework.git
synced 2026-06-01 02:15:07 +08:00
优化枚举字典
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
package org.hswebframework.web.dao.mybatis;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
import org.hswebframework.web.dict.EnumDict;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.*;
|
||||
|
||||
import static org.springframework.util.StringUtils.tokenizeToStringArray;
|
||||
|
||||
@Slf4j
|
||||
public class EnumDictHandlerRegister {
|
||||
|
||||
static TypeHandlerRegistry typeHandlerRegistry;
|
||||
|
||||
private static MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
|
||||
|
||||
private static ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
||||
|
||||
public static void register(String packages) {
|
||||
register(tokenizeToStringArray(packages,
|
||||
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
|
||||
}
|
||||
|
||||
public static void register(String[] packages) {
|
||||
if (typeHandlerRegistry == null) {
|
||||
log.error("请在spring容器初始化后再调用此方法!");
|
||||
return;
|
||||
}
|
||||
for (String basePackage : packages) {
|
||||
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||
ClassUtils.convertClassNameToResourcePath(basePackage) + "/**/*.class";
|
||||
try {
|
||||
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
|
||||
for (Resource resource : resources) {
|
||||
try {
|
||||
MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
|
||||
Class enumType = Class.forName(reader.getClassMetadata().getClassName());
|
||||
if (enumType.isEnum() && EnumDict.class.isAssignableFrom(enumType)) {
|
||||
log.debug("register typeHandler for enum dict:{}", enumType);
|
||||
typeHandlerRegistry.register(enumType, new EnumDictHandler(enumType));
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("register enum dict error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@MappedJdbcTypes({JdbcType.VARCHAR, JdbcType.BIT,
|
||||
JdbcType.BOOLEAN, JdbcType.NUMERIC,
|
||||
JdbcType.TINYINT, JdbcType.INTEGER,
|
||||
JdbcType.BIGINT, JdbcType.DECIMAL,
|
||||
JdbcType.CHAR})
|
||||
static class EnumDictHandler<T extends Enum & EnumDict> implements TypeHandler<T> {
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
@Override
|
||||
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
|
||||
ps.setObject(i, parameter.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getResult(ResultSet rs, String columnName) throws SQLException {
|
||||
Object val = rs.getObject(columnName);
|
||||
return EnumDict.findByValue(getType(), val).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
Object val = rs.getObject(columnIndex);
|
||||
return EnumDict.findByValue(getType(), val).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
Object val = cs.getObject(columnIndex);
|
||||
return EnumDict.findByValue(getType(), val).orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,6 @@ public class MyBatisAutoConfiguration {
|
||||
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
|
||||
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
|
||||
MybatisProperties mybatisProperties = this.mybatisProperties();
|
||||
|
||||
if (null != entityFactory) {
|
||||
factory.setObjectFactory(new MybatisEntityFactory(entityFactory));
|
||||
}
|
||||
@@ -109,7 +108,11 @@ public class MyBatisAutoConfiguration {
|
||||
}
|
||||
factory.setTypeHandlersPackage(typeHandlers);
|
||||
factory.setMapperLocations(mybatisProperties.resolveMapperLocations());
|
||||
|
||||
SqlSessionFactory sqlSessionFactory = factory.getObject();
|
||||
EnumDictHandlerRegister.typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
|
||||
EnumDictHandlerRegister.register("org.hswebframework.web;" + mybatisProperties.getTypeHandlersPackage());
|
||||
|
||||
ResultMapsUtils.setSqlSession(sqlSessionFactory);
|
||||
try {
|
||||
Class.forName("javax.persistence.Table");
|
||||
@@ -117,6 +120,9 @@ public class MyBatisAutoConfiguration {
|
||||
} catch (@SuppressWarnings("all") Exception ignore) {
|
||||
}
|
||||
EasyOrmSqlBuilder.getInstance().entityFactory = entityFactory;
|
||||
|
||||
sqlSessionFactory.getConfiguration().getTypeAliasRegistry();
|
||||
|
||||
return sqlSessionFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.hswebframework.ezorm.rdb.meta.RDBColumnMetaData;
|
||||
import org.hswebframework.ezorm.rdb.meta.RDBTableMetaData;
|
||||
import org.hswebframework.ezorm.rdb.meta.converter.DateTimeConverter;
|
||||
import org.hswebframework.ezorm.rdb.meta.converter.NumberValueConverter;
|
||||
import org.hswebframework.utils.ClassUtils;
|
||||
import org.hswebframework.web.dict.EnumDict;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
import javax.persistence.Column;
|
||||
@@ -59,6 +61,8 @@ public class JpaAnnotationParser {
|
||||
jdbcTypeMapping.put(java.sql.Date.class, JDBCType.TIMESTAMP);
|
||||
jdbcTypeMapping.put(java.sql.Timestamp.class, JDBCType.TIMESTAMP);
|
||||
|
||||
jdbcTypeMapping.put(Object.class, JDBCType.VARCHAR);
|
||||
|
||||
jdbcTypeConvert.add((type, property) -> {
|
||||
Enumerated enumerated = getAnnotation(type, property, Enumerated.class);
|
||||
return enumerated != null ? JDBCType.VARCHAR : null;
|
||||
@@ -67,6 +71,14 @@ public class JpaAnnotationParser {
|
||||
Lob enumerated = getAnnotation(type, property, Lob.class);
|
||||
return enumerated != null ? JDBCType.CLOB : null;
|
||||
});
|
||||
|
||||
jdbcTypeConvert.add((type, property) -> {
|
||||
if (type.isEnum() && EnumDict.class.isAssignableFrom(type)) {
|
||||
Class genType = ClassUtils.getGenericType(type);
|
||||
return jdbcTypeMapping.getOrDefault(genType, JDBCType.OTHER);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static RDBTableMetaData parseMetaDataFromEntity(Class entityClass) {
|
||||
@@ -92,7 +104,9 @@ public class JpaAnnotationParser {
|
||||
columnMetaData.setPrecision(column.precision());
|
||||
columnMetaData.setJavaType(descriptor.getPropertyType());
|
||||
|
||||
JDBCType type = jdbcTypeMapping.get(descriptor.getPropertyType());
|
||||
Class propertyType = descriptor.getPropertyType();
|
||||
|
||||
JDBCType type = jdbcTypeMapping.get(propertyType);
|
||||
if (type == null) {
|
||||
type = jdbcTypeConvert.stream()
|
||||
.map(func -> func.apply(entityClass, descriptor))
|
||||
|
||||
@@ -20,6 +20,6 @@ public class JpaAnnotationParserTest {
|
||||
RDBTableMetaData metaData = JpaAnnotationParser.parseMetaDataFromEntity(TestEntity.class);
|
||||
|
||||
Assert.assertNotNull(metaData);
|
||||
Assert.assertEquals(metaData.getColumns().size(), 4);
|
||||
Assert.assertEquals(metaData.getColumns().size(), 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.hswebframework.web.dao.mybatis.builder.jpa;
|
||||
|
||||
import lombok.Data;
|
||||
import org.hswebframework.web.dict.defaults.TrueOrFalse;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Table;
|
||||
@@ -22,4 +23,7 @@ public class TestEntity extends AbstractEntity {
|
||||
@Column(name = "role_id")
|
||||
private String roleId;
|
||||
|
||||
@Column(name = "enabled")
|
||||
private TrueOrFalse enabled;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package org.hswebframework.web.commons.entity;
|
||||
|
||||
/**
|
||||
* TODO 完成注释
|
||||
*
|
||||
* @author zhouhao
|
||||
* @see DataStatusEnum
|
||||
*/
|
||||
public interface DataStatus {
|
||||
Byte STATUS_ENABLED = 1;
|
||||
Byte STATUS_ENABLED = 1;
|
||||
Byte STATUS_DISABLED = 0;
|
||||
Byte STATUS_LOCKED = -1;
|
||||
Byte STATUS_LOCKED = -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.hswebframework.web.commons.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.hswebframework.web.dict.EnumDict;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum DataStatusEnum implements EnumDict<Byte> {
|
||||
ENABLED((byte) 1, "正常"),
|
||||
DISABLED((byte) 0, "禁用"),
|
||||
LOCK((byte) -1, "锁定"),
|
||||
DELETED((byte) -10, "删除");
|
||||
|
||||
private Byte value;
|
||||
|
||||
private String text;
|
||||
}
|
||||
@@ -26,6 +26,20 @@ public interface EnumDict<V> {
|
||||
*/
|
||||
String getText();
|
||||
|
||||
/**
|
||||
* 对比是否和value相等,对比地址,值,value转为string忽略大小写对比,text忽略大小写对比
|
||||
*
|
||||
* @param v value
|
||||
* @return 是否相等
|
||||
*/
|
||||
default boolean eq(Object v) {
|
||||
return getValue() == v
|
||||
|| getValue().equals(v)
|
||||
|| String.valueOf(getValue()).equalsIgnoreCase(String.valueOf(v))
|
||||
|| getText().equalsIgnoreCase(String.valueOf(v));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 枚举选项的描述,对一个选项进行详细的描述有时候是必要的.默认值为{@link this#getText()}
|
||||
*
|
||||
@@ -77,7 +91,7 @@ public interface EnumDict<V> {
|
||||
*
|
||||
* @see this#find(Class, Predicate)
|
||||
*/
|
||||
static <T extends Enum & EnumDict> Optional<T> find(Class<T> type, Object valueOrTextOrAlias) {
|
||||
return Optional.ofNullable(findByValue(type, valueOrTextOrAlias).orElseGet(() -> findByText(type, String.valueOf(valueOrTextOrAlias)).orElse(null)));
|
||||
static <T extends Enum & EnumDict> Optional<T> find(Class<T> type, Object target) {
|
||||
return find(type, v->v.eq(target));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.hswebframework.web.dict.defaults;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.hswebframework.web.dict.EnumDict;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TrueOrFalse implements EnumDict<Byte> {
|
||||
|
||||
TRUE((byte) 1, "是"),
|
||||
|
||||
FALSE((byte) 0, "否");
|
||||
|
||||
private Byte value;
|
||||
|
||||
private String text;
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO 完成注释
|
||||
* 验证结果
|
||||
*
|
||||
* @author zhouhao
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.hswebframework.web.BusinessException;
|
||||
import java.util.List;
|
||||
|
||||
public class ValidationException extends BusinessException {
|
||||
private static final long serialVersionUID = 7807607467371210082L;
|
||||
private ValidateResults results;
|
||||
|
||||
public ValidationException(String message) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.hswebframework.web.bean;
|
||||
|
||||
import org.apache.commons.beanutils.BeanUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -13,7 +15,7 @@ import java.util.Map;
|
||||
public class FastBeanCopierTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
public void test() throws InvocationTargetException, IllegalAccessException {
|
||||
Source source = new Source();
|
||||
source.setAge(100);
|
||||
source.setName("测试");
|
||||
@@ -31,8 +33,8 @@ public class FastBeanCopierTest {
|
||||
Target target = new Target();
|
||||
FastBeanCopier.copy(source, target);
|
||||
|
||||
|
||||
long t = System.currentTimeMillis();
|
||||
// Copier copier = FastBeanCopier.getCopier(source, target, true);
|
||||
for (int i = 10_0000; i > 0; i--) {
|
||||
FastBeanCopier.copy(source, target);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public class DictDefineTest {
|
||||
Assert.assertEquals(UserCode.SIMPLE, EnumDict.findByText(UserCode.class, UserCode.SIMPLE.getText()).orElse(null));
|
||||
|
||||
Assert.assertEquals(UserCode.SIMPLE, EnumDict.find(UserCode.class, UserCode.SIMPLE.getText()).orElse(null));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.hswebframework.web.service.TreeService;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO 完成注释
|
||||
*
|
||||
* @author zhouhao
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.hswebframework.web.commons.entity.DataStatus;
|
||||
import org.hswebframework.web.dao.schedule.ScheduleJobDao;
|
||||
import org.hswebframework.web.entity.schedule.ScheduleJobEntity;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import org.hswebframework.web.service.EnableCacheGenericEntityService;
|
||||
import org.hswebframework.web.service.GenericEntityService;
|
||||
import org.hswebframework.web.service.schedule.ScheduleJobService;
|
||||
import org.hswebframework.web.service.schedule.ScheduleTriggerBuilder;
|
||||
@@ -16,7 +15,6 @@ import org.quartz.*;
|
||||
import org.quartz.spi.MutableTrigger;
|
||||
import org.quartz.spi.OperableTrigger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -83,18 +81,18 @@ public class SimpleScheduleJobService extends GenericEntityService<ScheduleJobEn
|
||||
|
||||
protected void startJob(ScheduleJobEntity jobEntity) {
|
||||
try {
|
||||
if(scheduler.checkExists(createJobKey(jobEntity))) {
|
||||
return;
|
||||
}
|
||||
JobDetail jobDetail = JobBuilder
|
||||
.newJob(DynamicJob.class)
|
||||
.withIdentity(createJobKey(jobEntity))
|
||||
.setJobData(createJobDataMap(jobEntity.getParameters()))
|
||||
.usingJobData(DynamicJobFactory.JOB_ID_KEY, jobEntity.getId())
|
||||
.withDescription(jobEntity.getName() + (jobEntity.getRemark() == null ? "" : jobEntity.getRemark()))
|
||||
.build();
|
||||
MutableTrigger trigger = scheduleTriggerBuilder.buildTrigger(jobEntity.getQuartzConfig());
|
||||
trigger.setKey(createTriggerKey(jobEntity));
|
||||
if (scheduler.checkExists(createJobKey(jobEntity))) {
|
||||
return;
|
||||
}
|
||||
JobDetail jobDetail = JobBuilder
|
||||
.newJob(DynamicJob.class)
|
||||
.withIdentity(createJobKey(jobEntity))
|
||||
.setJobData(createJobDataMap(jobEntity.getParameters()))
|
||||
.usingJobData(DynamicJobFactory.JOB_ID_KEY, jobEntity.getId())
|
||||
.withDescription(jobEntity.getName() + (jobEntity.getRemark() == null ? "" : jobEntity.getRemark()))
|
||||
.build();
|
||||
MutableTrigger trigger = scheduleTriggerBuilder.buildTrigger(jobEntity.getQuartzConfig());
|
||||
trigger.setKey(createTriggerKey(jobEntity));
|
||||
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
} catch (SchedulerException e) {
|
||||
@@ -129,11 +127,11 @@ public class SimpleScheduleJobService extends GenericEntityService<ScheduleJobEn
|
||||
@Override
|
||||
public void enable(String id) {
|
||||
Objects.requireNonNull(id);
|
||||
int size= createUpdate().set(ScheduleJobEntity.status, DataStatus.STATUS_ENABLED)
|
||||
int size = createUpdate().set(ScheduleJobEntity.status, DataStatus.STATUS_ENABLED)
|
||||
.where(ScheduleJobEntity.id, id).exec();
|
||||
if(size>0) {
|
||||
startJob(selectByPk(id));
|
||||
}
|
||||
if (size > 0) {
|
||||
startJob(selectByPk(id));
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteJob(ScheduleJobEntity jobEntity) {
|
||||
@@ -150,10 +148,10 @@ public class SimpleScheduleJobService extends GenericEntityService<ScheduleJobEn
|
||||
@Override
|
||||
public void disable(String id) {
|
||||
Objects.requireNonNull(id);
|
||||
int size = createUpdate().set(ScheduleJobEntity.status, DataStatus.STATUS_DISABLED)
|
||||
int size = createUpdate().set(ScheduleJobEntity.status, DataStatus.STATUS_DISABLED)
|
||||
.where(ScheduleJobEntity.id, id).exec();
|
||||
if(size>0) {
|
||||
deleteJob(selectByPk(id));
|
||||
}
|
||||
if (size > 0) {
|
||||
deleteJob(selectByPk(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user