package com.ctrip.platform.dal.dao.helper; import java.lang.reflect.Field; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import com.ctrip.platform.dal.dao.DalRowMapper; import com.ctrip.platform.dal.dao.annotation.Database; import com.ctrip.platform.dal.dao.annotation.Sensitive; import com.ctrip.platform.dal.dao.annotation.Type; import com.ctrip.platform.dal.exceptions.DalException; import com.ctrip.platform.dal.exceptions.ErrorCode; /** * * @author gzxia * */ public class EntityManager { private static ConcurrentHashMap<Class<?>, EntityManager> registeredManager = new ConcurrentHashMap<>(); private Class<?> clazz; private Map<String, Field> fieldMap = new HashMap<>(); private List<Integer> types = new ArrayList<>(); private boolean autoIncremental = false; private List<String> columnNameList = new ArrayList<>(); private List<String> sensitiveColumnNameList = new ArrayList<>(); private List<String> insertableColumnList = new ArrayList<>(); private List<String> updatableColumnList = new ArrayList<>(); private List<String> primaryKeyNameList = new ArrayList<String>(); private List<Field> identityList = new ArrayList<>(); private String versionColumn = null; public static <T> EntityManager getEntityManager(Class<T> clazz) throws SQLException { if(registeredManager.containsKey(clazz)) return registeredManager.get(clazz); EntityManager manager = new EntityManager(clazz); EntityManager value = registeredManager.putIfAbsent(clazz, manager); return value == null ? manager : value; } public static <T> DalRowMapper<T> getMapper(Class<T> clazz) throws SQLException { return clazz.getAnnotation(Entity.class) == null ? new DalObjectRowMapper<>(clazz) : new DalDefaultJpaMapper<T>(clazz); } private <T> EntityManager(Class<T> clazz) throws SQLException { this.clazz = clazz; Field[] allFields = clazz.getDeclaredFields(); if (null == allFields || allFields.length == 0) throw new SQLException("The entity[" + clazz.getName() +"] has no fields."); for (Field f: allFields) { Column column = f.getAnnotation(Column.class); Id id = f.getAnnotation(Id.class); if (column == null && id == null) continue; String columnName = (column == null || column.name().trim().length() == 0)? f.getName() : column.name(); if(f.getAnnotation(Type.class) == null) throw new DalException(ErrorCode.TypeNotDefined); if(fieldMap.containsKey(columnName)) throw new DalException(ErrorCode.DuplicateColumnName); f.setAccessible(true); fieldMap.put(columnName, f); columnNameList.add(columnName); types.add(f.getAnnotation(Type.class).value()); if(column == null || column.updatable()) updatableColumnList.add(columnName); if(column == null || column.insertable()) insertableColumnList.add(columnName); if(id != null) primaryKeyNameList.add(columnName); GeneratedValue generatedValue = f.getAnnotation(GeneratedValue.class); if (!autoIncremental && null != generatedValue && (generatedValue.strategy() == GenerationType.AUTO || generatedValue.strategy() == GenerationType.IDENTITY)) autoIncremental = true; if (f.getAnnotation(Id.class) != null && generatedValue != null && generatedValue.strategy() == GenerationType.AUTO) { identityList.add(f); } if (f.getAnnotation(Sensitive.class) != null) sensitiveColumnNameList.add(columnName); if (f.getAnnotation(Version.class) != null) { if(versionColumn != null) throw new DalException(ErrorCode.MoreThanOneVersionColumn); versionColumn = columnName; } } } public String getDatabaseName() throws DalException { Database db = clazz.getAnnotation(Database.class); if (db != null && db.name() != null) return db.name(); throw new DalException(ErrorCode.NoDatabaseDefined); } public <T> String getTableName() { Table table = clazz.getAnnotation(Table.class); if (table != null && table.name() != null) return table.name(); Entity entity = clazz.getAnnotation(Entity.class); if ( entity != null && (!entity.name().isEmpty()) ) return entity.name(); return clazz.getSimpleName(); } public boolean isAutoIncrement() throws SQLException { return autoIncremental; } public String[] getSensitiveColumnNames() { return sensitiveColumnNameList.toArray(new String[sensitiveColumnNameList.size()]); } public String getVersionColumn() throws DalException { return versionColumn; } public String[] getUpdatableColumnNames() { return updatableColumnList.toArray(new String[updatableColumnList.size()]); } public String[] getInsertableColumnNames() { return insertableColumnList.toArray(new String[insertableColumnList.size()]); } public String[] getPrimaryKeyNames() throws SQLException { return primaryKeyNameList.toArray(new String[primaryKeyNameList.size()]); } public Field[] getIdentity() { return identityList.toArray(new Field[identityList.size()]); } public Map<String, Field> getFieldMap() throws SQLException { return fieldMap; } public String[] getColumnNames() { return columnNameList.toArray(new String[columnNameList.size()]); } public int[] getColumnTypes() throws SQLException { int[] columnTypes = new int[types.size()]; for(int i = 0; i < types.size(); i++) columnTypes[i] = types.get(i); return columnTypes; } }