#1971 建表调整(待完善)

parent ccb96eb2
Pipeline #4608 canceled with stages
package logwire.web.bo.loader;
import com.google.common.collect.Maps;
import logwire.core.bo.annotation.*;
import logwire.core.bo.field.BizArray;
import logwire.core.bo.field.BizExpando;
import logwire.core.bo.field.BizMany;
import logwire.core.bo.field.BizText;
import logwire.core.bo.object.BizObject;
......@@ -21,12 +23,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
......@@ -52,8 +54,11 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
//先扫描到所有的 BizObject (BizObject的所有子类)
ClassPathScanningCandidateComponentProvider provider = loaderUtil.getScanningBeanProvider();
provider.setResourceLoader(new DefaultResourceLoader(classLoader));
DefaultResourceLoader resourceLoader = new DefaultResourceLoader(classLoader);
provider.setResourceLoader(resourceLoader);
provider.addIncludeFilter(loaderUtil.getAbstractTypeFilter(BizObject.class));
//找到所有bo并根据是否有BizModel注解分类
Map<Boolean, List<BeanDefinition>> isBizModel = provider.findCandidateComponents("logwire.web")
.stream()
.collect(Collectors.groupingBy(beanDefinition -> {
......@@ -65,9 +70,22 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
throw new ApplicationException("");
}
}));
List<BeanDefinition> bizModelList = isBizModel.get(true);
for (BeanDefinition beanDefinition : bizModelList) {
Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
//获取需要创建表的bean
List<BeanDefinition> bizModelBeans = isBizModel.get(true);
//获取所有不需要创建表的bean(可能为boModel的子类)
List<BeanDefinition> childrenBeans = isBizModel.get(false);
//找到拓展字段
Set<Class<?>> expandoClasses = findExpandoClasses(classLoader,resourceLoader);
//处理建表boModel,子类boModel,拓展字段之间的关系
Map<Class, BoModelRelation> boModelRelations = handleBoModel(classLoader, bizModelBeans, childrenBeans, expandoClasses);
//遍历建表的bean,并找到其拓展字段
for (BoModelRelation beanDefinition : boModelRelations.values()) {
Class<?> clazz = beanDefinition.getBoModel();
//获取类名和注解里的label
String className = Util.toLowerCaseFirst(clazz.getSimpleName());
String label = clazz.getAnnotation(BizModel.class).label();
......@@ -80,6 +98,8 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
model.setIncludeVersionField(true);
model.setIncludeDomainField(true);
initField(clazz, model, consumer);
//todo 补充子类和拓展字段
consumer.accept(model);
}
}
......@@ -92,9 +112,8 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
*/
private void initField(Class<?> clazz, Model model, Consumer<IQuery> consumer) {
Field[] fields = clazz.getDeclaredFields();
setPrimaryKey(model);
//当一个表有多个大文本字段,只需要建一次表,将多个大文本字段的值放在一张表中
Boolean isFirstText = true;
boolean isFirstText = true;
//遍历所有字段
for (Field f : fields) {
if (f.getAnnotation(Column.class) != null) {
......@@ -128,6 +147,8 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
}
}
/**
* 数组字段值存到一个列中,用逗号分隔 字段:
* owner_id/所属对象ID (BigInt)
......@@ -223,7 +244,12 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
model.addField(id);
}
/**
* 设置表名,如果label不存在,用类名
* @param className
* @param model
* @param label
*/
private void setName(String className, Model model, String label) {
if (!Strings.isNullOrEmpty(label)) {
model.setName(label);
......@@ -232,8 +258,136 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
}
}
/**
* 找到拓展字段
* @param resourceLoader
* @return
*/
private Set<Class<?>> findExpandoClasses(TenantClassLoader classLoader,ResourceLoader resourceLoader) {
ClassPathScanningCandidateComponentProvider provider = loaderUtil.getScanningBeanProvider();
provider.setResourceLoader(resourceLoader);
provider.addIncludeFilter(loaderUtil.getInterfaceTypeFilter(BizExpando.class));
Set<BeanDefinition> candidateComponents = provider.findCandidateComponents("logwire.web");
return candidateComponents
.stream()
.map(e -> {
try {
return classLoader.loadClass(e.getBeanClassName());
} catch (ClassNotFoundException classNotFoundException) {
return null;
}
})
.collect(Collectors.toSet());
}
@Override
public boolean accept(TenantProject input) {
return true;
}
/**
* 找到model和他的子类和他的拓展字段
* @param bizModelBeans 需要建表的bo
* @param childrenBeans bo的子类
* @param expandoClasses bo的拓展字段
* @return
*/
private Map<Class,BoModelRelation> handleBoModel(TenantClassLoader classLoader, List<BeanDefinition> bizModelBeans, List<BeanDefinition> childrenBeans, Set<Class<?>> expandoClasses){
Map<Class, BoModelRelation> boModel_relation = Maps.newHashMap();
//遍历所有建表bo,初始化bo关系类
bizModelBeans.forEach(e->{
try {
Class<?> clazz = classLoader.loadClass(e.getBeanClassName());
boModel_relation.put(clazz,new BoModelRelation(clazz));
} catch (ClassNotFoundException classNotFoundException) {
}
});
//遍历子类bo
childrenBeans.forEach(e->{
try {
Class<?> childClazz = classLoader.loadClass(e.getBeanClassName());
boModel_relation.entrySet()
.stream()
.filter(f->childClazz.isAssignableFrom(f.getKey()))
.forEach(f->f.getValue().addChildBo(childClazz));
} catch (ClassNotFoundException classNotFoundException) {
}
});
//遍历所有拓展字段
expandoClasses.forEach(e->{
//找到所有接口
Type[] genericInterfaces = e.getGenericInterfaces();
for (Type type:genericInterfaces) {
//找到有泛型的接口
if (type instanceof ParameterizedType){
ParameterizedType paramterizedType = (ParameterizedType) type;
//找到BizExpando接口
if (paramterizedType.getRawType().equals("logwire.core.bo.field.BizExpando")){
//找到泛型
Class clazz = (Class)paramterizedType.getActualTypeArguments()[0];
//通过泛型去找对应的boRelation
Collection<BoModelRelation> relations = boModel_relation.values();
for (BoModelRelation relation:relations) {
if (relation.checkAndAddExpando(clazz,e))
break;
}
//BizExpando接口只会实现一次,找到后即可跳出循环
break;
}
}
}
});
return boModel_relation;
}
private class BoModelRelation{
private final Class boModel;
private Set<Class> childrenBo = new HashSet<>();
private Set<Class> expando = new HashSet<>();
public boolean checkAndAddExpando(Class parameterType,Class expandoClazz){
if (parameterType.isAssignableFrom(boModel)){
addExpando(expandoClazz);
return true;
}
for (Class child:childrenBo) {
if (parameterType.isAssignableFrom(child)){
addExpando(expandoClazz);
return true;
}
}
return false;
}
public BoModelRelation(Class boModel){
this.boModel = boModel;
}
public Class getBoModel() {
return boModel;
}
public Set<Class> getChildrenBo() {
return childrenBo;
}
public Set<Class> getExpando() {
return expando;
}
public void addChildBo(Class clazz){
childrenBo.add(clazz);
}
public void addExpando(Class clazz){
expando.add(clazz);
}
}
}
......@@ -24,7 +24,10 @@ public class LoaderUtil {
public TypeFilter getAbstractTypeFilter(Class targetType) {
return new AbstractTypeFilter(targetType);
}
public TypeFilter getInterfaceTypeFilter(Class targetType) {
return new InterfaceTypeFilter(targetType);
}
public boolean isAssignableFrom(Class<?> beanClass) {
......@@ -60,6 +63,18 @@ public class LoaderUtil {
}
}
private class InterfaceTypeFilter extends AssignableTypeFilter {
public InterfaceTypeFilter(Class<?> targetType) {
super(targetType);
}
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
return// 重写父类,增加判断,排除掉指定的接口 (targetType) 本身
!metadataReader.getClassMetadata().getClassName().equals(getTargetType().getName())
&& super.match(metadataReader, metadataReaderFactory);
}
}
private class LogwireClassPathScanningCandidateComponentProvider extends ClassPathScanningCandidateComponentProvider {
public LogwireClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) {
......
package logwire.web.bo.util;
public class ClassUtil {
/**
* 校验是否实现了某个类是否实现了这个接口
* @param orign
* @param interfaceClass
* @return
*/
public static boolean isInterfaceClass(Class<?> orign,Class<?> interfaceClass){
for (Class<?> clazz:orign.getInterfaces()) {
if (clazz==interfaceClass)
return true;
}
return false;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment