diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java index 1be877fbd..0e3e15ed4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java @@ -1,5 +1,7 @@ package com.avaje.ebeaninternal.server.deploy.parse; +import javax.persistence.AttributeOverride; +import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.NamedQueries; @@ -26,22 +28,60 @@ import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint; import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery; import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Read the class level deployment annotations. */ public class AnnotationClass extends AnnotationParser { + private static final Logger logger = LoggerFactory.getLogger(AnnotationClass.class); + private final String asOfViewSuffix; private final String versionsBetweenSuffix; + /** + * Create for normal early parse of class level annotations. + */ public AnnotationClass(DeployBeanInfo info, boolean validationAnnotations, String asOfViewSuffix, String versionsBetweenSuffix) { super(info, validationAnnotations); this.asOfViewSuffix = asOfViewSuffix; this.versionsBetweenSuffix = versionsBetweenSuffix; } + /** + * 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; + } + + /** + * Parse any AttributeOverride set on the class. + */ + public void parseAttributeOverride() { + + Class cls = descriptor.getBeanType(); + AttributeOverride override = cls.getAnnotation(AttributeOverride.class); + if (override != null) { + String propertyName = override.name(); + Column column = override.column(); + if (column != null) { + DeployBeanProperty beanProperty = descriptor.getBeanProperty(propertyName); + if (beanProperty == null) { + logger.error("AttributeOverride property [" + propertyName + "] not found on " + descriptor.getFullName()); + } else { + readColumn(column, beanProperty); + } + } + } + } + /** * Read the class level deployment annotations. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java index 93f82c994..bb2777181 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java @@ -460,32 +460,5 @@ public class AnnotationFields extends AnnotationParser { } } - private void readColumn(Column columnAnn, DeployBeanProperty prop) { - - if (!isEmpty(columnAnn.name())) { - String dbColumn = databasePlatform.convertQuotedIdentifiers(columnAnn.name()); - prop.setDbColumn(dbColumn); - } - - prop.setDbInsertable(columnAnn.insertable()); - prop.setDbUpdateable(columnAnn.updatable()); - prop.setNullable(columnAnn.nullable()); - prop.setUnique(columnAnn.unique()); - if (columnAnn.precision() > 0) { - prop.setDbLength(columnAnn.precision()); - } else if (columnAnn.length() != 255) { - // set default 255 on DbTypeMap - prop.setDbLength(columnAnn.length()); - } - prop.setDbScale(columnAnn.scale()); - prop.setDbColumnDefn(columnAnn.columnDefinition()); - - String baseTable = descriptor.getBaseTable(); - String tableName = columnAnn.table(); - if (!"".equals(tableName) && !tableName.equalsIgnoreCase(baseTable)) { - // its on a secondary table... - prop.setSecondaryTable(tableName); - } - } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationParser.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationParser.java index ed71b2e93..031681a5b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationParser.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationParser.java @@ -5,9 +5,11 @@ import java.util.HashMap; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.CascadeType; +import javax.persistence.Column; import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor; +import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne; /** @@ -66,4 +68,31 @@ public abstract class AnnotationParser extends AnnotationBase { } + protected void readColumn(Column columnAnn, DeployBeanProperty prop) { + + if (!isEmpty(columnAnn.name())) { + String dbColumn = databasePlatform.convertQuotedIdentifiers(columnAnn.name()); + prop.setDbColumn(dbColumn); + } + + prop.setDbInsertable(columnAnn.insertable()); + prop.setDbUpdateable(columnAnn.updatable()); + prop.setNullable(columnAnn.nullable()); + prop.setUnique(columnAnn.unique()); + if (columnAnn.precision() > 0) { + prop.setDbLength(columnAnn.precision()); + } else if (columnAnn.length() != 255) { + // set default 255 on DbTypeMap + prop.setDbLength(columnAnn.length()); + } + prop.setDbScale(columnAnn.scale()); + prop.setDbColumnDefn(columnAnn.columnDefinition()); + + String baseTable = descriptor.getBaseTable(); + String tableName = columnAnn.table(); + if (!"".equals(tableName) && !tableName.equalsIgnoreCase(baseTable)) { + // its on a secondary table... + prop.setSecondaryTable(tableName); + } + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java index e1bc81db2..49b829abf 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java @@ -79,6 +79,8 @@ public class ReadAnnotations { // dependent on field level annotations new AnnotationSql(info, javaxValidationAnnotations).parse(); + new AnnotationClass(info).parseAttributeOverride(); + } catch (RuntimeException e) { throw new RuntimeException("Error reading annotations for " + info, e); } diff --git a/src/test/java/com/avaje/tests/model/basic/first/Second.java b/src/test/java/com/avaje/tests/model/basic/first/Second.java index 585011585..4c5e808b8 100644 --- a/src/test/java/com/avaje/tests/model/basic/first/Second.java +++ b/src/test/java/com/avaje/tests/model/basic/first/Second.java @@ -1,9 +1,12 @@ package com.avaje.tests.model.basic.first; +import javax.persistence.AttributeOverride; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +@AttributeOverride(name="name", column=@Column(name = "mod_name")) @Entity @Table(name = "f_second") public class Second extends SuperSecond { diff --git a/src/test/java/com/avaje/tests/model/basic/first/SuperSecond.java b/src/test/java/com/avaje/tests/model/basic/first/SuperSecond.java index c3d7073bd..a82a7a4d2 100644 --- a/src/test/java/com/avaje/tests/model/basic/first/SuperSecond.java +++ b/src/test/java/com/avaje/tests/model/basic/first/SuperSecond.java @@ -8,6 +8,8 @@ import javax.persistence.OneToOne; @MappedSuperclass public abstract class SuperSecond { + protected String name; + @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinColumn(name = "first") protected First first; @@ -20,4 +22,11 @@ public abstract class SuperSecond { this.first = first; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/src/test/java/com/avaje/tests/model/basic/first/TestFirstSecond.java b/src/test/java/com/avaje/tests/model/basic/first/TestFirstSecond.java index 66de5b704..3a4c6bd68 100644 --- a/src/test/java/com/avaje/tests/model/basic/first/TestFirstSecond.java +++ b/src/test/java/com/avaje/tests/model/basic/first/TestFirstSecond.java @@ -15,7 +15,8 @@ public class TestFirstSecond extends BaseTestCase { Ebean.save(first); Second second = new Second(); - second.setTitle("John"); + second.setName("Jim"); + second.setTitle("Sir"); second.setFirst(first); Ebean.save(second); @@ -23,7 +24,5 @@ public class TestFirstSecond extends BaseTestCase { second.getFirst().setName("changed"); Ebean.save(second); Ebean.save(first); - - } }