mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-11-02 16:22:27 +00:00
#919 - io.ebean package initial
This commit is contained in:
1 parent
5821dc96b9
commit
971e2dc91b
2134 files changed
+10721
-8652
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,35 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Collects Deployment information on Embedded beans.
|
||||
* <p>
|
||||
* Typically collects the overridden column names mapped
|
||||
* to the Embedded bean.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployBeanEmbedded {
|
||||
|
||||
/**
|
||||
* A map of property names to dbColumns.
|
||||
*/
|
||||
private final Map<String, String> propMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Set a Map of property names to dbColumns.
|
||||
*/
|
||||
public void putAll(Map<String, String> propertyColumnMap) {
|
||||
propMap.putAll(propertyColumnMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of property names to dbColumns.
|
||||
*/
|
||||
public Map<String, String> getPropertyColumnMap() {
|
||||
return propMap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,992 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.annotation.CreatedTimestamp;
|
||||
import io.ebean.annotation.DocCode;
|
||||
import io.ebean.annotation.DocProperty;
|
||||
import io.ebean.annotation.DocSortable;
|
||||
import io.ebean.annotation.SoftDelete;
|
||||
import io.ebean.annotation.UpdatedTimestamp;
|
||||
import io.ebean.annotation.WhenCreated;
|
||||
import io.ebean.annotation.WhenModified;
|
||||
import io.ebean.annotation.WhoCreated;
|
||||
import io.ebean.annotation.WhoModified;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.dbplatform.DbDefaultValue;
|
||||
import io.ebean.config.dbplatform.DbEncrypt;
|
||||
import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.DeployDocPropertyOptions;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
import io.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.server.properties.BeanPropertyGetter;
|
||||
import io.ebeaninternal.server.properties.BeanPropertySetter;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
import io.ebeaninternal.server.type.ScalarTypeWrapper;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyOptions;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Description of a property of a bean. Includes its deployment information such
|
||||
* as database column mapping information.
|
||||
*/
|
||||
public class DeployBeanProperty {
|
||||
|
||||
private static final int ID_ORDER = 1000000;
|
||||
private static final int UNIDIRECTIONAL_ORDER = 100000;
|
||||
private static final int AUDITCOLUMN_ORDER = -1000000;
|
||||
private static final int VERSIONCOLUMN_ORDER = -1000000;
|
||||
|
||||
/**
|
||||
* Flag to mark this at part of the unique id.
|
||||
*/
|
||||
private boolean id;
|
||||
|
||||
/**
|
||||
* Flag to mark the property as embedded. This could be on
|
||||
* BeanPropertyAssocOne rather than here. Put it here for checking Id type
|
||||
* (embedded or not).
|
||||
*/
|
||||
private boolean embedded;
|
||||
|
||||
/**
|
||||
* Flag indicating if this the version property.
|
||||
*/
|
||||
private boolean versionColumn;
|
||||
|
||||
private boolean fetchEager = true;
|
||||
|
||||
/**
|
||||
* Set if this property is nullable.
|
||||
*/
|
||||
private boolean nullable = true;
|
||||
|
||||
private boolean unique;
|
||||
|
||||
private boolean discriminator;
|
||||
|
||||
/**
|
||||
* The length or precision of the DB column.
|
||||
*/
|
||||
private int dbLength;
|
||||
|
||||
private int dbScale;
|
||||
|
||||
private String dbColumnDefn;
|
||||
|
||||
private boolean isTransient;
|
||||
|
||||
private boolean localEncrypted;
|
||||
|
||||
private boolean jsonSerialize = true;
|
||||
private boolean jsonDeserialize = true;
|
||||
|
||||
private boolean dbEncrypted;
|
||||
private DbEncryptFunction dbEncryptFunction;
|
||||
|
||||
private int dbEncryptedType;
|
||||
|
||||
private String dbBind = "?";
|
||||
|
||||
/**
|
||||
* Is this property include in database resultSet.
|
||||
*/
|
||||
private boolean dbRead;
|
||||
|
||||
/**
|
||||
* Include this in DB insert.
|
||||
*/
|
||||
private boolean dbInsertable;
|
||||
|
||||
/**
|
||||
* Include this in a DB update.
|
||||
*/
|
||||
private boolean dbUpdateable;
|
||||
|
||||
private DeployTableJoin secondaryTableJoin;
|
||||
|
||||
private String secondaryTableJoinPrefix;
|
||||
|
||||
/**
|
||||
* Set to true if this property is based on a secondary table.
|
||||
*/
|
||||
private String secondaryTable;
|
||||
|
||||
/**
|
||||
* The type that owns this property.
|
||||
*/
|
||||
private Class<?> owningType;
|
||||
|
||||
/**
|
||||
* True if the property is a Clob, Blob LongVarchar or LongVarbinary.
|
||||
*/
|
||||
private boolean lob;
|
||||
|
||||
private boolean naturalKey;
|
||||
|
||||
/**
|
||||
* The logical bean property name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The reflected field.
|
||||
*/
|
||||
private Field field;
|
||||
|
||||
/**
|
||||
* The bean type.
|
||||
*/
|
||||
private final Class<?> propertyType;
|
||||
|
||||
private final Type genericType;
|
||||
|
||||
/**
|
||||
* Set for Non-JDBC types to provide logical to db type conversion.
|
||||
*/
|
||||
private ScalarType<?> scalarType;
|
||||
|
||||
/**
|
||||
* The database column. This can include quoted identifiers.
|
||||
*/
|
||||
private String dbColumn;
|
||||
|
||||
private String aggregationPrefix;
|
||||
private String aggregation;
|
||||
|
||||
private String sqlFormulaSelect;
|
||||
private String sqlFormulaJoin;
|
||||
|
||||
/**
|
||||
* The jdbc data type this maps to.
|
||||
*/
|
||||
private int dbType;
|
||||
|
||||
private DeployDocPropertyOptions docMapping = new DeployDocPropertyOptions();
|
||||
|
||||
/**
|
||||
* The method used to read the property.
|
||||
*/
|
||||
private Method readMethod;
|
||||
|
||||
private int propertyIndex;
|
||||
|
||||
private BeanPropertyGetter getter;
|
||||
|
||||
private BeanPropertySetter setter;
|
||||
|
||||
/**
|
||||
* Generator for insert or update timestamp etc.
|
||||
*/
|
||||
private GeneratedProperty generatedProperty;
|
||||
|
||||
protected final DeployBeanDescriptor<?> desc;
|
||||
|
||||
private boolean undirectionalShadow;
|
||||
|
||||
private int sortOrder;
|
||||
|
||||
private boolean excludedFromHistory;
|
||||
|
||||
private boolean tenantId;
|
||||
|
||||
private boolean draft;
|
||||
private boolean draftOnly;
|
||||
private boolean draftDirty;
|
||||
private boolean draftReset;
|
||||
|
||||
private boolean softDelete;
|
||||
private boolean unmappedJson;
|
||||
|
||||
private String dbComment;
|
||||
|
||||
private String dbColumnDefault;
|
||||
|
||||
public DeployBeanProperty(DeployBeanDescriptor<?> desc, Class<?> propertyType, ScalarType<?> scalarType, ScalarTypeConverter<?, ?> typeConverter) {
|
||||
this.desc = desc;
|
||||
this.propertyType = propertyType;
|
||||
this.genericType = null;
|
||||
this.scalarType = wrapScalarType(propertyType, scalarType, typeConverter);
|
||||
this.dbType = (scalarType == null) ? 0 : scalarType.getJdbcType();
|
||||
}
|
||||
|
||||
public DeployBeanProperty(DeployBeanDescriptor<?> desc, Class<?> propertyType, Type genericType) {
|
||||
this.desc = desc;
|
||||
this.propertyType = propertyType;
|
||||
this.genericType = genericType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the ScalarType using a ScalarTypeConverter.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private ScalarType<?> wrapScalarType(Class<?> propertyType, ScalarType<?> scalarType, ScalarTypeConverter<?, ?> typeConverter) {
|
||||
if (typeConverter == null) {
|
||||
return scalarType;
|
||||
}
|
||||
return new ScalarTypeWrapper(propertyType, scalarType, typeConverter);
|
||||
}
|
||||
|
||||
public int getSortOverride() {
|
||||
if (field == null) {
|
||||
return 0;
|
||||
}
|
||||
if (AnnotationBase.findAnnotation(field, Id.class) != null) {
|
||||
return ID_ORDER;
|
||||
} else if (AnnotationBase.findAnnotation(field, EmbeddedId.class) != null) {
|
||||
return ID_ORDER;
|
||||
} else if (undirectionalShadow) {
|
||||
return UNIDIRECTIONAL_ORDER;
|
||||
} else if (isAuditProperty()) {
|
||||
return AUDITCOLUMN_ORDER;
|
||||
} else if (AnnotationBase.findAnnotation(field, Version.class) != null) {
|
||||
return VERSIONCOLUMN_ORDER;
|
||||
} else if (AnnotationBase.findAnnotation(field, SoftDelete.class) != null) {
|
||||
return VERSIONCOLUMN_ORDER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean isAuditProperty() {
|
||||
return (AnnotationBase.findAnnotation(field, WhenCreated.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, WhenModified.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, WhoModified.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, WhoCreated.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, UpdatedTimestamp.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, CreatedTimestamp.class) != null);
|
||||
}
|
||||
|
||||
public String getFullBeanName() {
|
||||
return desc.getFullName() + "." + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB column length for character columns.
|
||||
* <p>
|
||||
* Note if there is no length explicitly defined then the scalarType is
|
||||
* checked to see if that has one (primarily to support putting a length on
|
||||
* Enum types).
|
||||
* </p>
|
||||
*/
|
||||
public int getDbLength() {
|
||||
if (dbLength == 0 && scalarType != null) {
|
||||
return scalarType.getLength();
|
||||
}
|
||||
|
||||
return dbLength;
|
||||
}
|
||||
|
||||
public boolean isJsonSerialize() {
|
||||
return jsonSerialize;
|
||||
}
|
||||
|
||||
public void setJsonSerialize(boolean jsonSerialize) {
|
||||
this.jsonSerialize = jsonSerialize;
|
||||
}
|
||||
|
||||
public boolean isJsonDeserialize() {
|
||||
return jsonDeserialize;
|
||||
}
|
||||
|
||||
public void setJsonDeserialize(boolean jsonDeserialize) {
|
||||
this.jsonDeserialize = jsonDeserialize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sortOrder for the properties.
|
||||
*/
|
||||
public int getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sortOrder for the properties.
|
||||
*/
|
||||
public void setSortOrder(int sortOrder) {
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a placeholder property for a unidirectional relationship.
|
||||
*/
|
||||
public boolean isUndirectionalShadow() {
|
||||
return undirectionalShadow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this property as a placeholder for a unidirectional relationship.
|
||||
*/
|
||||
public void setUndirectionalShadow() {
|
||||
this.undirectionalShadow = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this property as mapping to the discriminator column.
|
||||
*/
|
||||
public void setDiscriminator() {
|
||||
this.discriminator = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property maps to the inheritance discriminator column.s
|
||||
*/
|
||||
public boolean isDiscriminator() {
|
||||
return discriminator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is encrypted in java rather than in the DB.
|
||||
*/
|
||||
public boolean isLocalEncrypted() {
|
||||
return localEncrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true when the property is encrypted in java rather than in the DB.
|
||||
*/
|
||||
public void setLocalEncrypted() {
|
||||
this.localEncrypted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB column length for character columns.
|
||||
*/
|
||||
public void setDbLength(int dbLength) {
|
||||
this.dbLength = dbLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Db scale for numeric columns.
|
||||
*/
|
||||
public int getDbScale() {
|
||||
return dbScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Db scale for numeric columns.
|
||||
*/
|
||||
public void setDbScale(int dbScale) {
|
||||
this.dbScale = dbScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB column definition if defined.
|
||||
*/
|
||||
public String getDbColumnDefn() {
|
||||
return dbColumnDefn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a specific DB column definition.
|
||||
*/
|
||||
public void setDbColumnDefn(String dbColumnDefn) {
|
||||
if (dbColumnDefn == null || dbColumnDefn.trim().isEmpty()) {
|
||||
this.dbColumnDefn = null;
|
||||
} else {
|
||||
this.dbColumnDefn = InternString.intern(dbColumnDefn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scalarType. This returns null for native JDBC types, otherwise
|
||||
* it is used to convert between logical types and jdbc types.
|
||||
*/
|
||||
public ScalarType<?> getScalarType() {
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
public void setScalarType(ScalarType<?> scalarType) {
|
||||
this.scalarType = scalarType;
|
||||
}
|
||||
|
||||
public int getPropertyIndex() {
|
||||
return propertyIndex;
|
||||
}
|
||||
|
||||
public void setPropertyIndex(int propertyIndex) {
|
||||
this.propertyIndex = propertyIndex;
|
||||
}
|
||||
|
||||
public BeanPropertyGetter getGetter() {
|
||||
return getter;
|
||||
}
|
||||
|
||||
public BeanPropertySetter getSetter() {
|
||||
return setter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the getter method.
|
||||
*/
|
||||
public Method getReadMethod() {
|
||||
return readMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to the owning type form a Inheritance heirarchy.
|
||||
*/
|
||||
public void setOwningType(Class<?> owningType) {
|
||||
this.owningType = owningType;
|
||||
}
|
||||
|
||||
public Class<?> getOwningType() {
|
||||
return owningType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is local to this type - aka not from a super type.
|
||||
*/
|
||||
public boolean isLocal() {
|
||||
return owningType == null || owningType.equals(desc.getBeanType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the getter used to read the property value from a bean.
|
||||
*/
|
||||
public void setGetter(BeanPropertyGetter getter) {
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the setter used to set the property value to a bean.
|
||||
*/
|
||||
public void setSetter(BeanPropertySetter setter) {
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the property.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the property.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = InternString.intern(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean Field associated with this property.
|
||||
*/
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean Field associated with this property.
|
||||
*/
|
||||
public void setField(Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public boolean isNaturalKey() {
|
||||
return naturalKey;
|
||||
}
|
||||
|
||||
public void setNaturalKey() {
|
||||
this.naturalKey = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the GeneratedValue. Used to generate update timestamp etc.
|
||||
*/
|
||||
public GeneratedProperty getGeneratedProperty() {
|
||||
return generatedProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the GeneratedValue. Used to generate update timestamp etc.
|
||||
*/
|
||||
public void setGeneratedProperty(GeneratedProperty generatedValue) {
|
||||
this.generatedProperty = generatedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property is mandatory.
|
||||
*/
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the not nullable of this property.
|
||||
*/
|
||||
public void setNullable(boolean isNullable) {
|
||||
this.nullable = isNullable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DB column is unique.
|
||||
*/
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the DB column is unique.
|
||||
*/
|
||||
public void setUnique(boolean unique) {
|
||||
this.unique = unique;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a version column used for concurrency checking.
|
||||
*/
|
||||
public boolean isVersionColumn() {
|
||||
return versionColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if this is a version column used for concurrency checking.
|
||||
*/
|
||||
public void setVersionColumn() {
|
||||
this.versionColumn = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this should be eager fetched by default.
|
||||
*/
|
||||
public boolean isFetchEager() {
|
||||
return fetchEager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default fetch type for this property.
|
||||
*/
|
||||
public void setFetchType(FetchType fetchType) {
|
||||
this.fetchEager = FetchType.EAGER.equals(fetchType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the formula this property is based on.
|
||||
*/
|
||||
public String getSqlFormulaSelect() {
|
||||
return sqlFormulaSelect;
|
||||
}
|
||||
|
||||
public String getSqlFormulaJoin() {
|
||||
return sqlFormulaJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* The property is based on a formula.
|
||||
*/
|
||||
public void setSqlFormula(String formulaSelect, String formulaJoin) {
|
||||
this.sqlFormulaSelect = formulaSelect;
|
||||
this.sqlFormulaJoin = formulaJoin.equals("") ? null : formulaJoin;
|
||||
this.dbRead = true;
|
||||
this.dbInsertable = false;
|
||||
this.dbUpdateable = false;
|
||||
}
|
||||
|
||||
|
||||
public boolean isAggregation() {
|
||||
return aggregation != null;
|
||||
}
|
||||
|
||||
public String getAggregation() {
|
||||
return aggregation;
|
||||
}
|
||||
|
||||
public void setAggregation(String aggregation) {
|
||||
this.aggregation = aggregation;
|
||||
this.dbRead = true;
|
||||
this.dbInsertable = false;
|
||||
this.dbUpdateable = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path to the aggregation.
|
||||
*/
|
||||
public void setAggregationPrefix(String aggregationPrefix) {
|
||||
this.aggregationPrefix = aggregationPrefix;
|
||||
this.aggregation = aggregation.replace(aggregationPrefix, "u1");
|
||||
}
|
||||
|
||||
public String getElPrefix() {
|
||||
if (aggregation != null) {
|
||||
return aggregationPrefix;
|
||||
} else {
|
||||
return secondaryTableJoinPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
public String getElPlaceHolder() {
|
||||
if (aggregation != null) {
|
||||
return aggregation;
|
||||
} else if (sqlFormulaSelect != null) {
|
||||
return sqlFormulaSelect;
|
||||
} else {
|
||||
if (secondaryTableJoinPrefix != null) {
|
||||
return "${" + secondaryTableJoinPrefix + "}" + getDbColumn();
|
||||
}
|
||||
// prepend table alias placeholder
|
||||
return ElPropertyValue.ROOT_ELPREFIX + getDbColumn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The database column name this is mapped to.
|
||||
*/
|
||||
public String getDbColumn() {
|
||||
if (sqlFormulaSelect != null) {
|
||||
return sqlFormulaSelect;
|
||||
}
|
||||
if (aggregation != null) {
|
||||
return aggregation;
|
||||
}
|
||||
return dbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database column name this is mapped to.
|
||||
*/
|
||||
public void setDbColumn(String dbColumn) {
|
||||
this.dbColumn = InternString.intern(dbColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database jdbc data type this is mapped to.
|
||||
*/
|
||||
public int getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database jdbc data type this is mapped to.
|
||||
*/
|
||||
public void setDbType(int dbType) {
|
||||
this.dbType = dbType;
|
||||
this.lob = BeanProperty.isLobType(dbType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is mapped to a Clob Blob LongVarchar or
|
||||
* LongVarbinary.
|
||||
*/
|
||||
public boolean isLob() {
|
||||
return lob;
|
||||
}
|
||||
|
||||
public boolean isDbNumberType() {
|
||||
return isNumericType(dbType);
|
||||
}
|
||||
|
||||
private boolean isNumericType(int type) {
|
||||
switch (type) {
|
||||
case Types.BIGINT:
|
||||
return true;
|
||||
case Types.DECIMAL:
|
||||
return true;
|
||||
case Types.DOUBLE:
|
||||
return true;
|
||||
case Types.FLOAT:
|
||||
return true;
|
||||
case Types.INTEGER:
|
||||
return true;
|
||||
case Types.NUMERIC:
|
||||
return true;
|
||||
case Types.REAL:
|
||||
return true;
|
||||
case Types.SMALLINT:
|
||||
return true;
|
||||
case Types.TINYINT:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property is based on a secondary table.
|
||||
*/
|
||||
public boolean isSecondaryTable() {
|
||||
return secondaryTable != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the secondary table this property is associated with.
|
||||
*/
|
||||
public String getSecondaryTable() {
|
||||
return secondaryTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this property is included in persisting.
|
||||
*/
|
||||
public void setSecondaryTable(String secondaryTable) {
|
||||
this.secondaryTable = secondaryTable;
|
||||
this.dbInsertable = false;
|
||||
this.dbUpdateable = false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public String getSecondaryTableJoinPrefix() {
|
||||
return secondaryTableJoinPrefix;
|
||||
}
|
||||
|
||||
public DeployTableJoin getSecondaryTableJoin() {
|
||||
return secondaryTableJoin;
|
||||
}
|
||||
|
||||
public void setSecondaryTableJoin(DeployTableJoin secondaryTableJoin, String prefix) {
|
||||
this.secondaryTableJoin = secondaryTableJoin;
|
||||
this.secondaryTableJoinPrefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB Bind parameter. Typically is "?" but can be different for
|
||||
* encrypted bind.
|
||||
*/
|
||||
public String getDbBind() {
|
||||
return dbBind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property is encrypted in the DB.
|
||||
*/
|
||||
public boolean isDbEncrypted() {
|
||||
return dbEncrypted;
|
||||
}
|
||||
|
||||
public DbEncryptFunction getDbEncryptFunction() {
|
||||
return dbEncryptFunction;
|
||||
}
|
||||
|
||||
public void setDbEncryptFunction(DbEncryptFunction dbEncryptFunction, DbEncrypt dbEncrypt, int dbLen) {
|
||||
this.dbEncryptFunction = dbEncryptFunction;
|
||||
this.dbEncrypted = true;
|
||||
this.dbBind = dbEncryptFunction.getEncryptBindSql();
|
||||
|
||||
this.dbEncryptedType = isLob() ? Types.BLOB : dbEncrypt.getEncryptDbType();
|
||||
if (dbLen > 0) {
|
||||
setDbLength(dbLen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB type for the encrypted property. This can differ from the
|
||||
* logical type (String encrypted and stored in a VARBINARY)
|
||||
*/
|
||||
public int getDbEncryptedType() {
|
||||
return dbEncryptedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property is included in database queries.
|
||||
*/
|
||||
public boolean isDbRead() {
|
||||
return dbRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this property is included in database queries.
|
||||
*/
|
||||
public void setDbRead(boolean isDBRead) {
|
||||
this.dbRead = isDBRead;
|
||||
}
|
||||
|
||||
public boolean isDbInsertable() {
|
||||
return dbInsertable;
|
||||
}
|
||||
|
||||
public void setDbInsertable(boolean insertable) {
|
||||
this.dbInsertable = insertable;
|
||||
}
|
||||
|
||||
public boolean isDbUpdateable() {
|
||||
return dbUpdateable;
|
||||
}
|
||||
|
||||
public void setDbUpdateable(boolean updateable) {
|
||||
this.dbUpdateable = updateable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is transient.
|
||||
*/
|
||||
public boolean isTransient() {
|
||||
return isTransient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the property explicitly as a transient property.
|
||||
*/
|
||||
public void setTransient() {
|
||||
this.isTransient = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean read method.
|
||||
* <p>
|
||||
* NB: That a BeanReflectGetter is used to actually perform the getting of
|
||||
* property values from a bean. This is due to performance considerations.
|
||||
* </p>
|
||||
*/
|
||||
public void setReadMethod(Method readMethod) {
|
||||
this.readMethod = readMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property type.
|
||||
*/
|
||||
public Class<?> getPropertyType() {
|
||||
return propertyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the generic type for this property.
|
||||
*/
|
||||
public Type getGenericType() {
|
||||
return genericType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is included in the unique id.
|
||||
*/
|
||||
public boolean isId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is included in the unique id.
|
||||
*/
|
||||
public void setId() {
|
||||
this.id = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is an Embedded property. In this case it shares the
|
||||
* table and pk of its owner object.
|
||||
*/
|
||||
public boolean isEmbedded() {
|
||||
return embedded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is an embedded property.
|
||||
*/
|
||||
public void setEmbedded() {
|
||||
this.embedded = true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return desc.getFullName() + "." + name;
|
||||
}
|
||||
|
||||
public boolean isExcludedFromHistory() {
|
||||
return excludedFromHistory;
|
||||
}
|
||||
|
||||
public void setExcludedFromHistory() {
|
||||
this.excludedFromHistory = true;
|
||||
}
|
||||
|
||||
public void setDraft() {
|
||||
this.draft = true;
|
||||
this.isTransient = true;
|
||||
}
|
||||
|
||||
public boolean isDraft() {
|
||||
return draft;
|
||||
}
|
||||
|
||||
public void setDraftOnly() {
|
||||
this.draftOnly = true;
|
||||
}
|
||||
|
||||
public boolean isDraftOnly() {
|
||||
return draftOnly;
|
||||
}
|
||||
|
||||
public void setDraftDirty() {
|
||||
this.draftOnly = true;
|
||||
this.draftDirty = true;
|
||||
this.nullable = false;
|
||||
}
|
||||
|
||||
public boolean isDraftDirty() {
|
||||
return draftDirty;
|
||||
}
|
||||
|
||||
public void setDraftReset() {
|
||||
this.draftReset = true;
|
||||
}
|
||||
|
||||
public boolean isDraftReset() {
|
||||
return draftReset;
|
||||
}
|
||||
|
||||
public void setSoftDelete() {
|
||||
this.softDelete = true;
|
||||
this.nullable = false;
|
||||
this.dbColumnDefault = DbDefaultValue.FALSE;
|
||||
}
|
||||
|
||||
public boolean isSoftDelete() {
|
||||
return softDelete;
|
||||
}
|
||||
|
||||
public void setUnmappedJson() {
|
||||
this.unmappedJson = true;
|
||||
this.isTransient = true;
|
||||
}
|
||||
|
||||
public boolean isUnmappedJson() {
|
||||
return unmappedJson;
|
||||
}
|
||||
|
||||
public void setDbComment(String dbComment) {
|
||||
this.dbComment = dbComment;
|
||||
}
|
||||
|
||||
public String getDbComment() {
|
||||
return dbComment;
|
||||
}
|
||||
|
||||
public void setDocProperty(DocProperty docProperty) {
|
||||
docMapping.setDocProperty(docProperty);
|
||||
}
|
||||
|
||||
public void setDocSortable(DocSortable docSortable) {
|
||||
docMapping.setDocSortable(docSortable);
|
||||
}
|
||||
|
||||
public void setDocCode(DocCode docCode) {
|
||||
docMapping.setDocCode(docCode);
|
||||
}
|
||||
|
||||
public DocPropertyOptions getDocPropertyOptions() {
|
||||
return docMapping.create();
|
||||
}
|
||||
|
||||
public String getDbColumnDefault() {
|
||||
return dbColumnDefault;
|
||||
}
|
||||
|
||||
public void setTenantId() {
|
||||
this.tenantId = true;
|
||||
this.nullable = false;
|
||||
this.dbInsertable = true;
|
||||
this.dbUpdateable = false;
|
||||
}
|
||||
|
||||
public boolean isTenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebeaninternal.server.deploy.BeanCascadeInfo;
|
||||
import io.ebeaninternal.server.deploy.BeanTable;
|
||||
|
||||
/**
|
||||
* Abstract base for properties mapped to an associated bean, list, set or map.
|
||||
*/
|
||||
public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
|
||||
|
||||
/**
|
||||
* The type of the joined bean.
|
||||
*/
|
||||
protected Class<T> targetType;
|
||||
|
||||
/**
|
||||
* Persist settings.
|
||||
*/
|
||||
private final BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
|
||||
|
||||
/**
|
||||
* The join table information.
|
||||
*/
|
||||
private BeanTable beanTable;
|
||||
|
||||
/**
|
||||
* Join between the beans.
|
||||
*/
|
||||
protected final DeployTableJoin tableJoin = new DeployTableJoin();
|
||||
|
||||
/**
|
||||
* Literal added to where clause of lazy loading query.
|
||||
*/
|
||||
private String extraWhere;
|
||||
|
||||
/**
|
||||
* From the deployment mappedBy attribute.
|
||||
*/
|
||||
private String mappedBy;
|
||||
|
||||
private String docStoreDoc;
|
||||
|
||||
/**
|
||||
* Construct the property.
|
||||
*/
|
||||
DeployBeanPropertyAssoc(DeployBeanDescriptor<?> desc, Class<T> targetType) {
|
||||
super(desc, targetType, null, null);
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target DeployBeanDescriptor for this associated bean property.
|
||||
*/
|
||||
public DeployBeanDescriptor<?> getTargetDeploy() {
|
||||
return desc.getDeploy(targetType).getDescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of the target.
|
||||
* <p>
|
||||
* This is the class of the associated bean, or beans contained in a list,
|
||||
* set or map.
|
||||
* </p>
|
||||
*/
|
||||
public Class<T> getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a literal expression that is added to the query that lazy loads
|
||||
* the collection.
|
||||
*/
|
||||
public String getExtraWhere() {
|
||||
return extraWhere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a literal expression to add to the query that lazy loads the
|
||||
* collection.
|
||||
*/
|
||||
public void setExtraWhere(String extraWhere) {
|
||||
this.extraWhere = extraWhere;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the join to use for the bean.
|
||||
*/
|
||||
public DeployTableJoin getTableJoin() {
|
||||
return tableJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanTable for this association.
|
||||
* <p>
|
||||
* This has the table name which is used to determine the relationship for
|
||||
* this association.
|
||||
* </p>
|
||||
*/
|
||||
public BeanTable getBeanTable() {
|
||||
return beanTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean table.
|
||||
*/
|
||||
public void setBeanTable(BeanTable beanTable) {
|
||||
this.beanTable = beanTable;
|
||||
getTableJoin().setTable(beanTable.getBaseTable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the persist info.
|
||||
*/
|
||||
public BeanCascadeInfo getCascadeInfo() {
|
||||
return cascadeInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the mappedBy deployment attribute.
|
||||
* <p>
|
||||
* This is the name of the property in the 'detail' bean that maps back to
|
||||
* this 'master' bean.
|
||||
* </p>
|
||||
*/
|
||||
public String getMappedBy() {
|
||||
return mappedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mappedBy deployment attribute.
|
||||
*/
|
||||
public void setMappedBy(String mappedBy) {
|
||||
if (!"".equals(mappedBy)) {
|
||||
this.mappedBy = mappedBy;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DocStoreEmbedded deployment information.
|
||||
*/
|
||||
public void setDocStoreEmbedded(String embeddedDoc) {
|
||||
this.docStoreDoc = embeddedDoc;
|
||||
}
|
||||
|
||||
public String getDocStoreDoc() {
|
||||
return docStoreDoc;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import io.ebeaninternal.server.deploy.ManyType;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
|
||||
/**
|
||||
* Property mapped to a List Set or Map.
|
||||
*/
|
||||
public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
|
||||
|
||||
/**
|
||||
* The type of the many, set, list or map.
|
||||
*/
|
||||
final ManyType manyType;
|
||||
|
||||
ModifyListenMode modifyListenMode = ModifyListenMode.NONE;
|
||||
|
||||
/**
|
||||
* Flag to indicate manyToMany relationship.
|
||||
*/
|
||||
boolean manyToMany;
|
||||
|
||||
/**
|
||||
* Flag to indicate this is a unidirectional relationship.
|
||||
*/
|
||||
boolean unidirectional;
|
||||
|
||||
/**
|
||||
* Join for manyToMany intersection table.
|
||||
*/
|
||||
DeployTableJoin intersectionJoin;
|
||||
|
||||
/**
|
||||
* For ManyToMany this is the Inverse join used to build reference queries.
|
||||
*/
|
||||
DeployTableJoin inverseJoin;
|
||||
|
||||
String fetchOrderBy;
|
||||
|
||||
String mapKey;
|
||||
|
||||
String intersectionDraftTable;
|
||||
|
||||
/**
|
||||
* Create this property.
|
||||
*/
|
||||
public DeployBeanPropertyAssocMany(DeployBeanDescriptor<?> desc, Class<T> targetType, ManyType manyType) {
|
||||
super(desc, targetType);
|
||||
this.manyType = manyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* When generics is not used for manyType you can specify via annotations.
|
||||
* <p>
|
||||
* Really only expect this for Scala due to a Scala compiler bug at the moment.
|
||||
* Otherwise I'd probably not bother support this.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setTargetType(Class<?> cls){
|
||||
this.targetType = (Class<T>)cls;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the many type.
|
||||
*/
|
||||
public ManyType getManyType() {
|
||||
return manyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is many to many.
|
||||
*/
|
||||
public boolean isManyToMany() {
|
||||
return manyToMany;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is a many to many.
|
||||
*/
|
||||
public void setManyToMany() {
|
||||
this.manyToMany = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mode for listening to changes to the List Set or Map.
|
||||
*/
|
||||
public ModifyListenMode getModifyListenMode() {
|
||||
return modifyListenMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode for listening to changes to the List Set or Map.
|
||||
*/
|
||||
public void setModifyListenMode(ModifyListenMode modifyListenMode) {
|
||||
this.modifyListenMode = modifyListenMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a unidirectional relationship.
|
||||
*/
|
||||
public boolean isUnidirectional() {
|
||||
return unidirectional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is a unidirectional relationship.
|
||||
*/
|
||||
public void setUnidirectional() {
|
||||
this.unidirectional = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the immutable version of the intersection join.
|
||||
*/
|
||||
public TableJoin createIntersectionTableJoin() {
|
||||
if (intersectionJoin != null){
|
||||
return new TableJoin(intersectionJoin);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the immutable version of the inverse join.
|
||||
*/
|
||||
public TableJoin createInverseTableJoin() {
|
||||
if (inverseJoin != null){
|
||||
return new TableJoin(inverseJoin);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ManyToMany only, join from local table to intersection table.
|
||||
*/
|
||||
public DeployTableJoin getIntersectionJoin() {
|
||||
return intersectionJoin;
|
||||
}
|
||||
|
||||
public DeployTableJoin getInverseJoin() {
|
||||
return inverseJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* ManyToMany only, join from local table to intersection table.
|
||||
*/
|
||||
public void setIntersectionJoin(DeployTableJoin intersectionJoin) {
|
||||
this.intersectionJoin = intersectionJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* ManyToMany only, join from foreign table to intersection table.
|
||||
*/
|
||||
public void setInverseJoin(DeployTableJoin inverseJoin) {
|
||||
this.inverseJoin = inverseJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the order by clause used to order the fetching of the data for
|
||||
* this list, set or map.
|
||||
*/
|
||||
public String getFetchOrderBy() {
|
||||
return fetchOrderBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default mapKey when returning a Map.
|
||||
*/
|
||||
public String getMapKey() {
|
||||
return mapKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default mapKey to use when returning a Map.
|
||||
*/
|
||||
public void setMapKey(String mapKey) {
|
||||
if (mapKey != null && !mapKey.isEmpty()) {
|
||||
this.mapKey = mapKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order by clause used to order the fetching or the data for this
|
||||
* list, set or map.
|
||||
*/
|
||||
public void setFetchOrderBy(String orderBy) {
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
fetchOrderBy = orderBy;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a draft table for intersection between 2 @Draftable entities.
|
||||
*/
|
||||
public String getIntersectionDraftTable() {
|
||||
return (intersectionDraftTable != null) ? intersectionDraftTable : intersectionJoin.getTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* ManyToMany between 2 @Draftable entities to also need draft intersection table.
|
||||
*/
|
||||
public void setIntersectionDraftTable() {
|
||||
this.intersectionDraftTable = intersectionJoin.getTable()+"_draft";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
/**
|
||||
* Property mapped to a joined bean.
|
||||
*/
|
||||
public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
|
||||
|
||||
private boolean oneToOne;
|
||||
|
||||
private boolean oneToOneExported;
|
||||
|
||||
private boolean importedPrimaryKey;
|
||||
|
||||
private DeployBeanEmbedded deployEmbedded;
|
||||
|
||||
private String columnPrefix;
|
||||
|
||||
/**
|
||||
* Create the property.
|
||||
*/
|
||||
public DeployBeanPropertyAssocOne(DeployBeanDescriptor<?> desc, Class<T> targetType) {
|
||||
super(desc, targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the deploy information specifically for the deployment
|
||||
* of Embedded beans.
|
||||
*/
|
||||
public DeployBeanEmbedded getDeployEmbedded() {
|
||||
// deployment should be single threaded
|
||||
if (deployEmbedded == null) {
|
||||
deployEmbedded = new DeployBeanEmbedded();
|
||||
}
|
||||
return deployEmbedded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this has multiple properties (expected for embedded id).
|
||||
*/
|
||||
public boolean isCompound() {
|
||||
// just checking for compound and not doing numeric check at this stage
|
||||
return getDeployEmbedded().getPropertyColumnMap().size() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDbColumn() {
|
||||
DeployTableJoinColumn[] columns = tableJoin.columns();
|
||||
if (columns.length == 1) {
|
||||
return columns[0].getLocalDbColumn();
|
||||
}
|
||||
return super.getDbColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this a OneToOne property. Otherwise assumed ManyToOne.
|
||||
*/
|
||||
public boolean isOneToOne() {
|
||||
return oneToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is a OneToOne.
|
||||
*/
|
||||
public void setOneToOne() {
|
||||
this.oneToOne = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is the exported side of a OneToOne.
|
||||
*/
|
||||
public boolean isOneToOneExported() {
|
||||
return oneToOneExported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is the exported side of a OneToOne. This means
|
||||
* it doesn't 'own' the foreign key column. A OneToMany without the many.
|
||||
*/
|
||||
public void setOneToOneExported() {
|
||||
this.oneToOneExported = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is part of the primary key.
|
||||
*/
|
||||
public boolean isImportedPrimaryKey() {
|
||||
return importedPrimaryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this is part of the primary key.
|
||||
*/
|
||||
void setImportedPrimaryKey(DeployBeanProperty primaryKey) {
|
||||
this.importedPrimaryKey = true;
|
||||
String dbColumn = primaryKey.getDbColumn();
|
||||
if (dbColumn != null) {
|
||||
// change join db column if matched by property name
|
||||
tableJoin.setLocalColumn(dbColumn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSqlFormula(String formulaSelect, String formulaJoin) {
|
||||
super.setSqlFormula(formulaSelect, formulaJoin);
|
||||
DeployTableJoinColumn[] columns = tableJoin.columns();
|
||||
if (columns.length == 1) {
|
||||
columns[0].setLocalSqlFormula(formulaSelect);
|
||||
}
|
||||
}
|
||||
|
||||
public void setColumnPrefix(String columnPrefix) {
|
||||
this.columnPrefix = columnPrefix;
|
||||
}
|
||||
|
||||
public String getColumnPrefix() {
|
||||
return columnPrefix;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorMap;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertySimpleCollection;
|
||||
import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
import io.ebeaninternal.server.type.ScalarTypeString;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper object to classify BeanProperties into appropriate lists.
|
||||
*/
|
||||
public class DeployBeanPropertyLists {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DeployBeanPropertyLists.class);
|
||||
|
||||
private BeanProperty versionProperty;
|
||||
|
||||
private BeanProperty unmappedJson;
|
||||
|
||||
private BeanProperty draft;
|
||||
|
||||
private BeanProperty draftDirty;
|
||||
|
||||
private BeanProperty tenant;
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final LinkedHashMap<String, BeanProperty> propertyMap;
|
||||
|
||||
private final List<BeanProperty> ids = new ArrayList<>();
|
||||
|
||||
private final List<BeanProperty> local = new ArrayList<>();
|
||||
|
||||
private final List<BeanProperty> mutable = new ArrayList<>();
|
||||
|
||||
private final List<BeanPropertyAssocMany<?>> manys = new ArrayList<>();
|
||||
|
||||
private final List<BeanProperty> nonManys = new ArrayList<>();
|
||||
|
||||
private final List<BeanPropertyAssocOne<?>> ones = new ArrayList<>();
|
||||
|
||||
private final List<BeanPropertyAssocOne<?>> onesImported = new ArrayList<>();
|
||||
|
||||
private final List<BeanPropertyAssocOne<?>> embedded = new ArrayList<>();
|
||||
|
||||
private final List<BeanProperty> baseScalar = new ArrayList<>();
|
||||
|
||||
private final List<BeanProperty> transients = new ArrayList<>();
|
||||
|
||||
private final List<BeanProperty> nonTransients = new ArrayList<>();
|
||||
|
||||
private final TableJoin[] tableJoins;
|
||||
|
||||
private final BeanPropertyAssocOne<?> unidirectional;
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public DeployBeanPropertyLists(BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
|
||||
this.desc = desc;
|
||||
|
||||
setImportedPrimaryKeys(deploy);
|
||||
|
||||
DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
|
||||
if (deployUnidirectional == null) {
|
||||
unidirectional = null;
|
||||
} else {
|
||||
unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional);
|
||||
}
|
||||
|
||||
this.propertyMap = new LinkedHashMap<>();
|
||||
|
||||
// see if there is a discriminator property we should add
|
||||
String discriminatorColumn = null;
|
||||
BeanProperty discProperty = null;
|
||||
|
||||
InheritInfo inheritInfo = deploy.getInheritInfo();
|
||||
if (inheritInfo != null) {
|
||||
// Create a BeanProperty for the discriminator column to support
|
||||
// using RawSql queries with inheritance
|
||||
discriminatorColumn = inheritInfo.getDiscriminatorColumn();
|
||||
DeployBeanProperty discDeployProp = new DeployBeanProperty(deploy, String.class, new ScalarTypeString(), null);
|
||||
discDeployProp.setDiscriminator();
|
||||
discDeployProp.setName(discriminatorColumn);
|
||||
discDeployProp.setDbColumn(discriminatorColumn);
|
||||
|
||||
// only register it in the propertyMap. This might not be used if
|
||||
// an explicit property is mapped to the discriminator on the bean
|
||||
discProperty = new BeanProperty(desc, discDeployProp);
|
||||
}
|
||||
|
||||
for (DeployBeanProperty prop : deploy.propertiesAll()) {
|
||||
if (discriminatorColumn != null && discriminatorColumn.equals(prop.getDbColumn())) {
|
||||
// we have an explicit property mapped to the discriminator column
|
||||
prop.setDiscriminator();
|
||||
discProperty = null;
|
||||
}
|
||||
BeanProperty beanProp = createBeanProperty(owner, prop);
|
||||
propertyMap.put(beanProp.getName(), beanProp);
|
||||
}
|
||||
|
||||
int order = 0;
|
||||
for (BeanProperty prop : propertyMap.values()) {
|
||||
prop.setDeployOrder(order++);
|
||||
allocateToList(prop);
|
||||
}
|
||||
|
||||
if (discProperty != null) {
|
||||
// put the discriminator property into the property map only
|
||||
// (after the real properties have been organised into their lists)
|
||||
propertyMap.put(discProperty.getName(), discProperty);
|
||||
}
|
||||
|
||||
List<DeployTableJoin> deployTableJoins = deploy.getTableJoins();
|
||||
tableJoins = new TableJoin[deployTableJoins.size()];
|
||||
for (int i = 0; i < deployTableJoins.size(); i++) {
|
||||
tableJoins[i] = new TableJoin(deployTableJoins.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and set imported primary keys.
|
||||
* <p>
|
||||
* This is where @ManyToOne properties maps to a PFK (Primary and foreign key).
|
||||
* Perform the match by naming convention on property name and db column.
|
||||
* </p>
|
||||
*/
|
||||
private void setImportedPrimaryKeys(DeployBeanDescriptor<?> deploy) {
|
||||
|
||||
List<DeployBeanProperty> ids = deploy.propertiesId();
|
||||
if (ids.size() == 1) {
|
||||
DeployBeanProperty id = ids.get(0);
|
||||
if (id instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
// only interested if the primary key is a compound key
|
||||
DeployBeanDescriptor<?> targetDeploy = ((DeployBeanPropertyAssocOne<?>) id).getTargetDeploy();
|
||||
for (DeployBeanPropertyAssocOne<?> assoc : deploy.propertiesAssocOne()) {
|
||||
DeployBeanProperty pkMatch = targetDeploy.findMatch(assoc.getName(), assoc.getDbColumn());
|
||||
if (pkMatch != null) {
|
||||
assoc.setImportedPrimaryKey(pkMatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the unidirectional.
|
||||
*/
|
||||
public BeanPropertyAssocOne<?> getUnidirectional() {
|
||||
return unidirectional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the property to a list.
|
||||
*/
|
||||
private void allocateToList(BeanProperty prop) {
|
||||
if (prop.isTransient()) {
|
||||
transients.add(prop);
|
||||
if (prop.isDraft()) {
|
||||
draft = prop;
|
||||
}
|
||||
if (prop.isUnmappedJson()) {
|
||||
unmappedJson = prop;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (prop.isId()) {
|
||||
ids.add(prop);
|
||||
return;
|
||||
} else {
|
||||
nonTransients.add(prop);
|
||||
}
|
||||
|
||||
if (prop.isMutableScalarType()) {
|
||||
mutable.add(prop);
|
||||
}
|
||||
|
||||
if (desc.getInheritInfo() != null && prop.isLocal()) {
|
||||
local.add(prop);
|
||||
}
|
||||
|
||||
if (prop instanceof BeanPropertyAssocMany<?>) {
|
||||
manys.add((BeanPropertyAssocMany<?>)prop);
|
||||
|
||||
} else {
|
||||
nonManys.add(prop);
|
||||
if (prop instanceof BeanPropertyAssocOne<?>) {
|
||||
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>) prop;
|
||||
if (prop.isEmbedded()) {
|
||||
embedded.add(assocOne);
|
||||
} else {
|
||||
ones.add(assocOne);
|
||||
if (!assocOne.isOneToOneExported()) {
|
||||
onesImported.add(assocOne);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// its a "base" property...
|
||||
if (prop.isVersion()) {
|
||||
if (versionProperty == null) {
|
||||
versionProperty = prop;
|
||||
} else {
|
||||
logger.warn("Multiple @Version properties - property " + prop.getFullBeanName() + " not treated as a version property");
|
||||
}
|
||||
} else if (prop.isDraftDirty()) {
|
||||
draftDirty = prop;
|
||||
} else if (prop.isTenantId()) {
|
||||
tenant = prop;
|
||||
}
|
||||
if (!prop.isAggregation()) {
|
||||
baseScalar.add(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, BeanProperty> getPropertyMap() {
|
||||
return propertyMap;
|
||||
}
|
||||
|
||||
public TableJoin[] getTableJoin() {
|
||||
return tableJoins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base scalar properties (excludes Id and secondary table
|
||||
* properties).
|
||||
*/
|
||||
public BeanProperty[] getBaseScalar() {
|
||||
return baseScalar.toArray(new BeanProperty[baseScalar.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty getId() {
|
||||
if (ids.size() > 1) {
|
||||
String msg = "Issue with bean "+desc+". Ebean does not support multiple @Id properties. You need to convert to using an @EmbeddedId."
|
||||
+" Please email the ebean google group if you need further clarification.";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
if (ids.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return ids.get(0);
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonTransients() {
|
||||
return nonTransients.toArray(new BeanProperty[nonTransients.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getTransients() {
|
||||
return transients.toArray(new BeanProperty[transients.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty getVersionProperty() {
|
||||
return versionProperty;
|
||||
}
|
||||
|
||||
public BeanProperty[] getLocal() {
|
||||
return local.toArray(new BeanProperty[local.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getMutable() {
|
||||
return mutable.toArray(new BeanProperty[mutable.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getEmbedded() {
|
||||
return embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImported() {
|
||||
return onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOnes() {
|
||||
return ones.toArray(new BeanPropertyAssocOne[ones.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
|
||||
return getOne(false, Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedDelete() {
|
||||
return getOne(false, Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImportedSave() {
|
||||
return getOne(true, Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImportedDelete() {
|
||||
return getOne(true, Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonMany() {
|
||||
return nonManys.toArray(new BeanProperty[nonManys.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getMany() {
|
||||
return manys.toArray(new BeanPropertyAssocMany[manys.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManySave() {
|
||||
return getMany(Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManyDelete() {
|
||||
return getMany(Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManyToMany() {
|
||||
return getMany2Many();
|
||||
}
|
||||
|
||||
public BeanProperty getDraftDirty() {
|
||||
return draftDirty;
|
||||
}
|
||||
|
||||
public BeanProperty getUnmappedJson() {
|
||||
return unmappedJson;
|
||||
}
|
||||
|
||||
public BeanProperty getDraft() {
|
||||
return draft;
|
||||
}
|
||||
|
||||
public BeanProperty getSoftDeleteProperty() {
|
||||
|
||||
for (BeanProperty prop: nonManys) {
|
||||
if (prop.isSoftDelete()) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public BeanProperty getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mode used to determine which BeanPropertyAssoc to include.
|
||||
*/
|
||||
private enum Mode {
|
||||
Save, Delete
|
||||
}
|
||||
|
||||
private BeanPropertyAssocOne<?>[] getOne(boolean imported, Mode mode) {
|
||||
ArrayList<BeanPropertyAssocOne<?>> list = new ArrayList<>();
|
||||
for (BeanPropertyAssocOne<?> prop : ones) {
|
||||
if (imported != prop.isOneToOneExported()) {
|
||||
switch (mode) {
|
||||
case Save:
|
||||
if (prop.getCascadeInfo().isSave()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Delete:
|
||||
if (prop.getCascadeInfo().isDelete()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[list.size()]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany2Many() {
|
||||
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<>();
|
||||
for (BeanPropertyAssocMany<?> prop : manys) {
|
||||
if (prop.isManyToMany()) {
|
||||
list.add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany(Mode mode) {
|
||||
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<>();
|
||||
for (BeanPropertyAssocMany<?> prop : manys) {
|
||||
switch (mode) {
|
||||
case Save:
|
||||
if (prop.getCascadeInfo().isSave() || prop.isManyToMany()
|
||||
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
|
||||
// Note ManyToMany always included as we always 'save'
|
||||
// the relationship via insert/delete of intersection table
|
||||
// REMOVALS means including PrivateOwned relationships
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Delete:
|
||||
if (prop.getCascadeInfo().isDelete() || ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
|
||||
// REMOVALS means including PrivateOwned relationships
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private BeanProperty createBeanProperty(BeanDescriptorMap owner, DeployBeanProperty deployProp) {
|
||||
|
||||
if (deployProp instanceof DeployBeanPropertyAssocOne) {
|
||||
return new BeanPropertyAssocOne(owner, desc, (DeployBeanPropertyAssocOne) deployProp);
|
||||
}
|
||||
|
||||
if (deployProp instanceof DeployBeanPropertySimpleCollection<?>) {
|
||||
return new BeanPropertySimpleCollection(desc, (DeployBeanPropertySimpleCollection) deployProp);
|
||||
}
|
||||
|
||||
if (deployProp instanceof DeployBeanPropertyAssocMany) {
|
||||
return new BeanPropertyAssocMany(desc, (DeployBeanPropertyAssocMany) deployProp);
|
||||
}
|
||||
|
||||
return new BeanProperty(desc, deployProp);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import io.ebeaninternal.server.deploy.ManyType;
|
||||
|
||||
public class DeployBeanPropertySimpleCollection<T> extends DeployBeanPropertyAssocMany<T> {
|
||||
|
||||
public DeployBeanPropertySimpleCollection(DeployBeanDescriptor<?> desc, Class<T> targetType, ManyType manyType) {
|
||||
super(desc, targetType, manyType);
|
||||
this.modifyListenMode = ModifyListenMode.ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false as never a ManyToMany.
|
||||
*/
|
||||
@Override
|
||||
public boolean isManyToMany() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true as always Unidirectional.
|
||||
*/
|
||||
@Override
|
||||
public boolean isUnidirectional() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorMap;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
|
||||
|
||||
/**
|
||||
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
|
||||
* recursion issues due to the potentially bi-directional and circular
|
||||
* relationships between beans.
|
||||
* <p>
|
||||
* It holds the main deployment information and not all the detail that is held
|
||||
* in a BeanDescriptor.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployBeanTable {
|
||||
|
||||
private final Class<?> beanType;
|
||||
|
||||
/**
|
||||
* The base table.
|
||||
*/
|
||||
private String baseTable;
|
||||
|
||||
private List<DeployBeanProperty> idProperties;
|
||||
|
||||
/**
|
||||
* Create the BeanTable.
|
||||
*/
|
||||
public DeployBeanTable(Class<?> beanType) {
|
||||
this.beanType = beanType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base table for this BeanTable.
|
||||
* This is used to determine the join information
|
||||
* for associations.
|
||||
*/
|
||||
public String getBaseTable() {
|
||||
return baseTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base table for this BeanTable.
|
||||
*/
|
||||
public void setBaseTable(String baseTable) {
|
||||
this.baseTable = baseTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id properties.
|
||||
*/
|
||||
public BeanProperty[] createIdProperties(BeanDescriptorMap owner) {
|
||||
BeanProperty[] props = new BeanProperty[idProperties.size()];
|
||||
for (int i = 0; i < idProperties.size(); i++) {
|
||||
props[i] = createProperty(owner, idProperties.get(i));
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private BeanProperty createProperty(BeanDescriptorMap owner, DeployBeanProperty prop){
|
||||
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>){
|
||||
return new BeanPropertyAssocOne(owner, (DeployBeanPropertyAssocOne<?>)prop);
|
||||
|
||||
} else {
|
||||
return new BeanProperty(prop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Id properties.
|
||||
*/
|
||||
public void setIdProperties(List<DeployBeanProperty> idProperties) {
|
||||
this.idProperties = idProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class for this beanTable.
|
||||
*/
|
||||
public Class<?> getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebeaninternal.server.deploy.BeanTable;
|
||||
import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a join to another table during deployment phase.
|
||||
* <p>
|
||||
* This gets converted into a immutable TableJoin when complete.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployTableJoin {
|
||||
|
||||
/**
|
||||
* The joined table.
|
||||
*/
|
||||
private String table;
|
||||
|
||||
/**
|
||||
* The type of join. LEFT JOIN etc.
|
||||
*/
|
||||
private SqlJoinType type = SqlJoinType.INNER;
|
||||
|
||||
/**
|
||||
* The list of join column pairs. Used to generate the on clause.
|
||||
*/
|
||||
private ArrayList<DeployTableJoinColumn> columns = new ArrayList<>(4);
|
||||
|
||||
private InheritInfo inheritInfo;
|
||||
|
||||
/**
|
||||
* Create a DeployTableJoin.
|
||||
*/
|
||||
public DeployTableJoin() {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + " " + table + " " + columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the JoinOnPair have been set.
|
||||
*/
|
||||
public boolean hasJoinColumns() {
|
||||
return !columns.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all the columns to this join potentially reversing the columns.
|
||||
*/
|
||||
public void setColumns(DeployTableJoinColumn[] cols, boolean reverse) {
|
||||
columns = new ArrayList<>();
|
||||
for (DeployTableJoinColumn col : cols) {
|
||||
addJoinColumn(col.copy(reverse));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a join pair
|
||||
*/
|
||||
public void addJoinColumn(DeployTableJoinColumn pair) {
|
||||
columns.add(pair);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JoinColumn
|
||||
* <p>
|
||||
* The order is generally true for OneToMany and false for ManyToOne relationships.
|
||||
* </p>
|
||||
*/
|
||||
public void addJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
|
||||
if (!"".equals(jc.table())) {
|
||||
setTable(jc.table());
|
||||
}
|
||||
if (!"".equals(jc.name()) || !"".equals(jc.referencedColumnName())) {
|
||||
// only add the join column details when name or referencedColumnName is specified
|
||||
addJoinColumn(new DeployTableJoinColumn(order, jc, beanTable));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JoinColumn array.
|
||||
*/
|
||||
public void addJoinColumn(boolean order, JoinColumn[] jcArray, BeanTable beanTable) {
|
||||
for (JoinColumn aJcArray : jcArray) {
|
||||
addJoinColumn(order, aJcArray, beanTable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JoinColumn set.
|
||||
*/
|
||||
public void addJoinColumn(boolean order, Set<JoinColumn> joinColumns, BeanTable beanTable) {
|
||||
for (JoinColumn joinColumn : joinColumns) {
|
||||
addJoinColumn(order, joinColumn, beanTable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the join columns.
|
||||
*/
|
||||
public DeployTableJoinColumn[] columns() {
|
||||
return columns.toArray(new DeployTableJoinColumn[columns.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the joined table name.
|
||||
*/
|
||||
public String getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the joined table name.
|
||||
*/
|
||||
public void setTable(String table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of join. LEFT OUTER JOIN etc.
|
||||
*/
|
||||
public SqlJoinType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(SqlJoinType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public DeployTableJoin createInverse(String tableName) {
|
||||
|
||||
DeployTableJoin inverse = new DeployTableJoin();
|
||||
return copyInternal(inverse, true, tableName, true);
|
||||
}
|
||||
|
||||
public void copyTo(DeployTableJoin destJoin, boolean reverse, String tableName) {
|
||||
copyInternal(destJoin, reverse, tableName, true);
|
||||
}
|
||||
|
||||
public void copyWithoutType(DeployTableJoin destJoin, boolean reverse, String tableName) {
|
||||
copyInternal(destJoin, reverse, tableName, false);
|
||||
}
|
||||
|
||||
private DeployTableJoin copyInternal(DeployTableJoin destJoin, boolean reverse, String tableName, boolean withType) {
|
||||
|
||||
destJoin.setTable(tableName);
|
||||
if (withType) {
|
||||
destJoin.setType(type);
|
||||
}
|
||||
destJoin.setColumns(columns(), reverse);
|
||||
|
||||
return destJoin;
|
||||
}
|
||||
|
||||
public InheritInfo getInheritInfo() {
|
||||
return inheritInfo;
|
||||
}
|
||||
|
||||
public void setInheritInfo(InheritInfo inheritInfo) {
|
||||
this.inheritInfo = inheritInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the join column (based on imported primary key match on property name etc).
|
||||
*/
|
||||
void setLocalColumn(String dbColumn) {
|
||||
if (columns.size() == 1) {
|
||||
columns.get(0).setLocalDbColumn(dbColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanTable;
|
||||
|
||||
/**
|
||||
* A join pair of local and foreign properties.
|
||||
*/
|
||||
public class DeployTableJoinColumn {
|
||||
|
||||
/**
|
||||
* The local database column name.
|
||||
*/
|
||||
String localDbColumn;
|
||||
|
||||
/**
|
||||
* SQL formula used for local column
|
||||
*/
|
||||
String localSqlFormula;
|
||||
|
||||
/**
|
||||
* The foreign database column name.
|
||||
*/
|
||||
String foreignDbColumn;
|
||||
|
||||
/**
|
||||
* SQL formula used for foreign column
|
||||
*/
|
||||
String foreignSqlFormula;
|
||||
|
||||
boolean insertable;
|
||||
|
||||
boolean updateable;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Construct when automatically determining the join.
|
||||
* <p>
|
||||
* Assume that we want the foreign key to be insertable and updateable.
|
||||
* </p>
|
||||
*/
|
||||
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
|
||||
this(localDbColumn, foreignDbColumn, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with explicit insertable and updateable flags.
|
||||
*/
|
||||
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
|
||||
this.localDbColumn = nullEmptyString(localDbColumn);
|
||||
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
|
||||
this.insertable = insertable;
|
||||
this.updateable = updateable;
|
||||
}
|
||||
|
||||
public void setLocalSqlFormula(String localSqlFormula) {
|
||||
if (localSqlFormula != null) {
|
||||
this.localSqlFormula = localSqlFormula;
|
||||
this.localDbColumn = null;
|
||||
this.insertable = false;
|
||||
this.updateable = false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getLocalSqlFormula() {
|
||||
return localSqlFormula;
|
||||
}
|
||||
|
||||
public void setForeignSqlFormula(String foreignSqlFormula) {
|
||||
if (foreignSqlFormula != null) {
|
||||
this.foreignSqlFormula = foreignSqlFormula;
|
||||
this.foreignDbColumn = null;
|
||||
this.insertable = false;
|
||||
this.updateable = false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getForeignSqlFormula() {
|
||||
return foreignSqlFormula;
|
||||
}
|
||||
|
||||
|
||||
public DeployTableJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
|
||||
this(jc.referencedColumnName(), jc.name(), jc.insertable(), jc.updatable());
|
||||
setReferencedColumn(beanTable);
|
||||
if (!order){
|
||||
reverse();
|
||||
}
|
||||
}
|
||||
|
||||
private void setReferencedColumn(BeanTable beanTable){
|
||||
if (localDbColumn == null){
|
||||
BeanProperty[] idProperties = beanTable.getIdProperties();
|
||||
if (idProperties.length == 1){
|
||||
localDbColumn = idProperties[0].getDbColumn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the direction of the join.
|
||||
*/
|
||||
public DeployTableJoinColumn reverse() {
|
||||
String temp = localDbColumn;
|
||||
localDbColumn = foreignDbColumn;
|
||||
foreignDbColumn = temp;
|
||||
|
||||
temp = localSqlFormula;
|
||||
localSqlFormula = foreignSqlFormula;
|
||||
foreignSqlFormula = temp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to null out empty strings.
|
||||
*/
|
||||
private String nullEmptyString(String s){
|
||||
if ("".equals(s)){
|
||||
return null;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
public DeployTableJoinColumn copy(boolean reverse) {
|
||||
// Note that the insertable and updateable are just copied
|
||||
// which may not always be the correct thing to do
|
||||
// but will leave it like this for now
|
||||
DeployTableJoinColumn ret;
|
||||
if (reverse){
|
||||
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
|
||||
ret.setLocalSqlFormula(foreignSqlFormula);
|
||||
ret.setForeignSqlFormula(localSqlFormula);
|
||||
|
||||
} else {
|
||||
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
|
||||
ret.setLocalSqlFormula(localSqlFormula);
|
||||
ret.setForeignSqlFormula(foreignSqlFormula);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return localDbColumn + " = " + foreignDbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this column should be insertable.
|
||||
*/
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this column should be updateable.
|
||||
*/
|
||||
public boolean isUpdateable() {
|
||||
return updateable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the foreign database column name.
|
||||
*/
|
||||
public String getForeignDbColumn() {
|
||||
return foreignDbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the local database column name.
|
||||
*/
|
||||
public String getLocalDbColumn() {
|
||||
return localDbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the local database column name.
|
||||
*/
|
||||
public void setLocalDbColumn(String localDbColumn) {
|
||||
this.localDbColumn = localDbColumn;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<title>Temporary objects used to collect deployment information</title>
|
||||
</head>
|
||||
<body BGCOLOR="#ffffff">
|
||||
Temporary objects used to collect deployment information
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user