package indi.mybatis.flying.models; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Id; import org.apache.ibatis.type.JdbcType; import indi.mybatis.flying.annotations.FieldMapperAnnotation; import indi.mybatis.flying.annotations.ForeignAssociation; import indi.mybatis.flying.exception.BuildSqlException; import indi.mybatis.flying.exception.BuildSqlExceptionEnum; import indi.mybatis.flying.statics.AssociationType; import indi.mybatis.flying.statics.OpLockType; import indi.mybatis.flying.utils.JdbcTypeEnum; /** * * @date 2019年12月18日 11:56:08 * * @author 李萌 * @email [email protected] * @since JDK 1.8。 * @description Field mapping class that describes the correspondence between a * Java object field and a database table field. */ public class FieldMapper implements Mapperable { private Field field; /** * Java object field name. */ private String fieldName; /** * Database table field name. */ private String dbFieldName; /** * The JDBC type corresponding to the database field. */ private JdbcType jdbcType; /** * If it is a foreign key, it corresponds to the name of the primary key field * of the other table in the database. Blank means it's not foreign key. */ private String dbAssociationUniqueKey = ""; /** * Describes the association between this table and related table, especially * when there are other constraints other than foreign key. */ private ForeignAssociationMapper[] foreignAssociationMappers; /** * This variable corresponds to the primary key of the database table. The * default is false. */ private boolean isUniqueKey; /** * This variable corresponds to the foreign key of the database table. The * default is false. */ private boolean isForeignKey; /** * If this variable corresponds to the foreign key of the database table, the * ForeignFieldName represents the Java object field name of the related table's * primary key.Blank means it's not foreign key. */ private String foreignFieldName; /** * Whether this variable is a version optimistic lock, the default is false. */ private boolean isOpVersionLock; /** * The access path of the custom typeHandler for this variable, the default is * null. */ private String typeHandlerPath; private OpLockType opLockType = OpLockType.NULL; private String[] ignoreTag = {}; private String[] whiteListTag = {}; /** * IgnoreTag's set for this variable, the default is empty. */ private Set<String> ignoreTagSet = new HashSet<>(); /** * WhiteListTag's set for this variable, the default is empty. */ private Set<String> whiteListTagSet = new HashSet<>(); private FieldMapperAnnotation fieldMapperAnnotation; private Column column; private Id id; private boolean insertAble = true; private boolean updateAble = true; private Class<?> fieldType; private Class<?> subTarget; private boolean isDelegate = false; /** * How the tables are related (e.g. left join or right join) */ private AssociationType associationType; private FieldMapper delegate; private boolean hasDelegate = false; public void buildMapper() { if (fieldMapperAnnotation == null && column == null) { throw new BuildSqlException( BuildSqlExceptionEnum.NO_FIELD_MAPPER_ANNOTATION_OR_COLUMN_ANNOTATION.toString()); } setFieldName(field.getName()); setFieldType(field.getType()); /* * The Column annotation has the lowest priority, so it is written at the top. */ if (column != null) { setDbFieldName(getColumnName(column, field)); setJdbcType(getColumnType(column, field)); setInsertAble(column.insertable()); setUpdateAble(column.updatable()); } if (fieldMapperAnnotation != null) { setDbFieldName(fieldMapperAnnotation.dbFieldName()); setJdbcType(fieldMapperAnnotation.jdbcType()); setTypeHandlerPath(fieldMapperAnnotation.customTypeHandler()); setOpLockType(fieldMapperAnnotation.opLockType()); setUniqueKey(fieldMapperAnnotation.isUniqueKey()); setIgnoreTag(fieldMapperAnnotation.ignoreTag()); setWhiteListTag(fieldMapperAnnotation.whiteListTag()); setDbAssociationUniqueKey(fieldMapperAnnotation.dbAssociationUniqueKey()); setAssociationType(fieldMapperAnnotation.associationType()); if (fieldMapperAnnotation.associationExtra().length > 0) { ForeignAssociation[] fas = fieldMapperAnnotation.associationExtra(); ForeignAssociationMapper[] fams = new ForeignAssociationMapper[fieldMapperAnnotation .associationExtra().length]; int i = 0; for (ForeignAssociation fa : fas) { fams[i] = new ForeignAssociationMapper(fa.dbFieldName(), fa.dbAssociationFieldName(), fa.condition()); i++; } setForeignAssociationMappers(fams); } // is in delegate mode or not setDelegate(fieldMapperAnnotation.delegate()); } /* The Id has the highest priority, so it's written at the end. */ if (id != null) { setUniqueKey(true); } } public boolean buildMapper(Field field) { Annotation[] fieldAnnotations = field.getDeclaredAnnotations(); if (fieldAnnotations.length == 0) { return false; } for (Annotation an1 : fieldAnnotations) { if (an1 instanceof Id) { setId((Id) an1); } if ((an1 instanceof FieldMapperAnnotation) || (an1 instanceof Column)) { setField(field); if (an1 instanceof FieldMapperAnnotation) { setFieldMapperAnnotation((FieldMapperAnnotation) an1); } else if (an1 instanceof Column) { setColumn((Column) an1); } } } buildMapper(); return true; } public static String getColumnName(Column column, Field field) { if (!"".equals(column.name())) { return column.name(); } else { return field.getName(); } } public static JdbcType getColumnType(Column column, Field field) { if (!"".equals(column.columnDefinition().trim())) { String columnDefinition = column.columnDefinition().indexOf(" ") > -1 ? column.columnDefinition().substring(0, column.columnDefinition().indexOf(" ")) : column.columnDefinition(); JdbcType jdbcType = JdbcTypeEnum.forName(columnDefinition); if (jdbcType != null) { return jdbcType; } } if (TypeJdbcTypeConverter.map.get(field.getType()) != null) { return TypeJdbcTypeConverter.map.get(field.getType()); } else { return JdbcType.OTHER; } } @Override public String getDbFieldName() { return dbFieldName; } public void setDbFieldName(String dbFieldName) { this.dbFieldName = dbFieldName; } @Override public String getFieldName() { return fieldName; } public void setFieldName(String fieldName) { this.fieldName = fieldName; } @Override public JdbcType getJdbcType() { return jdbcType; } public void setJdbcType(JdbcType jdbcType) { this.jdbcType = jdbcType; } @Override public String getDbAssociationUniqueKey() { return dbAssociationUniqueKey; } public void setDbAssociationUniqueKey(String dbAssociationUniqueKey) { this.dbAssociationUniqueKey = dbAssociationUniqueKey; } @Override public ForeignAssociationMapper[] getForeignAssociationMappers() { return foreignAssociationMappers; } public void setForeignAssociationMappers(ForeignAssociationMapper[] foreignAssociationMappers) { this.foreignAssociationMappers = foreignAssociationMappers; } public boolean isUniqueKey() { return isUniqueKey; } public void setUniqueKey(boolean isUniqueKey) { this.isUniqueKey = isUniqueKey; } @Override public boolean isForeignKey() { return isForeignKey; } public void setForeignKey(boolean isForeignKey) { this.isForeignKey = isForeignKey; } @Override public String getForeignFieldName() { return foreignFieldName; } public void setForeignFieldName(String foreignFieldName) { this.foreignFieldName = foreignFieldName; } public boolean isOpVersionLock() { return isOpVersionLock; } public void setOpVersionLock(boolean isOpVersionLock) { this.isOpVersionLock = isOpVersionLock; } @Override public Set<String> getIgnoreTagSet() { return ignoreTagSet; } public void setIgnoreTagSet(Set<String> ignoreTagSet) { this.ignoreTagSet = ignoreTagSet; } @Override public Set<String> getWhiteListTagSet() { return whiteListTagSet; } public void setWhiteListTagSet(Set<String> whiteListTagSet) { this.whiteListTagSet = whiteListTagSet; } @Override public String getTypeHandlerPath() { return typeHandlerPath; } public void setTypeHandlerPath(Class<?> typeHandler) { if (!Void.class.equals(typeHandler)) { this.typeHandlerPath = typeHandler.getName(); } } public FieldMapperAnnotation getFieldMapperAnnotation() { return fieldMapperAnnotation; } public void setFieldMapperAnnotation(FieldMapperAnnotation fieldMapperAnnotation) { this.fieldMapperAnnotation = fieldMapperAnnotation; } public Column getColumn() { return column; } public void setColumn(Column column) { this.column = column; } public Id getId() { return id; } public void setId(Id id) { this.id = id; } public OpLockType getOpLockType() { return opLockType; } public void setOpLockType(OpLockType opLockType) { this.opLockType = opLockType; } public String[] getIgnoreTag() { return ignoreTag; } public void setIgnoreTag(String[] ignoreTag) { this.ignoreTag = ignoreTag; } public String[] getWhiteListTag() { return whiteListTag; } public void setWhiteListTag(String[] whiteListTag) { this.whiteListTag = whiteListTag; } public Field getField() { return field; } public void setField(Field field) { this.field = field; } public boolean isInsertAble() { return insertAble; } public void setInsertAble(boolean insertAble) { this.insertAble = insertAble; } public boolean isUpdateAble() { return updateAble; } public void setUpdateAble(boolean updateAble) { this.updateAble = updateAble; } @Override public Class<?> getFieldType() { return fieldType; } public void setFieldType(Class<?> fieldType) { this.fieldType = fieldType; } @Override public Class<?> getSubTarget() { return subTarget; } public AssociationType getAssociationType() { return associationType; } public void setAssociationType(AssociationType associationType) { this.associationType = associationType; } public boolean isDelegate() { return isDelegate; } public void setDelegate(boolean isDelegate) { this.isDelegate = isDelegate; } public FieldMapper getDelegate() { return delegate; } public void setDelegate(FieldMapper delegate) { this.delegate = delegate; } public boolean isHasDelegate() { return hasDelegate; } public void setHasDelegate(boolean hasDelegate) { this.hasDelegate = hasDelegate; } }