All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.easycodebox.jdbc.config.Configuration Maven / Gradle / Ivy

package com.easycodebox.jdbc.config;

import com.easycodebox.common.error.BaseException;
import com.easycodebox.common.validate.Assert;
import com.easycodebox.jdbc.*;
import com.easycodebox.jdbc.dialect.Dialect;
import com.easycodebox.jdbc.dialect.MySqlDialect;
import com.easycodebox.jdbc.rule.DefaultTableRule;
import com.easycodebox.jdbc.rule.TableRule;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.easycodebox.jdbc.util.AnnotateUtils.*;

/**
 * @author WangXiaoJin
 *
 */
public class Configuration implements Serializable {

	protected static ConcurrentHashMap tables = new ConcurrentHashMap<>();
	protected static ConcurrentHashMap> tableNames = new ConcurrentHashMap<>();

	public static final Dialect dialect = new MySqlDialect();
	public static final TableRule tableRule = new DefaultTableRule();
	
	private static Set filterFields = new HashSet<>();
	
	public static void addAnnotatedClass(Class clazz) {
		if(tables.containsKey(clazz.getName()))
			return;
		Table table = new Table();
		table.setEntityType(clazz);
		
		fitTableAnno(table, clazz);
		
		for(Class curClazz = clazz; 
				curClazz != null && curClazz != Object.class; 
				curClazz = curClazz.getSuperclass()) {
			
			Field[] fields = curClazz.getDeclaredFields();
			for(Field field : fields) {
				//排除掉final 和 static 修饰的属性
				if(Modifier.isFinal(field.getModifiers())
						|| Modifier.isStatic(field.getModifiers())) 
					continue;
				if(!filterFields.contains(field.getName())) {
					//获取Transient注解
					if(isTransient(field))
						continue;
					//处理关联关系ManyToOne、OneToOne等
					if(fitAssociatedColumn(table, field))
						continue;
					fitColumn(table, field);
				}
			}
		}
		
		tables.putIfAbsent(clazz.getName(), table);
		tableNames.putIfAbsent(table.getName(), clazz);
	}
	
	/**
	 * 加载完所有的entity class后需要调用此方法来初始化各个entity之间的关联关系
	 * 分析JoinColumn、JoinColumns、JoinTable注解,自动加上默认值
	 */
	public static void initTablesAssociate() {
		for(Table table : tables.values()) {
			
			Map columns = table.getAssociatedColumns();
			for(AssociatedColumn ac : columns.values()) {
				if(ac instanceof OneToOne) {
					OneToOne oneToOne = (OneToOne)ac;
					if(oneToOne.getMappedBy() != null) {
						//关联关系有mappedBy属性,执行逻辑待考虑
					}else {
						JoinColumnObj[] joinColumns = autoAssociatedColumn(
								ac.getJoinColumns(), table, 
								getTable(oneToOne.getAssociatedClass()));
						ac.setJoinColumns(joinColumns);
					}
				}else if(ac instanceof OneToMany) {
					OneToMany oneToMany = (OneToMany)ac;
					if(oneToMany.getMappedBy() != null) {
						//关联关系有mappedBy属性,执行逻辑待考虑
					}else {
						JoinColumnObj[] joinColumns = autoAssociatedColumn(
								ac.getJoinColumns(), 
								getTable(oneToMany.getAssociatedClass()), table);
						ac.setJoinColumns(joinColumns);
					}
				}else if(ac instanceof ManyToOne) {
					ManyToOne manyToOne = (ManyToOne)ac;
					JoinColumnObj[] joinColumns = autoAssociatedColumn(
							ac.getJoinColumns(), table, 
							getTable(manyToOne.getAssociatedClass()));
					ac.setJoinColumns(joinColumns);
				}else if(ac instanceof ManyToMany) {
					ManyToMany manyToMany = (ManyToMany)ac;
					if(manyToMany.getMappedBy() != null) {
						//关联关系有mappedBy属性,执行逻辑待考虑
					}else {
						Class entity = getEntityByTableName(manyToMany.getJoinTableName());
						Table joinTable = entity != null ? getTable(entity) 
								: new Table(manyToMany.getJoinTableName());
						JoinColumnObj[] joinColumns = autoAssociatedColumn(
								ac.getJoinColumns(), joinTable, table);
						ac.setJoinColumns(joinColumns);
						
						Table inverseTable = getTable(manyToMany.getAssociatedClass());
						JoinColumnObj[] inverseJoinColumns = autoAssociatedColumn(
								manyToMany.getInverseJoinColumns(), joinTable, inverseTable);
						manyToMany.setInverseJoinColumns(inverseJoinColumns);
					}
				}else {
					throw new BaseException("unknown AssociatedColumn class - {0}.", ac.getClass());
				}
			}
			
		}
	}
	
	/**
	 * 处理关联关系列,自动补全未初始化的属性,返回最新的处理过的JoinColumnObj[]
	 */
	private static JoinColumnObj[] autoAssociatedColumn(JoinColumnObj[] joinColumns, Table table, 
			Table refTable) {
		if(joinColumns == null || joinColumns.length == 0) {
			return generateJoinColumns(table, refTable);
		}
		List pks = refTable.getPrimaryKeys();
		Assert.notEmpty(pks, "Entity {0} has no pk.", refTable.getEntityType());
		for(JoinColumnObj jc : joinColumns) {
			if(pks.size() > 1 && (jc.getName() == null || jc.getReferencedColumnName() == null)) {
				//自动创建joinColumn,并覆盖以前的
				return generateJoinColumns(table, refTable);
			}
			if(jc.getName() == null) {
				jc.setName(tableRule.generateFk(refTable.getName(), pks.get(0).getSqlName()));
			}
			if(jc.getReferencedColumnName() == null) {
				jc.setReferencedColumnName(pks.get(0).getSqlName());
			}
			if(jc.getTable() == null) {
				jc.setTable(table.getName());
			}
		}
		return joinColumns;
	}
	
	/**
	 * 如果关联注解(ManyToMany、ManyToOne、OneToOne等)没有JoinColumn或者JoinColumns注解时,则调用此方法自动生成JoinColumn。
	 * 如果关联表是联合主键,且JoinColumn没有初始化name或referencedColumnName属性时也会执行此方法
	 * @param table		主表(有外键的表)
	 * @param refTable	外键引用表
	 * @return
	 */
	private static JoinColumnObj[] generateJoinColumns(Table table, Table refTable) {
		List refPks = refTable.getPrimaryKeys();
		JoinColumnObj[] objs = new JoinColumnObj[refPks.size()];
		for(int i = 0; i < refPks.size(); i++) {
			JoinColumnObj jco = JoinColumnObj.instance();
			jco.setTable(table.getName());
			jco.setName(tableRule.generateFk(refTable.getName(), refPks.get(i).getSqlName()));
			jco.setReferencedColumnName(refPks.get(i).getSqlName());
			objs[i] = jco;
		}
		return objs;
	}
	
	public static Table getTable(Class entityClass) {
		return tables.get(entityClass.getName());
	}
	
	public static Table getTable(String entityName) {
		return tables.get(entityName);
	}
	
	public static Class getEntityByTableName(String tableName) {
		return tableNames.get(tableName);
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy