mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#115 - Mapping - Add support for @ElementCollection enhancement
Initial support - simple List.
This commit is contained in:
@@ -7,18 +7,24 @@ import io.ebean.annotation.Where;
|
||||
import io.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import io.ebean.config.NamingConvention;
|
||||
import io.ebean.config.TableName;
|
||||
import io.ebean.util.CamelCaseHelper;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanTable;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployOrderColumn;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
@@ -38,8 +44,8 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
/**
|
||||
* Create with the DeployInfo.
|
||||
*/
|
||||
AnnotationAssocManys(DeployBeanInfo<?> info, boolean javaxValidationAnnotations, BeanDescriptorManager factory) {
|
||||
super(info, javaxValidationAnnotations);
|
||||
AnnotationAssocManys(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig, BeanDescriptorManager factory) {
|
||||
super(info, readConfig);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@@ -82,6 +88,10 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
if (manyToMany != null) {
|
||||
readToMany(manyToMany, prop);
|
||||
}
|
||||
ElementCollection elementCollection = get(prop, ElementCollection.class);
|
||||
if (elementCollection != null) {
|
||||
readElementCollection(prop, elementCollection);
|
||||
}
|
||||
|
||||
if (get(prop, HistoryExclude.class) != null) {
|
||||
prop.setExcludedFromHistory();
|
||||
@@ -160,6 +170,59 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
private void readElementCollection(DeployBeanPropertyAssocMany<?> prop, ElementCollection elementCollection) {
|
||||
|
||||
prop.setElementCollection();
|
||||
if (!elementCollection.targetClass().equals(void.class)) {
|
||||
prop.setTargetType(elementCollection.targetClass());
|
||||
}
|
||||
Column column = get(prop, Column.class);
|
||||
if (column != null) {
|
||||
prop.setDbColumn(column.name());
|
||||
prop.setDbLength(column.length());
|
||||
prop.setDbScale(column.scale());
|
||||
}
|
||||
|
||||
CollectionTable collectionTable = get(prop, CollectionTable.class);
|
||||
|
||||
String fullTableName = getFullTableName(collectionTable);
|
||||
if (fullTableName == null) {
|
||||
fullTableName = descriptor.getBaseTable()+"_"+ CamelCaseHelper.toUnderscoreFromCamel(prop.getName());
|
||||
}
|
||||
//namingConvention.
|
||||
BeanTable beanTable = factory.getCollectionBeanTable(fullTableName, prop.getTargetType());
|
||||
prop.setBeanTable(beanTable);
|
||||
|
||||
if (collectionTable != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, collectionTable.joinColumns(), beanTable);
|
||||
}
|
||||
|
||||
Class<?> elementType = prop.getTargetType();
|
||||
|
||||
DeployBeanDescriptor<?> elementDescriptor = factory.createDeployDescriptor(elementType);
|
||||
elementDescriptor.setBaseTable(new TableName(fullTableName), readConfig.getAsOfViewSuffix(), readConfig.getVersionsBetweenSuffix());
|
||||
|
||||
ScalarType<?> scalarType = util.getTypeManager().getScalarType(elementType);
|
||||
DeployBeanProperty elementProp = new DeployBeanProperty(elementDescriptor, elementType, scalarType, null);
|
||||
|
||||
elementProp.setName("value");
|
||||
elementProp.setDbColumn(prop.getDbColumn());
|
||||
elementProp.setNullable(false);
|
||||
elementProp.setDbInsertable(true);
|
||||
elementProp.setDbUpdateable(true);
|
||||
elementProp.setDbRead(true);
|
||||
elementProp.setElementProperty();
|
||||
|
||||
elementDescriptor.addBeanProperty(elementProp);
|
||||
elementDescriptor.setProperties(new String[]{"value"});
|
||||
elementDescriptor.setName(prop.getFullBeanName());
|
||||
|
||||
Class<?> owningType = prop.getOwningType();
|
||||
|
||||
factory.createUnidirectional(elementDescriptor, owningType, beanTable, prop.getTableJoin());
|
||||
prop.setElementDescriptor(factory.createElementDescriptor(elementDescriptor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the joins for a ManyToMany relationship.
|
||||
* <p>
|
||||
@@ -204,6 +267,24 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full table name
|
||||
*/
|
||||
private String getFullTableName(CollectionTable collectionTable) {
|
||||
if (collectionTable == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!StringHelper.isNull(collectionTable.catalog())) {
|
||||
sb.append(collectionTable.catalog()).append(".");
|
||||
}
|
||||
if (!StringHelper.isNull(collectionTable.schema())) {
|
||||
sb.append(collectionTable.schema()).append(".");
|
||||
}
|
||||
sb.append(collectionTable.name());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define intersection table and foreign key columns for ManyToMany.
|
||||
* <p>
|
||||
|
||||
@@ -41,8 +41,8 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
/**
|
||||
* Create with the deploy Info.
|
||||
*/
|
||||
AnnotationAssocOnes(DeployBeanInfo<?> info, boolean javaxValidationAnnotations, BeanDescriptorManager factory) {
|
||||
super(info, javaxValidationAnnotations);
|
||||
AnnotationAssocOnes(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig, BeanDescriptorManager factory) {
|
||||
super(info, readConfig);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
info.setBeanJoinType(prop, prop.isNullable());
|
||||
prop.setJoinType(prop.isNullable());
|
||||
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null) {
|
||||
|
||||
|
||||
@@ -42,25 +42,15 @@ public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
private final boolean disableL2Cache;
|
||||
|
||||
/**
|
||||
* Create for normal early parse of class level annotations.
|
||||
*/
|
||||
public AnnotationClass(DeployBeanInfo<?> info, boolean validationAnnotations, String asOfViewSuffix, String versionsBetweenSuffix, boolean disableL2Cache) {
|
||||
super(info, validationAnnotations);
|
||||
this.asOfViewSuffix = asOfViewSuffix;
|
||||
this.versionsBetweenSuffix = versionsBetweenSuffix;
|
||||
this.disableL2Cache = disableL2Cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create to parse AttributeOverride annotations which is run last
|
||||
* after all the properties/fields have been parsed fully.
|
||||
*/
|
||||
public AnnotationClass(DeployBeanInfo<?> info) {
|
||||
super(info, false);
|
||||
this.asOfViewSuffix = null;
|
||||
this.versionsBetweenSuffix = null;
|
||||
this.disableL2Cache = false;
|
||||
public AnnotationClass(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig) {
|
||||
super(info, readConfig);
|
||||
this.asOfViewSuffix = readConfig.getAsOfViewSuffix();
|
||||
this.versionsBetweenSuffix = readConfig.getVersionsBetweenSuffix();
|
||||
this.disableL2Cache = readConfig.isDisableL2Cache();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,14 +91,11 @@ public class AnnotationFields extends AnnotationParser {
|
||||
*/
|
||||
private FetchType defaultLobFetchType = FetchType.LAZY;
|
||||
|
||||
AnnotationFields(GeneratedPropertyFactory generatedPropFactory, DeployBeanInfo<?> info,
|
||||
boolean javaxValidationAnnotations, boolean jacksonAnnotationsPresent, boolean eagerFetchLobs) {
|
||||
|
||||
super(info, javaxValidationAnnotations);
|
||||
this.jacksonAnnotationsPresent = jacksonAnnotationsPresent;
|
||||
this.generatedPropFactory = generatedPropFactory;
|
||||
|
||||
if (eagerFetchLobs) {
|
||||
AnnotationFields(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig) {
|
||||
super(info, readConfig);
|
||||
this.jacksonAnnotationsPresent = readConfig.isJacksonAnnotations();
|
||||
this.generatedPropFactory = readConfig.getGeneratedPropFactory();
|
||||
if (readConfig.isEagerFetchLobs()) {
|
||||
defaultLobFetchType = FetchType.EAGER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,12 @@ public abstract class AnnotationParser extends AnnotationBase {
|
||||
|
||||
protected final boolean validationAnnotations;
|
||||
|
||||
public AnnotationParser(DeployBeanInfo<?> info, boolean validationAnnotations) {
|
||||
protected final ReadAnnotationConfig readConfig;
|
||||
|
||||
public AnnotationParser(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig) {
|
||||
super(info.getUtil());
|
||||
this.validationAnnotations = validationAnnotations;
|
||||
this.readConfig = readConfig;
|
||||
this.validationAnnotations = readConfig.isJavaxValidationAnnotations();
|
||||
this.info = info;
|
||||
this.beanType = info.getDescriptor().getBeanType();
|
||||
this.descriptor = info.getDescriptor();
|
||||
|
||||
@@ -7,10 +7,10 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
*/
|
||||
public class AnnotationSql extends AnnotationParser {
|
||||
class AnnotationSql extends AnnotationParser {
|
||||
|
||||
public AnnotationSql(DeployBeanInfo<?> info, boolean javaxValidationAnnotations) {
|
||||
super(info, javaxValidationAnnotations);
|
||||
AnnotationSql(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig) {
|
||||
super(info, readConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.ebeaninternal.server.deploy.parse;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
import io.ebeaninternal.server.rawsql.SpiRawSql;
|
||||
@@ -70,15 +69,6 @@ public class DeployBeanInfo<T> {
|
||||
return tableJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a the join alias for a assoc one property.
|
||||
*/
|
||||
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
|
||||
|
||||
DeployTableJoin tableJoin = beanProp.getTableJoin();
|
||||
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named RawSql from ebean.xml.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
|
||||
/**
|
||||
* Configuration used when reading the deployment annotations.
|
||||
*/
|
||||
class ReadAnnotationConfig {
|
||||
|
||||
private final GeneratedPropertyFactory generatedPropFactory;
|
||||
private final String asOfViewSuffix;
|
||||
private final String versionsBetweenSuffix;
|
||||
private final boolean disableL2Cache;
|
||||
private final boolean eagerFetchLobs;
|
||||
private final boolean javaxValidationAnnotations;
|
||||
private final boolean jacksonAnnotations;
|
||||
|
||||
ReadAnnotationConfig(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, ServerConfig serverConfig) {
|
||||
|
||||
this.generatedPropFactory = generatedPropFactory;
|
||||
this.asOfViewSuffix = asOfViewSuffix;
|
||||
this.versionsBetweenSuffix = versionsBetweenSuffix;
|
||||
this.disableL2Cache = serverConfig.isDisableL2Cache();
|
||||
this.eagerFetchLobs = serverConfig.isEagerFetchLobs();
|
||||
|
||||
this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent();
|
||||
this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent();
|
||||
}
|
||||
|
||||
GeneratedPropertyFactory getGeneratedPropFactory() {
|
||||
return generatedPropFactory;
|
||||
}
|
||||
|
||||
String getAsOfViewSuffix() {
|
||||
return asOfViewSuffix;
|
||||
}
|
||||
|
||||
String getVersionsBetweenSuffix() {
|
||||
return versionsBetweenSuffix;
|
||||
}
|
||||
|
||||
boolean isDisableL2Cache() {
|
||||
return disableL2Cache;
|
||||
}
|
||||
|
||||
boolean isEagerFetchLobs() {
|
||||
return eagerFetchLobs;
|
||||
}
|
||||
|
||||
boolean isJavaxValidationAnnotations() {
|
||||
return javaxValidationAnnotations;
|
||||
}
|
||||
|
||||
boolean isJacksonAnnotations() {
|
||||
return jacksonAnnotations;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
|
||||
@@ -9,38 +10,10 @@ import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory
|
||||
*/
|
||||
public class ReadAnnotations {
|
||||
|
||||
/**
|
||||
* Creates appropriate generated properties - WhenXXX, WhoXXX, Version etc.
|
||||
*/
|
||||
private final GeneratedPropertyFactory generatedPropFactory;
|
||||
private final ReadAnnotationConfig readConfig;
|
||||
|
||||
/**
|
||||
* Typically _with_history and when appended to the base table derives the name of
|
||||
* the view that unions the base table with the history table to support asOf queries.
|
||||
*/
|
||||
private final String asOfViewSuffix;
|
||||
|
||||
private final String versionsBetweenSuffix;
|
||||
|
||||
/**
|
||||
* True if the javax validation annotations are present in the classpath.
|
||||
*/
|
||||
private final boolean javaxValidationAnnotations;
|
||||
|
||||
/**
|
||||
* True if the jackson annotations are present in the classpath.
|
||||
*/
|
||||
private final boolean jacksonAnnotations;
|
||||
|
||||
private final boolean disableL2Cache;
|
||||
|
||||
public ReadAnnotations(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, boolean disableL2Cache) {
|
||||
this.generatedPropFactory = generatedPropFactory;
|
||||
this.asOfViewSuffix = asOfViewSuffix;
|
||||
this.versionsBetweenSuffix = versionsBetweenSuffix;
|
||||
this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent();
|
||||
this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent();
|
||||
this.disableL2Cache = disableL2Cache;
|
||||
public ReadAnnotations(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, ServerConfig serverConfig) {
|
||||
this.readConfig = new ReadAnnotationConfig(generatedPropFactory, asOfViewSuffix, versionsBetweenSuffix, serverConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,12 +23,10 @@ public class ReadAnnotations {
|
||||
* to resolve the relationships etc.
|
||||
* </p>
|
||||
*/
|
||||
public void readInitial(DeployBeanInfo<?> info, boolean eagerFetchLobs) {
|
||||
|
||||
public void readInitial(DeployBeanInfo<?> info) {
|
||||
try {
|
||||
new AnnotationClass(info, javaxValidationAnnotations, asOfViewSuffix, versionsBetweenSuffix, disableL2Cache).parse();
|
||||
new AnnotationFields(generatedPropFactory, info, javaxValidationAnnotations, jacksonAnnotations, eagerFetchLobs).parse();
|
||||
|
||||
new AnnotationClass(info, readConfig).parse();
|
||||
new AnnotationFields(info, readConfig).parse();
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error reading annotations for " + info, e);
|
||||
}
|
||||
@@ -75,14 +46,14 @@ public class ReadAnnotations {
|
||||
|
||||
try {
|
||||
|
||||
new AnnotationAssocOnes(info, javaxValidationAnnotations, factory).parse();
|
||||
new AnnotationAssocManys(info, javaxValidationAnnotations, factory).parse();
|
||||
new AnnotationAssocOnes(info, readConfig, factory).parse();
|
||||
new AnnotationAssocManys(info, readConfig, factory).parse();
|
||||
|
||||
// read the Sql annotations last because they may be
|
||||
// dependent on field level annotations
|
||||
new AnnotationSql(info, javaxValidationAnnotations).parse();
|
||||
new AnnotationSql(info, readConfig).parse();
|
||||
|
||||
new AnnotationClass(info).parseAttributeOverride();
|
||||
new AnnotationClass(info, readConfig).parseAttributeOverride();
|
||||
info.getDescriptor().postAnnotations();
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
|
||||
@@ -5,8 +5,6 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Mark transient properties.
|
||||
*/
|
||||
@@ -20,29 +18,22 @@ public class TransientProperties {
|
||||
*/
|
||||
public void process(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
List<DeployBeanProperty> props = desc.propertiesBase();
|
||||
for (DeployBeanProperty prop : props) {
|
||||
for (DeployBeanProperty prop : desc.propertiesBase()) {
|
||||
if (!prop.isDbRead() && !prop.isDbInsertable() && !prop.isDbUpdateable()) {
|
||||
// non-transient...
|
||||
prop.setTransient();
|
||||
}
|
||||
}
|
||||
|
||||
List<DeployBeanPropertyAssocOne<?>> ones = desc.propertiesAssocOne();
|
||||
for (DeployBeanPropertyAssocOne<?> prop : ones) {
|
||||
if (prop.getBeanTable() == null) {
|
||||
if (!prop.isEmbedded()) {
|
||||
prop.setTransient();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DeployBeanPropertyAssocMany<?>> manys = desc.propertiesAssocMany();
|
||||
for (DeployBeanPropertyAssocMany<?> prop : manys) {
|
||||
if (prop.getBeanTable() == null) {
|
||||
for (DeployBeanPropertyAssocOne<?> prop : desc.propertiesAssocOne()) {
|
||||
if (prop.getBeanTable() == null && !prop.isEmbedded()) {
|
||||
prop.setTransient();
|
||||
}
|
||||
}
|
||||
|
||||
for (DeployBeanPropertyAssocMany<?> prop : desc.propertiesAssocMany()) {
|
||||
if (prop.getBeanTable() == null) {
|
||||
prop.setTransient();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user