feat: 完成非常牛逼的动态类型和关联感知,尽可能使用原生注解实现
This commit is contained in:
parent
f6c2997c45
commit
d84030494c
@ -1,7 +1,5 @@
|
|||||||
package com.flyfish.framework.repository.base;
|
package com.flyfish.framework.repository.base;
|
||||||
|
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
|
||||||
import org.springframework.data.mapping.PersistentProperty;
|
|
||||||
import org.springframework.data.repository.core.EntityInformation;
|
import org.springframework.data.repository.core.EntityInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,12 +15,4 @@ public interface DomainRepository<T> {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
EntityInformation<T, String> getEntityInformation();
|
EntityInformation<T, String> getEntityInformation();
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取持久化实体信息
|
|
||||||
*
|
|
||||||
* @param <P> 持久化属性泛型
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
<P extends PersistentProperty<P>> PersistentEntity<T, P> getPersistentEntity();
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.flyfish.framework.annotations.relation;
|
package com.flyfish.framework.annotations.relation;
|
||||||
|
|
||||||
import org.springframework.data.annotation.Reference;
|
|
||||||
import org.springframework.data.annotation.Transient;
|
import org.springframework.data.annotation.Transient;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
@ -14,17 +13,20 @@ import java.lang.annotation.*;
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
@Transient
|
@Transient
|
||||||
@Reference
|
|
||||||
public @interface Association {
|
public @interface Association {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 关联在本对象上的字段名称
|
* @return 关联在本对象上的字段名称
|
||||||
|
* 可不指定。不指定时,会自动取得当前对象上 @Reference 注解的字段
|
||||||
|
* <p>
|
||||||
* 如当前表的detail_id字段对应detail表的id字段,则该值为 detail_id
|
* 如当前表的detail_id字段对应detail表的id字段,则该值为 detail_id
|
||||||
*/
|
*/
|
||||||
String field() default "";
|
String field() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 关联在外部对象上的字段名称,注意,禁止循环依赖
|
* @return 关联在外部对象上的字段名称,注意,禁止循环依赖
|
||||||
|
* 可不指定。不指定时,会自动取得目标类型中 @Reference 注解的字段
|
||||||
|
* <p>
|
||||||
* 如当前表不存在目标表detail的关联id,目标表关联本实体的id为main_id,则该值为main_id。
|
* 如当前表不存在目标表detail的关联id,目标表关联本实体的id为main_id,则该值为main_id。
|
||||||
* 与field互斥,同时指定永远都以field为主
|
* 与field互斥,同时指定永远都以field为主
|
||||||
*/
|
*/
|
||||||
|
@ -10,10 +10,7 @@ import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
|
||||||
import org.springframework.data.mapping.PersistentProperty;
|
|
||||||
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||||
@ -188,9 +185,4 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleReact
|
|||||||
private Optional<Query> getQuery(Qo<T> qo) {
|
private Optional<Query> getQuery(Qo<T> qo) {
|
||||||
return qo.getQuery(entityInformation);
|
return qo.getQuery(entityInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <P extends PersistentProperty<P>> PersistentEntity<T, P> getPersistentEntity() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager;
|
|||||||
import com.flyfish.framework.r2dbc.metadata.impl.SimpleR2dbcMetadataManager;
|
import com.flyfish.framework.r2dbc.metadata.impl.SimpleR2dbcMetadataManager;
|
||||||
import com.flyfish.framework.r2dbc.operations.R2dbcReactiveEntityOperations;
|
import com.flyfish.framework.r2dbc.operations.R2dbcReactiveEntityOperations;
|
||||||
import com.flyfish.framework.r2dbc.repository.factory.DefaultReactiveRepositoryFactoryBean;
|
import com.flyfish.framework.r2dbc.repository.factory.DefaultReactiveRepositoryFactoryBean;
|
||||||
import com.flyfish.framework.r2dbc.repository.impl.DefaultReactiveRepositoryImpl;
|
import com.flyfish.framework.r2dbc.repository.impl.QueryingR2dbcReactiveRepository;
|
||||||
import com.flyfish.framework.repository.ReactiveEntityOperations;
|
import com.flyfish.framework.repository.ReactiveEntityOperations;
|
||||||
import io.r2dbc.spi.ConnectionFactory;
|
import io.r2dbc.spi.ConnectionFactory;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
@ -16,6 +16,7 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
import org.springframework.data.mapping.callback.EntityCallback;
|
import org.springframework.data.mapping.callback.EntityCallback;
|
||||||
import org.springframework.data.r2dbc.config.EnableR2dbcAuditing;
|
import org.springframework.data.r2dbc.config.EnableR2dbcAuditing;
|
||||||
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
||||||
|
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
|
||||||
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||||
import org.springframework.r2dbc.connection.init.CompositeDatabasePopulator;
|
import org.springframework.r2dbc.connection.init.CompositeDatabasePopulator;
|
||||||
import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer;
|
import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer;
|
||||||
@ -31,7 +32,7 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
@EnableR2dbcRepositories(
|
@EnableR2dbcRepositories(
|
||||||
repositoryFactoryBeanClass = DefaultReactiveRepositoryFactoryBean.class,
|
repositoryFactoryBeanClass = DefaultReactiveRepositoryFactoryBean.class,
|
||||||
repositoryBaseClass = DefaultReactiveRepositoryImpl.class,
|
repositoryBaseClass = QueryingR2dbcReactiveRepository.class,
|
||||||
basePackages = "com.flyfish.framework.*.repository"
|
basePackages = "com.flyfish.framework.*.repository"
|
||||||
)
|
)
|
||||||
@EnableR2dbcAuditing
|
@EnableR2dbcAuditing
|
||||||
@ -49,8 +50,8 @@ public class R2dbcDataConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public R2dbcMetadataManager r2dbcMetadataManager() {
|
public R2dbcMetadataManager r2dbcMetadataManager(R2dbcMappingContext mappingContext) {
|
||||||
return new SimpleR2dbcMetadataManager();
|
return new SimpleR2dbcMetadataManager(mappingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.flyfish.framework.r2dbc.config.annotations;
|
package com.flyfish.framework.r2dbc.config.annotations;
|
||||||
|
|
||||||
import com.flyfish.framework.r2dbc.repository.factory.DefaultReactiveRepositoryFactoryBean;
|
import com.flyfish.framework.r2dbc.repository.factory.DefaultReactiveRepositoryFactoryBean;
|
||||||
import com.flyfish.framework.r2dbc.repository.impl.DefaultReactiveRepositoryImpl;
|
import com.flyfish.framework.r2dbc.repository.impl.QueryingR2dbcReactiveRepository;
|
||||||
import org.springframework.core.annotation.AliasFor;
|
import org.springframework.core.annotation.AliasFor;
|
||||||
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ import java.lang.annotation.*;
|
|||||||
*/
|
*/
|
||||||
@EnableR2dbcRepositories(
|
@EnableR2dbcRepositories(
|
||||||
repositoryFactoryBeanClass = DefaultReactiveRepositoryFactoryBean.class,
|
repositoryFactoryBeanClass = DefaultReactiveRepositoryFactoryBean.class,
|
||||||
repositoryBaseClass = DefaultReactiveRepositoryImpl.class
|
repositoryBaseClass = QueryingR2dbcReactiveRepository.class
|
||||||
)
|
)
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@ -25,7 +25,10 @@ import org.springframework.data.util.Lazy;
|
|||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -61,14 +64,14 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
|
|||||||
// 遍历fields,找到要注入的数据
|
// 遍历fields,找到要注入的数据
|
||||||
R2dbcTableMetadata metadata = r2dbcMetadataManager.getMetadata(entityClass);
|
R2dbcTableMetadata metadata = r2dbcMetadataManager.getMetadata(entityClass);
|
||||||
// 获取本实体的持久化对象
|
// 获取本实体的持久化对象
|
||||||
PersistentEntity<?, ?> persistentEntity = getRepository(entityClass).getPersistentEntity();
|
PersistentEntity<?, ?> persistentEntity = metadata.getEntity();
|
||||||
// 获取属性设置器
|
// 获取属性设置器
|
||||||
PersistentPropertyAccessor<Domain> accessor = persistentEntity.getPropertyAccessor(entity);
|
PersistentPropertyAccessor<Domain> accessor = persistentEntity.getPropertyAccessor(entity);
|
||||||
|
|
||||||
// 尝试填充一对一关联
|
// 尝试填充一对一关联
|
||||||
List<Mono<Domain>> signals = new ArrayList<>();
|
List<Mono<Domain>> signals = new ArrayList<>();
|
||||||
signals.addAll(fetchAssociation(metadata.getAssociations(), persistentEntity, accessor));
|
signals.addAll(fetchAssociation(metadata.getAssociations(), accessor));
|
||||||
signals.addAll(fetchCollections(metadata.getCollections(), persistentEntity, accessor));
|
signals.addAll(fetchCollections(metadata.getCollections(), accessor));
|
||||||
|
|
||||||
// 尝试填充一对多关联
|
// 尝试填充一对多关联
|
||||||
if (CollectionUtils.isNotEmpty(signals)) {
|
if (CollectionUtils.isNotEmpty(signals)) {
|
||||||
@ -87,24 +90,26 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
|
|||||||
.collect(Collectors.toMap(repo -> repo.getEntityInformation().getJavaType(), Function.identity())));
|
.collect(Collectors.toMap(repo -> repo.getEntityInformation().getJavaType(), Function.identity())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Mono<Domain>> fetchAssociation(List<R2dbcAssociation> associations, PersistentEntity<?, ?> persistentEntity,
|
/**
|
||||||
PersistentPropertyAccessor<Domain> accessor) {
|
* 拉取一对一关联
|
||||||
|
*
|
||||||
|
* @param associations 一对一关联集合
|
||||||
|
* @param accessor 本对象的属性访问器
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
private List<Mono<Domain>> fetchAssociation(List<R2dbcAssociation> associations, PersistentPropertyAccessor<Domain> accessor) {
|
||||||
List<Mono<Domain>> signals = new ArrayList<>();
|
List<Mono<Domain>> signals = new ArrayList<>();
|
||||||
if (CollectionUtils.isNotEmpty(associations)) {
|
if (CollectionUtils.isNotEmpty(associations)) {
|
||||||
// 分区,将判断提在外面,提升性能
|
// 分区,将判断提在外面,提升性能
|
||||||
Map<Boolean, List<R2dbcAssociation>> partitions = associations.stream()
|
Map<Boolean, List<R2dbcAssociation>> partitions = associations.stream()
|
||||||
.filter(R2dbcAssociation::isValid)
|
|
||||||
.collect(Collectors.partitioningBy(R2dbcAssociation::isInner));
|
.collect(Collectors.partitioningBy(R2dbcAssociation::isInner));
|
||||||
// 处理内部查询
|
// 处理内部查询
|
||||||
if (CollectionUtils.isNotEmpty(partitions.get(true))) {
|
if (CollectionUtils.isNotEmpty(partitions.get(true))) {
|
||||||
partitions.get(true).forEach(association -> {
|
partitions.get(true).forEach(association -> {
|
||||||
// 获取对方的仓库
|
// 获取对方的仓库
|
||||||
DefaultReactiveRepository<Domain> repository = getRepository(association.getEntityClass());
|
DefaultReactiveRepository<Domain> repository = getRepository(association.getEntity().getType());
|
||||||
// 内部查询,以对象内的值作为查询条件
|
// 内部查询,以对象内的值作为查询条件
|
||||||
PersistentProperty<?> property = persistentEntity.getPersistentProperty(association.getField());
|
Object value = accessor.getProperty(association.getField());
|
||||||
if (null == property) return;
|
|
||||||
// 得到条件值
|
|
||||||
Object value = accessor.getProperty(property);
|
|
||||||
if (ObjectUtils.isEmpty(value)) return;
|
if (ObjectUtils.isEmpty(value)) return;
|
||||||
// 查询
|
// 查询
|
||||||
Mono<Domain> signal = repository.findById(String.valueOf(value))
|
Mono<Domain> signal = repository.findById(String.valueOf(value))
|
||||||
@ -120,12 +125,9 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
|
|||||||
// 获取条件
|
// 获取条件
|
||||||
String id = accessor.getBean().getId();
|
String id = accessor.getBean().getId();
|
||||||
// 准备查询
|
// 准备查询
|
||||||
DefaultReactiveRepository<Domain> repository = getRepository(association.getEntityClass());
|
DefaultReactiveRepository<Domain> repository = getRepository(association.getEntity().getType());
|
||||||
// 获取目标属性名
|
|
||||||
PersistentProperty<?> property = repository.getPersistentEntity().getPersistentProperty(association.getField());
|
|
||||||
if (null == property) return;
|
|
||||||
// 直接通过外部字段查询
|
// 直接通过外部字段查询
|
||||||
Mono<Domain> signal = repository.findOne(Queries.where(getColumnName(property)).eq(id).wrap())
|
Mono<Domain> signal = repository.findOne(Queries.where(getColumnName(association.getField())).eq(id).wrap())
|
||||||
.map(result -> association.setValue(accessor.getBean(), result))
|
.map(result -> association.setValue(accessor.getBean(), result))
|
||||||
.defaultIfEmpty(accessor.getBean());
|
.defaultIfEmpty(accessor.getBean());
|
||||||
signals.add(signal);
|
signals.add(signal);
|
||||||
@ -135,11 +137,40 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
|
|||||||
return signals;
|
return signals;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Mono<Domain>> fetchCollections(List<R2dbcCollection> collections, PersistentEntity<?, ?> persistentEntity,
|
/**
|
||||||
|
* 拉取一对多关联实体
|
||||||
|
*
|
||||||
|
* @param collections 一对多关联
|
||||||
|
* @param accessor 本对象的属性访问器
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
private List<Mono<Domain>> fetchCollections(List<R2dbcCollection> collections,
|
||||||
PersistentPropertyAccessor<Domain> accessor) {
|
PersistentPropertyAccessor<Domain> accessor) {
|
||||||
return Collections.emptyList();
|
List<Mono<Domain>> signals = new ArrayList<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(collections)) {
|
||||||
|
// 外部查询,以当前实体的id为条件,去外部表的字段上查询
|
||||||
|
collections.forEach(collection -> {
|
||||||
|
// 获取条件
|
||||||
|
String id = accessor.getBean().getId();
|
||||||
|
// 准备查询
|
||||||
|
DefaultReactiveRepository<Domain> repository = getRepository(collection.getEntity().getType());
|
||||||
|
// 直接通过外部字段查询
|
||||||
|
Mono<Domain> signal = repository.findAll(Queries.where(getColumnName(collection.getField())).eq(id).wrap())
|
||||||
|
.collectList()
|
||||||
|
.map(result -> collection.setValue(accessor.getBean(), result))
|
||||||
|
.defaultIfEmpty(accessor.getBean());
|
||||||
|
signals.add(signal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return signals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过持久化属性获取真实的列名
|
||||||
|
*
|
||||||
|
* @param property 属性
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
private String getColumnName(PersistentProperty<?> property) {
|
private String getColumnName(PersistentProperty<?> property) {
|
||||||
if (property instanceof RelationalPersistentProperty) {
|
if (property instanceof RelationalPersistentProperty) {
|
||||||
return ((RelationalPersistentProperty) property).getColumnName().getReference();
|
return ((RelationalPersistentProperty) property).getColumnName().getReference();
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.flyfish.framework.r2dbc.metadata;
|
package com.flyfish.framework.r2dbc.metadata;
|
||||||
|
|
||||||
import com.flyfish.framework.annotations.Property;
|
import com.flyfish.framework.annotations.Property;
|
||||||
import com.flyfish.framework.domain.base.Domain;
|
import com.flyfish.framework.r2dbc.metadata.reference.FieldSetter;
|
||||||
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcAssociation;
|
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcAssociation;
|
||||||
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcCollection;
|
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcCollection;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
|
import org.springframework.data.mapping.PersistentProperty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -18,11 +20,8 @@ import java.util.List;
|
|||||||
@Property("表的元数据,用于关联查询")
|
@Property("表的元数据,用于关联查询")
|
||||||
public class R2dbcTableMetadata {
|
public class R2dbcTableMetadata {
|
||||||
|
|
||||||
@Property("表名")
|
@Property("表实体信息")
|
||||||
private String tableName;
|
private PersistentEntity<?, ?> entity;
|
||||||
|
|
||||||
@Property("表实体类名")
|
|
||||||
private Class<? extends Domain> entityClass;
|
|
||||||
|
|
||||||
@Property("一对一关联信息")
|
@Property("一对一关联信息")
|
||||||
private List<R2dbcAssociation> associations = new ArrayList<>();
|
private List<R2dbcAssociation> associations = new ArrayList<>();
|
||||||
@ -30,12 +29,16 @@ public class R2dbcTableMetadata {
|
|||||||
@Property("一对多关联信息")
|
@Property("一对多关联信息")
|
||||||
private List<R2dbcCollection> collections = new ArrayList<>();
|
private List<R2dbcCollection> collections = new ArrayList<>();
|
||||||
|
|
||||||
public R2dbcTableMetadata(Class<? extends Domain> entityClass) {
|
public R2dbcTableMetadata(PersistentEntity<?, ?> entity) {
|
||||||
this.entityClass = entityClass;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAssociation(org.springframework.data.mapping.model.Property property, String field, boolean inner) {
|
public void addAssociation(PersistentEntity<?, ?> entity, PersistentProperty<?> property, FieldSetter setter, boolean inner) {
|
||||||
this.associations.add(R2dbcAssociation.of(property, field, inner));
|
this.associations.add(R2dbcAssociation.of(entity, property, setter, inner));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCollection(PersistentEntity<?, ?> entity, PersistentProperty<?> property, FieldSetter setter) {
|
||||||
|
this.collections.add(R2dbcCollection.of(entity, property, setter));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,28 @@ import com.flyfish.framework.annotations.relation.Association;
|
|||||||
import com.flyfish.framework.domain.base.Domain;
|
import com.flyfish.framework.domain.base.Domain;
|
||||||
import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager;
|
import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager;
|
||||||
import com.flyfish.framework.r2dbc.metadata.R2dbcTableMetadata;
|
import com.flyfish.framework.r2dbc.metadata.R2dbcTableMetadata;
|
||||||
|
import com.flyfish.framework.r2dbc.metadata.reference.FieldSetter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.ClassUtils;
|
import org.apache.commons.lang3.ClassUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
import org.springframework.data.mapping.model.Property;
|
import org.springframework.data.annotation.Reference;
|
||||||
import org.springframework.data.util.ClassTypeInformation;
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.data.mapping.PersistentProperty;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Arrays;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.function.Function;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 简单的元数据管理器
|
* 简单的元数据管理器
|
||||||
@ -29,8 +33,10 @@ import java.util.stream.Collectors;
|
|||||||
* @author wangyu
|
* @author wangyu
|
||||||
* 基于线程安全的反射方法进行加载并持有
|
* 基于线程安全的反射方法进行加载并持有
|
||||||
*/
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class SimpleR2dbcMetadataManager implements R2dbcMetadataManager {
|
public class SimpleR2dbcMetadataManager implements R2dbcMetadataManager {
|
||||||
|
|
||||||
|
private final R2dbcMappingContext r2dbcMappingContext;
|
||||||
private final ConcurrentMap<Class<? extends Domain>, R2dbcTableMetadata> METADATA_STORE = new ConcurrentHashMap<>();
|
private final ConcurrentMap<Class<? extends Domain>, R2dbcTableMetadata> METADATA_STORE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,55 +57,121 @@ public class SimpleR2dbcMetadataManager implements R2dbcMetadataManager {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
private R2dbcTableMetadata computeMetadata(Class<? extends Domain> entityClass) {
|
private R2dbcTableMetadata computeMetadata(Class<? extends Domain> entityClass) {
|
||||||
MetadataCreator creator = new MetadataCreator(entityClass);
|
PersistentEntity<?, ?> entity = r2dbcMappingContext.getRequiredPersistentEntity(entityClass);
|
||||||
ReflectionUtils.doWithFields(entityClass, creator);
|
MetadataCreator creator = new MetadataCreator(entity);
|
||||||
|
FieldUtils.getFieldsListWithAnnotation(entityClass, Association.class).forEach(creator);
|
||||||
return creator.metadata;
|
return creator.metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MetadataCreator implements ReflectionUtils.FieldCallback {
|
private class MetadataCreator implements Consumer<Field> {
|
||||||
|
|
||||||
private final Map<String, PropertyDescriptor> descriptors;
|
private final PersistentEntity<?, ?> entity;
|
||||||
|
|
||||||
private final ClassTypeInformation<? extends Domain> typeInformation;
|
|
||||||
|
|
||||||
private final R2dbcTableMetadata metadata;
|
private final R2dbcTableMetadata metadata;
|
||||||
|
|
||||||
private MetadataCreator(Class<? extends Domain> entityClass) {
|
private MetadataCreator(PersistentEntity<?, ?> entity) {
|
||||||
this.descriptors = Arrays.stream(BeanUtils.getPropertyDescriptors(entityClass))
|
this.entity = entity;
|
||||||
.collect(Collectors.toMap(PropertyDescriptor::getName, Function.identity()));
|
this.metadata = new R2dbcTableMetadata(entity);
|
||||||
this.typeInformation = ClassTypeInformation.from(entityClass);
|
}
|
||||||
this.metadata = new R2dbcTableMetadata(entityClass);
|
|
||||||
|
private void invokeSetter(Method method, Object obj, Object value) {
|
||||||
|
try {
|
||||||
|
method.invoke(obj, value);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldSetter getSetter(Field field) {
|
||||||
|
PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(entity.getType(), field.getName());
|
||||||
|
return Optional.ofNullable(descriptor).map(PropertyDescriptor::getWriteMethod)
|
||||||
|
.map(method -> (FieldSetter) (obj, value) -> invokeSetter(method, obj, value))
|
||||||
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform an operation using the given field.
|
* 处理所有关联属性
|
||||||
*
|
*
|
||||||
* @param field the field to operate on
|
* @param field 属性永远都不为空
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doWith(@NonNull Field field) throws IllegalArgumentException, IllegalAccessException {
|
public void accept(Field field) {
|
||||||
if (!descriptors.containsKey(field.getName())) return;
|
|
||||||
Property property = Property.of(typeInformation, field, descriptors.get(field.getName()));
|
|
||||||
Class<?> fieldType = property.getType();
|
|
||||||
|
|
||||||
ReflectionUtils.makeAccessible(field);
|
|
||||||
|
|
||||||
Association association = AnnotatedElementUtils.findMergedAnnotation(field, Association.class);
|
Association association = AnnotatedElementUtils.findMergedAnnotation(field, Association.class);
|
||||||
if (null != association) {
|
if (null == association) return;
|
||||||
if (ClassUtils.isAssignable(fieldType, Domain.class)) {
|
FieldSetter setter = getSetter(field);
|
||||||
|
if (null == setter) return;
|
||||||
|
// 获取具体类型
|
||||||
|
Class<?> type = field.getType();
|
||||||
|
if (ClassUtils.isAssignable(type, Domain.class)) {
|
||||||
|
// 目标类型
|
||||||
|
PersistentEntity<?, ?> targetEntity = r2dbcMappingContext.getRequiredPersistentEntity(type);
|
||||||
// 一对一关联
|
// 一对一关联
|
||||||
if (StringUtils.isNotBlank(association.field())) {
|
if (StringUtils.isNotBlank(association.field())) {
|
||||||
metadata.addAssociation(property, association.field(), true);
|
// 获取内部属性
|
||||||
|
PersistentProperty<?> property = entity.getRequiredPersistentProperty(association.field());
|
||||||
|
// 添加内部关联
|
||||||
|
metadata.addAssociation(targetEntity, property, setter, true);
|
||||||
} else if (StringUtils.isNotBlank(association.foreignField())) {
|
} else if (StringUtils.isNotBlank(association.foreignField())) {
|
||||||
metadata.addAssociation(property, association.foreignField(), false);
|
// 获取外部属性
|
||||||
|
PersistentProperty<?> property = targetEntity.getRequiredPersistentProperty(association.foreignField());
|
||||||
|
// 添加外部关联
|
||||||
|
metadata.addAssociation(targetEntity, property, setter, false);
|
||||||
} else {
|
} else {
|
||||||
// 尚且不支持空白策略
|
// 都为空,从当前对象查找目标类型的reference,并自动添加关联
|
||||||
|
Optional<PersistentProperty<?>> inner = findInnerKey(type);
|
||||||
|
if (inner.isPresent()) {
|
||||||
|
metadata.addAssociation(targetEntity, inner.get(), setter, true);
|
||||||
|
} else {
|
||||||
|
findForeignKey(targetEntity).ifPresent(property -> metadata.addAssociation(targetEntity, property, setter, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ClassUtils.isAssignable(type, Collection.class)) {
|
||||||
|
// 获取真实的类型
|
||||||
|
Class<?> entityType = ResolvableType.forField(field).resolveGeneric(0);
|
||||||
|
if (null == entityType) return;
|
||||||
|
// 目标类型
|
||||||
|
PersistentEntity<?, ?> targetEntity = r2dbcMappingContext.getRequiredPersistentEntity(entityType);
|
||||||
|
// 一对多关联,仅支持外部字段
|
||||||
|
if (StringUtils.isNotBlank(association.foreignField())) {
|
||||||
|
// 获取外部属性
|
||||||
|
PersistentProperty<?> property = targetEntity.getRequiredPersistentProperty(association.foreignField());
|
||||||
|
// 添加外部关联
|
||||||
|
metadata.addCollection(targetEntity, property, setter);
|
||||||
|
} else {
|
||||||
|
// 都为空,从当前对象查找目标类型的reference,并自动添加关联
|
||||||
|
findForeignKey(targetEntity).ifPresent(property -> metadata.addCollection(targetEntity, property, setter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从当前实体查找目的实体的外键
|
||||||
|
* 从当前实体找到关联目标实体的id
|
||||||
|
*
|
||||||
|
* @param entityClass 目的实体类型
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
private Optional<PersistentProperty<?>> findInnerKey(Class<?> entityClass) {
|
||||||
|
return StreamSupport.stream(entity.getPersistentProperties(Reference.class).spliterator(), false)
|
||||||
|
.filter(property -> ClassUtils.isAssignable(entityClass, property.getRequiredAnnotation(Reference.class).value()))
|
||||||
|
.findFirst()
|
||||||
|
.map(p -> (PersistentProperty<?>) p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找目的实体的外键
|
||||||
|
* 从目标实体中找到关联本实体的id
|
||||||
|
*
|
||||||
|
* @param targetEntity 目的实体信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
private Optional<PersistentProperty<?>> findForeignKey(PersistentEntity<?, ?> targetEntity) {
|
||||||
|
Class<?> ownerEntityClass = entity.getType();
|
||||||
|
return StreamSupport.stream(targetEntity.getPersistentProperties(Reference.class).spliterator(), false)
|
||||||
|
.filter(property -> ClassUtils.isAssignable(ownerEntityClass, property.getRequiredAnnotation(Reference.class).value()))
|
||||||
|
.findFirst()
|
||||||
|
.map(p -> (PersistentProperty<?>) p);
|
||||||
}
|
}
|
||||||
} else if (ClassUtils.isAssignable(fieldType, Collection.class)) {
|
|
||||||
// 一对多关联
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.flyfish.framework.r2dbc.metadata.reference;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FieldSetter extends BiConsumer<Object, Object> {
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
package com.flyfish.framework.r2dbc.metadata.reference;
|
package com.flyfish.framework.r2dbc.metadata.reference;
|
||||||
|
|
||||||
import com.flyfish.framework.annotations.Property;
|
import com.flyfish.framework.annotations.Property;
|
||||||
|
import com.flyfish.framework.domain.base.Domain;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
import java.lang.reflect.Method;
|
import org.springframework.data.mapping.PersistentProperty;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Property("一对一关联查询")
|
@Property("一对一关联查询")
|
||||||
@ -12,37 +13,23 @@ import java.lang.reflect.Method;
|
|||||||
public class R2dbcAssociation {
|
public class R2dbcAssociation {
|
||||||
|
|
||||||
@Property("关联实体类")
|
@Property("关联实体类")
|
||||||
private Class<?> entityClass;
|
private PersistentEntity<?, ?> entity;
|
||||||
|
|
||||||
@Property("关联字段")
|
@Property("关联字段")
|
||||||
private String field;
|
private PersistentProperty<?> field;
|
||||||
|
|
||||||
@Property("目标字段")
|
@Property("目标字段")
|
||||||
private org.springframework.data.mapping.model.Property targetField;
|
private FieldSetter setter;
|
||||||
|
|
||||||
@Property("字段是否在当前实体内部")
|
@Property("字段是否在当前实体内部")
|
||||||
boolean inner;
|
boolean inner;
|
||||||
|
|
||||||
public static R2dbcAssociation of(org.springframework.data.mapping.model.Property targetField, String field, boolean inner) {
|
public static R2dbcAssociation of(PersistentEntity<?, ?> entity, PersistentProperty<?> field, FieldSetter setter, boolean inner) {
|
||||||
return new R2dbcAssociation(targetField.getType(), field, targetField, inner);
|
return new R2dbcAssociation(entity, field, setter, inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public <T extends Domain> T setValue(T obj, Object value) {
|
||||||
return targetField.hasAccessor();
|
setter.accept(obj, value);
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T setValue(T obj, Object value) {
|
|
||||||
if (null != value && targetField.hasAccessor()) {
|
|
||||||
targetField.getSetter().ifPresent(method -> invokeSetter(method, obj, value));
|
|
||||||
}
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeSetter(Method method, Object obj, Object value) {
|
|
||||||
try {
|
|
||||||
method.invoke(obj, value);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,31 @@ package com.flyfish.framework.r2dbc.metadata.reference;
|
|||||||
|
|
||||||
import com.flyfish.framework.annotations.Property;
|
import com.flyfish.framework.annotations.Property;
|
||||||
import com.flyfish.framework.domain.base.Domain;
|
import com.flyfish.framework.domain.base.Domain;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
|
import org.springframework.data.mapping.PersistentProperty;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Property("一对多关联查询")
|
@Property("一对多关联查询")
|
||||||
|
@AllArgsConstructor
|
||||||
public class R2dbcCollection {
|
public class R2dbcCollection {
|
||||||
|
|
||||||
@Property("关联实体类")
|
@Property("关联实体类")
|
||||||
private Class<? extends Domain> entityClass;
|
private PersistentEntity<?, ?> entity;
|
||||||
|
|
||||||
@Property("关联字段")
|
@Property("关联字段")
|
||||||
private String field;
|
private PersistentProperty<?> field;
|
||||||
|
|
||||||
|
@Property("目标字段")
|
||||||
|
private FieldSetter setter;
|
||||||
|
|
||||||
|
public static R2dbcCollection of(PersistentEntity<?, ?> entity, PersistentProperty<?> field, FieldSetter setter) {
|
||||||
|
return new R2dbcCollection(entity, field, setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Domain> T setValue(T obj, Object value) {
|
||||||
|
setter.accept(obj, value);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.flyfish.framework.r2dbc.repository.factory;
|
package com.flyfish.framework.r2dbc.repository.factory;
|
||||||
|
|
||||||
import com.flyfish.framework.r2dbc.repository.impl.DefaultReactiveRepositoryImpl;
|
import com.flyfish.framework.r2dbc.repository.impl.QueryingR2dbcReactiveRepository;
|
||||||
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
||||||
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
||||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||||
@ -16,12 +16,12 @@ public class DefaultReactiveRepositoryFactory extends R2dbcRepositoryFactory {
|
|||||||
*/
|
*/
|
||||||
public DefaultReactiveRepositoryFactory(R2dbcEntityOperations operations) {
|
public DefaultReactiveRepositoryFactory(R2dbcEntityOperations operations) {
|
||||||
super(operations);
|
super(operations);
|
||||||
this.setRepositoryBaseClass(DefaultReactiveRepositoryImpl.class);
|
this.setRepositoryBaseClass(QueryingR2dbcReactiveRepository.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
protected Class<?> getRepositoryBaseClass(@NonNull RepositoryMetadata metadata) {
|
protected Class<?> getRepositoryBaseClass(@NonNull RepositoryMetadata metadata) {
|
||||||
return DefaultReactiveRepositoryImpl.class;
|
return QueryingR2dbcReactiveRepository.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,10 @@ import org.springframework.data.domain.Sort;
|
|||||||
import org.springframework.data.r2dbc.convert.R2dbcConverter;
|
import org.springframework.data.r2dbc.convert.R2dbcConverter;
|
||||||
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
||||||
import org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository;
|
import org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository;
|
||||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
|
||||||
import org.springframework.data.relational.core.query.Criteria;
|
import org.springframework.data.relational.core.query.Criteria;
|
||||||
import org.springframework.data.relational.core.query.Query;
|
import org.springframework.data.relational.core.query.Query;
|
||||||
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
|
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
|
||||||
import org.springframework.data.repository.core.EntityInformation;
|
import org.springframework.data.repository.core.EntityInformation;
|
||||||
import org.springframework.data.util.Lazy;
|
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
@ -32,7 +30,7 @@ import java.util.Optional;
|
|||||||
*
|
*
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
*/
|
*/
|
||||||
public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleR2dbcRepository<T, String>
|
public class QueryingR2dbcReactiveRepository<T extends Domain> extends SimpleR2dbcRepository<T, String>
|
||||||
implements DefaultReactiveRepository<T> {
|
implements DefaultReactiveRepository<T> {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -40,8 +38,6 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleR2dbc
|
|||||||
|
|
||||||
private final R2dbcEntityOperations entityOperations;
|
private final R2dbcEntityOperations entityOperations;
|
||||||
|
|
||||||
private final Lazy<RelationalPersistentEntity<T>> persistentEntity;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造新的默认仓库
|
* 构造新的默认仓库
|
||||||
*
|
*
|
||||||
@ -49,13 +45,11 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleR2dbc
|
|||||||
* @param entityOperations 数据库操作模板
|
* @param entityOperations 数据库操作模板
|
||||||
* @param converter 转换器
|
* @param converter 转换器
|
||||||
*/
|
*/
|
||||||
public DefaultReactiveRepositoryImpl(RelationalEntityInformation<T, String> entity, R2dbcEntityOperations entityOperations, R2dbcConverter converter) {
|
public QueryingR2dbcReactiveRepository(RelationalEntityInformation<T, String> entity, R2dbcEntityOperations entityOperations, R2dbcConverter converter) {
|
||||||
super(entity, entityOperations, converter);
|
super(entity, entityOperations, converter);
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.entityOperations = entityOperations;
|
this.entityOperations = entityOperations;
|
||||||
this.persistentEntity = Lazy.of(() -> (RelationalPersistentEntity<T>) converter
|
|
||||||
.getMappingContext()
|
|
||||||
.getRequiredPersistentEntity(entity.getJavaType()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,12 +230,6 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleR2dbc
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public RelationalPersistentEntity<T> getPersistentEntity() {
|
|
||||||
return persistentEntity.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<Query> getQuery(Qo<T> qo) {
|
private Mono<Query> getQuery(Qo<T> qo) {
|
||||||
return Mono.justOrEmpty(qo.getQuery(entity));
|
return Mono.justOrEmpty(qo.getQuery(entity));
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.flyfish.framework.r2dbc;
|
package com.flyfish.framework.r2dbc;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
import com.flyfish.framework.r2dbc.config.R2dbcDataConfig;
|
import com.flyfish.framework.r2dbc.config.R2dbcDataConfig;
|
||||||
import com.flyfish.framework.r2dbc.domain.TestDO;
|
import com.flyfish.framework.r2dbc.domain.TestDO;
|
||||||
import com.flyfish.framework.r2dbc.domain.TestQO;
|
import com.flyfish.framework.r2dbc.domain.TestQO;
|
||||||
@ -26,7 +27,7 @@ public class R2DbcRepositoryTest {
|
|||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
TestQO qo = new TestQO();
|
TestQO qo = new TestQO();
|
||||||
qo.setName("2");
|
qo.setName("1");
|
||||||
// 开启关联查询
|
// 开启关联查询
|
||||||
qo.setFetchRef(true);
|
qo.setFetchRef(true);
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ public class R2DbcRepositoryTest {
|
|||||||
test.setName("测试名称");
|
test.setName("测试名称");
|
||||||
test.setOtherId("1");
|
test.setOtherId("1");
|
||||||
|
|
||||||
System.out.println(JSON.toJSONString(testRepository.insert(test).block()));
|
System.out.println(JSON.toJSONString(testRepository.insert(test).block(), SerializerFeature.PrettyFormat));
|
||||||
System.out.println(JSON.toJSONString(testRepository.findAll(qo).collectList().block()));
|
System.out.println(JSON.toJSONString(testRepository.findAll(qo).collectList().block(), SerializerFeature.PrettyFormat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,24 +6,32 @@ import com.flyfish.framework.r2dbc.domain.reference.TestAsso;
|
|||||||
import com.flyfish.framework.r2dbc.domain.reference.TestChild;
|
import com.flyfish.framework.r2dbc.domain.reference.TestChild;
|
||||||
import com.flyfish.framework.r2dbc.domain.reference.TestOther;
|
import com.flyfish.framework.r2dbc.domain.reference.TestOther;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.annotation.Reference;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
import org.springframework.data.relational.core.mapping.Column;
|
||||||
import org.springframework.data.relational.core.mapping.Table;
|
import org.springframework.data.relational.core.mapping.Table;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试实体
|
||||||
|
* 体现了所有的情况
|
||||||
|
*
|
||||||
|
* @author wangyu
|
||||||
|
*/
|
||||||
@Table("test")
|
@Table("test")
|
||||||
@Data
|
@Data
|
||||||
public class TestDO extends AuditDomain {
|
public class TestDO extends AuditDomain {
|
||||||
|
|
||||||
@Column("other_id")
|
@Column("other_id")
|
||||||
|
@Reference(TestAsso.class)
|
||||||
private String otherId;
|
private String otherId;
|
||||||
|
|
||||||
@Association(field = "otherId")
|
@Association
|
||||||
private TestAsso asso;
|
private TestAsso asso;
|
||||||
|
|
||||||
@Association(foreignField = "testId")
|
@Association
|
||||||
private TestOther other;
|
private TestOther other;
|
||||||
|
|
||||||
@Association(foreignField = "parentId")
|
@Association
|
||||||
private List<TestChild> children;
|
private List<TestChild> children;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.flyfish.framework.r2dbc.domain.reference;
|
package com.flyfish.framework.r2dbc.domain.reference;
|
||||||
|
|
||||||
import com.flyfish.framework.domain.base.AuditDomain;
|
import com.flyfish.framework.domain.base.AuditDomain;
|
||||||
|
import com.flyfish.framework.r2dbc.domain.TestDO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.annotation.Reference;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
import org.springframework.data.relational.core.mapping.Column;
|
||||||
import org.springframework.data.relational.core.mapping.Table;
|
import org.springframework.data.relational.core.mapping.Table;
|
||||||
|
|
||||||
@ -10,5 +12,6 @@ import org.springframework.data.relational.core.mapping.Table;
|
|||||||
public class TestChild extends AuditDomain {
|
public class TestChild extends AuditDomain {
|
||||||
|
|
||||||
@Column("parent_id")
|
@Column("parent_id")
|
||||||
|
@Reference(TestDO.class)
|
||||||
private String parentId;
|
private String parentId;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.flyfish.framework.r2dbc.domain.reference;
|
package com.flyfish.framework.r2dbc.domain.reference;
|
||||||
|
|
||||||
import com.flyfish.framework.annotations.relation.Association;
|
|
||||||
import com.flyfish.framework.domain.base.AuditDomain;
|
import com.flyfish.framework.domain.base.AuditDomain;
|
||||||
import com.flyfish.framework.r2dbc.domain.TestDO;
|
import com.flyfish.framework.r2dbc.domain.TestDO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.annotation.Reference;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
import org.springframework.data.relational.core.mapping.Column;
|
||||||
import org.springframework.data.relational.core.mapping.Table;
|
import org.springframework.data.relational.core.mapping.Table;
|
||||||
|
|
||||||
@ -12,5 +12,6 @@ import org.springframework.data.relational.core.mapping.Table;
|
|||||||
public class TestOther extends AuditDomain {
|
public class TestOther extends AuditDomain {
|
||||||
|
|
||||||
@Column("test_id")
|
@Column("test_id")
|
||||||
|
@Reference(TestDO.class)
|
||||||
private String testId;
|
private String testId;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
DROP TABLE IF EXISTS `test`;
|
DROP TABLE IF EXISTS `test`;
|
||||||
DROP TABLE IF EXISTS `test_child`;
|
DROP TABLE IF EXISTS `test_child`;
|
||||||
DROP TABLE IF EXISTS `test_asso`;
|
DROP TABLE IF EXISTS `test_asso`;
|
||||||
|
DROP TABLE IF EXISTS `test_other`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user