mirror of
https://github.com/hs-web/hsweb-framework.git
synced 2026-07-01 05:24:36 +08:00
优化实体类自定义拓展
This commit is contained in:
@@ -49,13 +49,11 @@ public class AutoDDLProcessor implements InitializingBean {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void afterPropertiesSet() {
|
||||
if (entityFactory instanceof MapperEntityFactory) {
|
||||
MapperEntityFactory factory = ((MapperEntityFactory) entityFactory);
|
||||
for (EntityInfo entity : entities) {
|
||||
factory.addMapping(entity.getEntityType(), MapperEntityFactory.defaultMapper(entity.getRealType()));
|
||||
}
|
||||
}
|
||||
List<Class> entities = this.entities.stream().map(EntityInfo::getRealType).collect(Collectors.toList());
|
||||
|
||||
List<Class<?>> entities = this.entities
|
||||
.stream()
|
||||
.map(e -> entityFactory.getInstanceType(e.getRealType(), true))
|
||||
.collect(Collectors.toList());
|
||||
if (properties.isAutoDdl()) {
|
||||
//加载全部表信息
|
||||
if (reactive) {
|
||||
@@ -63,7 +61,7 @@ public class AutoDDLProcessor implements InitializingBean {
|
||||
.doOnNext(type -> log.trace("auto ddl for {}", type))
|
||||
.map(type -> {
|
||||
RDBTableMetadata metadata = resolver.resolve(type);
|
||||
EntityDDLEvent event = new EntityDDLEvent(this,type,metadata);
|
||||
EntityDDLEvent<?> event = new EntityDDLEvent<>(this, type, metadata);
|
||||
eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, event, type));
|
||||
return metadata;
|
||||
})
|
||||
@@ -83,7 +81,7 @@ public class AutoDDLProcessor implements InitializingBean {
|
||||
log.trace("auto ddl for {}", type);
|
||||
try {
|
||||
RDBTableMetadata metadata = resolver.resolve(type);
|
||||
EntityDDLEvent event = new EntityDDLEvent(this,type,metadata);
|
||||
EntityDDLEvent<?> event = new EntityDDLEvent<>(this, type, metadata);
|
||||
eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, event, type));
|
||||
operator.ddl()
|
||||
.createOrAlter(metadata)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.hswebframework.web.crud.configuration;
|
||||
|
||||
import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping;
|
||||
import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType;
|
||||
import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
class DetectEntityColumnMapping implements EntityColumnMapping {
|
||||
private final String id;
|
||||
private final Class<?> type;
|
||||
private final EntityColumnMapping mapping;
|
||||
|
||||
public DetectEntityColumnMapping(Class<?> type,
|
||||
EntityColumnMapping mapping) {
|
||||
this.id = MappingFeatureType.columnPropertyMapping.createFeatureId(type);
|
||||
this.type = type;
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RDBColumnMetadata> getColumnByProperty(String property) {
|
||||
return mapping.getColumnByProperty(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getPropertyByColumnName(String columnName) {
|
||||
return mapping.getPropertyByColumnName(columnName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RDBColumnMetadata> getColumnByName(String columnName) {
|
||||
return mapping.getColumnByName(columnName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getColumnPropertyMapping() {
|
||||
return mapping.getColumnPropertyMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getId();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import org.hswebframework.ezorm.core.meta.Feature;
|
||||
import org.hswebframework.ezorm.rdb.events.EventListener;
|
||||
import org.hswebframework.ezorm.rdb.executor.SyncSqlExecutor;
|
||||
import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSqlExecutor;
|
||||
import org.hswebframework.ezorm.rdb.mapping.DefaultEntityColumnMapping;
|
||||
import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping;
|
||||
import org.hswebframework.ezorm.rdb.mapping.EntityManager;
|
||||
import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType;
|
||||
@@ -186,16 +187,25 @@ public class EasyormConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EntityTableMetadataParser jpaEntityTableMetadataParser(RDBDatabaseMetadata metadata,
|
||||
EntityFactory factory,
|
||||
ObjectProvider<TableMetadataCustomizer> customizers) {
|
||||
|
||||
JpaEntityTableMetadataParser parser = new JpaEntityTableMetadataParser() {
|
||||
|
||||
@Override
|
||||
public Optional<RDBTableMetadata> parseTableMetadata(Class<?> entityType) {
|
||||
Optional<RDBTableMetadata> tableOpt = super.parseTableMetadata(entityType);
|
||||
Class<?> realType = factory.getInstanceType(entityType, true);
|
||||
Optional<RDBTableMetadata> tableOpt = super.parseTableMetadata(realType);
|
||||
tableOpt.ifPresent(table -> {
|
||||
if (realType != entityType) {
|
||||
table.addFeature(new DetectEntityColumnMapping(
|
||||
entityType,
|
||||
table.findFeatureNow(
|
||||
MappingFeatureType.columnPropertyMapping.createFeatureId(realType)
|
||||
)));
|
||||
}
|
||||
for (TableMetadataCustomizer customizer : customizers) {
|
||||
customizer.customTable(entityType, table);
|
||||
customizer.customTable(realType, table);
|
||||
}
|
||||
});
|
||||
return tableOpt;
|
||||
@@ -203,7 +213,8 @@ public class EasyormConfiguration {
|
||||
|
||||
@Override
|
||||
protected JpaEntityTableMetadataParserProcessor createProcessor(RDBTableMetadata table, Class<?> type) {
|
||||
return new JpaEntityTableMetadataParserProcessor(table, type) {
|
||||
Class<?> realType = factory.getInstanceType(type, true);
|
||||
return new JpaEntityTableMetadataParserProcessor(table, realType) {
|
||||
@Override
|
||||
protected void customColumn(PropertyDescriptor descriptor,
|
||||
Field field,
|
||||
@@ -211,7 +222,7 @@ public class EasyormConfiguration {
|
||||
Set<Annotation> annotations) {
|
||||
super.customColumn(descriptor, field, column, annotations);
|
||||
for (TableMetadataCustomizer customizer : customizers) {
|
||||
customizer.customColumn(type, descriptor, field, annotations, column);
|
||||
customizer.customColumn(realType, descriptor, field, annotations, column);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,8 +46,10 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
|
||||
|
||||
private String getResourceClassName(Resource resource) {
|
||||
try {
|
||||
return metadataReaderFactory.getMetadataReader(resource)
|
||||
.getClassMetadata().getClassName();
|
||||
return metadataReaderFactory
|
||||
.getMetadataReader(resource)
|
||||
.getClassMetadata()
|
||||
.getClassName();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -98,46 +100,31 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
|
||||
for (String className : scanEntities(arr)) {
|
||||
Class<?> entityType = org.springframework.util.ClassUtils.forName(className, null);
|
||||
if (Arrays.stream(anno)
|
||||
.noneMatch(ann -> AnnotationUtils.findAnnotation(entityType, ann) != null)) {
|
||||
.noneMatch(ann -> AnnotationUtils.getAnnotation(entityType, ann) != null)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ImplementFor implementFor = AnnotationUtils.findAnnotation(entityType, ImplementFor.class);
|
||||
Reactive reactive = AnnotationUtils.findAnnotation(entityType, Reactive.class);
|
||||
Class genericType = Optional
|
||||
.ofNullable(implementFor)
|
||||
.map(ImplementFor::value)
|
||||
.orElseGet(() -> {
|
||||
return Stream
|
||||
.of(entityType.getInterfaces())
|
||||
.filter(e -> GenericEntity.class.isAssignableFrom(e))
|
||||
.findFirst()
|
||||
.orElse(entityType);
|
||||
});
|
||||
|
||||
Class idType = null;
|
||||
if (implementFor == null || implementFor.idType() == Void.class) {
|
||||
try {
|
||||
if (GenericEntity.class.isAssignableFrom(entityType)) {
|
||||
idType = ClassUtils.getGenericType(entityType);
|
||||
}
|
||||
if (idType == null) {
|
||||
Method getId = org.springframework.util.ClassUtils.getMethod(entityType, "getId");
|
||||
idType = getId.getReturnType();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
idType = String.class;
|
||||
try {
|
||||
if (GenericEntity.class.isAssignableFrom(entityType)) {
|
||||
idType = ClassUtils.getGenericType(entityType);
|
||||
}
|
||||
} else {
|
||||
idType = implementFor.idType();
|
||||
if (idType == null) {
|
||||
Method getId = org.springframework.util.ClassUtils.getMethod(entityType, "getId");
|
||||
idType = getId.getReturnType();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
idType = String.class;
|
||||
}
|
||||
|
||||
EntityInfo entityInfo = new EntityInfo(genericType,
|
||||
EntityInfo entityInfo = new EntityInfo(entityType,
|
||||
entityType,
|
||||
idType,
|
||||
reactiveEnabled,
|
||||
nonReactiveEnabled);
|
||||
if (!entityInfos.contains(entityInfo) || implementFor != null) {
|
||||
if (!entityInfos.contains(entityInfo)) {
|
||||
entityInfos.add(entityInfo);
|
||||
}
|
||||
|
||||
@@ -187,15 +174,6 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
|
||||
registry.registerBeanDefinition(AutoDDLProcessor.class.getName() + "_" + count.incrementAndGet(), definition);
|
||||
}
|
||||
|
||||
// try {
|
||||
// BeanDefinition definition = registry.getBeanDefinition(AutoDDLProcessor.class.getName());
|
||||
// Set<EntityInfo> infos = (Set) definition.getPropertyValues().get("entities");
|
||||
// infos.addAll(entityInfos);
|
||||
// } catch (NoSuchBeanDefinitionException e) {
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
static AtomicInteger count = new AtomicInteger();
|
||||
|
||||
@@ -10,11 +10,11 @@ import lombok.Setter;
|
||||
@EqualsAndHashCode(of = "entityType")
|
||||
@AllArgsConstructor
|
||||
public class EntityInfo {
|
||||
private Class entityType;
|
||||
private Class<?> entityType;
|
||||
|
||||
private Class realType;
|
||||
private Class<?> realType;
|
||||
|
||||
private Class idType;
|
||||
private Class<?> idType;
|
||||
|
||||
private boolean reactive;
|
||||
|
||||
|
||||
@@ -73,6 +73,11 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> MapperEntityFactory addMappingIfAbsent(Class<T> target, Mapper<? extends T> mapper) {
|
||||
realTypeMapper.putIfAbsent(target, mapper);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <S, T> MapperEntityFactory addCopier(PropertyCopier<S, T> copier) {
|
||||
Class<S> source = (Class<S>) ClassUtils.getGenericType(copier.getClass(), 0);
|
||||
Class<T> target = (Class<T>) ClassUtils.getGenericType(copier.getClass(), 1);
|
||||
|
||||
@@ -8,13 +8,14 @@ import org.hswebframework.ezorm.core.DefaultValue;
|
||||
import org.hswebframework.ezorm.core.DefaultValueGenerator;
|
||||
import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import org.springframework.util.StringUtils;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class DefaultIdGenerator implements DefaultValueGenerator<RDBColumnMetadata> {
|
||||
public class DefaultIdGenerator implements DefaultValueGenerator<RDBColumnMetadata> {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@@ -32,14 +33,10 @@ public class DefaultIdGenerator implements DefaultValueGenerator<RDBColumnMetada
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public DefaultValue generate(RDBColumnMetadata metadata) {
|
||||
return Mono.justOrEmpty(mappings.get(metadata.getOwner().getName()))
|
||||
.switchIfEmpty(Mono.justOrEmpty(defaultId))
|
||||
.flatMap(id->Mono.justOrEmpty(metadata.findFeature(DefaultValueGenerator.createId(id))))
|
||||
.doOnNext(gen-> log.debug("use default id generator : {} for column : {}", gen.getSortId(), metadata.getFullName()))
|
||||
.map(gen->gen.generate(metadata))
|
||||
.switchIfEmpty(Mono.error(()->new UnsupportedOperationException("不支持的生成器:" + defaultId)))
|
||||
.toFuture()
|
||||
.get();
|
||||
String genId = mappings.getOrDefault(metadata.getOwner().getName(), defaultId);
|
||||
DefaultValueGenerator<RDBColumnMetadata> generator = metadata.findFeatureNow(DefaultValueGenerator.createId(genId));
|
||||
log.debug("use default id generator : {} for column : {}", generator.getSortId(), metadata.getFullName());
|
||||
return generator.generate(metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.hswebframework.web.crud;
|
||||
|
||||
import org.hswebframework.web.crud.entity.CustomTestEntity;
|
||||
import org.hswebframework.web.crud.entity.TestEntity;
|
||||
import org.hswebframework.web.crud.service.TestEntityService;
|
||||
import org.junit.Assert;
|
||||
@@ -13,22 +14,31 @@ import reactor.test.StepVerifier;
|
||||
|
||||
@SpringBootTest
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class CrudTests {
|
||||
public class CrudTests {
|
||||
|
||||
@Autowired
|
||||
private TestEntityService service;
|
||||
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
|
||||
TestEntity entity = TestEntity.of("test",100);
|
||||
public void test() {
|
||||
|
||||
CustomTestEntity entity = new CustomTestEntity();
|
||||
entity.setExt("xxx");
|
||||
entity.setAge(1);
|
||||
entity.setName("test");
|
||||
|
||||
Mono.just(entity)
|
||||
.as(service::insert)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(1)
|
||||
.verifyComplete();
|
||||
.cast(TestEntity.class)
|
||||
.as(service::insert)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(1)
|
||||
.verifyComplete();
|
||||
Assert.assertNotNull(entity.getId());
|
||||
|
||||
service.findById(entity.getId())
|
||||
.as(StepVerifier::create)
|
||||
.expectNextMatches(e -> e instanceof CustomTestEntity)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.hswebframework.web.crud;
|
||||
|
||||
import org.hswebframework.web.api.crud.entity.EntityFactory;
|
||||
import org.hswebframework.web.crud.entity.factory.EntityMappingCustomizer;
|
||||
import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -13,7 +15,9 @@ import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||
public class TestApplication {
|
||||
|
||||
@Bean
|
||||
public EntityFactory entityFactory(){
|
||||
return new MapperEntityFactory();
|
||||
public EntityFactory entityFactory(ObjectProvider<EntityMappingCustomizer> customizers) {
|
||||
MapperEntityFactory factory = new MapperEntityFactory();
|
||||
customizers.forEach(customizer -> customizer.custom(factory));
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.hswebframework.web.crud.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hswebframework.web.api.crud.entity.GenericEntity;
|
||||
import org.hswebframework.web.bean.ToString;
|
||||
import org.hswebframework.web.crud.generator.Generators;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
@NoArgsConstructor
|
||||
public class CustomTestEntity extends TestEntity {
|
||||
|
||||
|
||||
@Column
|
||||
@ToString.Ignore
|
||||
private String ext;
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hswebframework.web.api.crud.entity.GenericEntity;
|
||||
import org.hswebframework.web.crud.annotation.EnableEntityEvent;
|
||||
import org.hswebframework.web.crud.generator.Generators;
|
||||
|
||||
import javax.persistence.Column;
|
||||
@@ -16,6 +17,7 @@ import javax.persistence.Table;
|
||||
@Table(name = "s_test")
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
@NoArgsConstructor
|
||||
@EnableEntityEvent
|
||||
public class TestEntity extends GenericEntity<String> {
|
||||
|
||||
@Column(length = 32)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.hswebframework.web.crud.service;
|
||||
|
||||
import org.hswebframework.web.crud.entity.CustomTestEntity;
|
||||
import org.hswebframework.web.crud.entity.TestEntity;
|
||||
import org.hswebframework.web.crud.entity.factory.EntityMappingCustomizer;
|
||||
import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CustomTestCustom implements EntityMappingCustomizer {
|
||||
@Override
|
||||
public void custom(MapperEntityFactory factory) {
|
||||
factory.addMapping(TestEntity.class, new MapperEntityFactory.Mapper<>(CustomTestEntity.class,CustomTestEntity::new));
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,19 @@
|
||||
package org.hswebframework.web.crud.service;
|
||||
|
||||
import org.hswebframework.web.crud.entity.TestEntity;
|
||||
import org.hswebframework.web.crud.events.EntityCreatedEvent;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class TestEntityService extends GenericReactiveCrudService<TestEntity,String> {
|
||||
|
||||
|
||||
@EventListener
|
||||
public void handleEvent(EntityCreatedEvent<TestEntity> event){
|
||||
|
||||
System.out.println(event.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user