优化实体类自定义拓展

This commit is contained in:
zhouhao
2022-03-30 14:20:51 +08:00
parent 90255abc9d
commit 2b656b5943
13 changed files with 184 additions and 73 deletions

View File

@@ -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)

View File

@@ -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();
}
}

View File

@@ -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);
}
}
};

View File

@@ -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();

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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));
}
}

View File

@@ -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());
}
}