diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssoc.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssoc.java index a7e060004..472a71db3 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssoc.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssoc.java @@ -176,4 +176,9 @@ public abstract class DeployBeanPropertyAssoc extends DeployBeanProperty { public void setFetchPreference(int fetchPreference) { this.fetchPreference = fetchPreference; } + + @SuppressWarnings("unchecked") + public void setTargetType(Class targetType) { + this.targetType = (Class)targetType; + } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java index 7ed3ff164..606a6d215 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java @@ -65,19 +65,6 @@ public class DeployBeanPropertyAssocMany extends DeployBeanPropertyAssoc { this.manyType = manyType; } - /** - * When generics is not used for manyType you can specify via annotations. - *

- * Really only expect this for Scala due to a Scala compiler bug at the moment. - * Otherwise I'd probably not bother support this. - *

- */ - @SuppressWarnings("unchecked") - public void setTargetType(Class cls) { - this.targetType = (Class) cls; - } - - /** * Return the many type. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssoc.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssoc.java new file mode 100644 index 000000000..525034f41 --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssoc.java @@ -0,0 +1,39 @@ +package io.ebeaninternal.server.deploy.parse; + +import io.ebean.config.BeanNotRegisteredException; +import io.ebeaninternal.server.deploy.BeanDescriptorManager; +import io.ebeaninternal.server.deploy.BeanTable; +import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc; + +abstract class AnnotationAssoc extends AnnotationParser { + + final BeanDescriptorManager factory; + + AnnotationAssoc(DeployBeanInfo info, ReadAnnotationConfig readConfig, BeanDescriptorManager factory) { + super(info, readConfig); + this.factory = factory; + } + + void setTargetType(Class targetType, DeployBeanPropertyAssoc prop) { + if (!targetType.equals(void.class)) { + prop.setTargetType(targetType); + } + } + + void setBeanTable(DeployBeanPropertyAssoc prop) { + BeanTable assoc = getBeanTable(prop); + if (assoc == null) { + throw new BeanNotRegisteredException(errorMsgMissingBeanTable(prop.getTargetType(), prop.getFullBeanName())); + } + prop.setBeanTable(assoc); + } + + BeanTable getBeanTable(DeployBeanPropertyAssoc prop) { + return factory.getBeanTable(prop.getTargetType()); + } + + private String errorMsgMissingBeanTable(Class type, String from) { + return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered? See https://ebean.io/docs/trouble-shooting#not-registered"; + } + +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java index e0dae8abc..91c949a0f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java @@ -44,16 +44,10 @@ import static io.ebean.util.StringHelper.isNull; /** * Read the deployment annotation for Assoc Many beans. */ -class AnnotationAssocManys extends AnnotationParser { +class AnnotationAssocManys extends AnnotationAssoc { - private final BeanDescriptorManager factory; - - /** - * Create with the DeployInfo. - */ AnnotationAssocManys(DeployBeanInfo info, ReadAnnotationConfig readConfig, BeanDescriptorManager factory) { - super(info, readConfig); - this.factory = factory; + super(info, readConfig, factory); } /** @@ -435,11 +429,6 @@ class AnnotationAssocManys extends AnnotationParser { prop.setInverseJoin(inverseDest); } - - private String errorMsgMissingBeanTable(Class type, String from) { - return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered? See https://ebean.io/docs/trouble-shooting#not-registered"; - } - private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany manyProp) { manyProp.setMappedBy(propAnn.mappedBy()); @@ -462,20 +451,6 @@ class AnnotationAssocManys extends AnnotationParser { manyProp.getTableJoin().setType(SqlJoinType.OUTER); } - private void setTargetType(Class targetType, DeployBeanPropertyAssocMany prop) { - if (!targetType.equals(void.class)) { - prop.setTargetType(targetType); - } - } - - private void setBeanTable(DeployBeanPropertyAssocMany manyProp) { - BeanTable assoc = factory.getBeanTable(manyProp.getTargetType()); - if (assoc == null) { - throw new BeanNotRegisteredException(errorMsgMissingBeanTable(manyProp.getTargetType(), manyProp.getFullBeanName())); - } - manyProp.setBeanTable(assoc); - } - private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable) { TableName lhs = new TableName(lhsTable.getBaseTable()); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java index 8d4d178f1..6750633cb 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java @@ -33,18 +33,15 @@ import javax.validation.constraints.NotNull; /** * Read the deployment annotations for Associated One beans. */ -public class AnnotationAssocOnes extends AnnotationParser { +public class AnnotationAssocOnes extends AnnotationAssoc { private static final Logger log = LoggerFactory.getLogger(AnnotationAssocOnes.class); - private final BeanDescriptorManager factory; - /** * Create with the deploy Info. */ AnnotationAssocOnes(DeployBeanInfo info, ReadAnnotationConfig readConfig, BeanDescriptorManager factory) { - super(info, readConfig); - this.factory = factory; + super(info, readConfig, factory); } /** @@ -191,25 +188,11 @@ public class AnnotationAssocOnes extends AnnotationParser { } } - private String errorMsgMissingBeanTable(Class type, String from) { - return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered? Does it have the @Entity annotation? See https://ebean.io/docs/trouble-shooting#not-registered"; - } - - private BeanTable beanTable(DeployBeanPropertyAssoc prop) { - BeanTable assoc = factory.getBeanTable(prop.getPropertyType()); - if (assoc == null) { - throw new BeanNotRegisteredException(errorMsgMissingBeanTable(prop.getPropertyType(), prop.getFullBeanName())); - } - return assoc; - } - - private void readManyToOne(ManyToOne propAnn, DeployBeanProperty prop) { - - DeployBeanPropertyAssocOne beanProp = (DeployBeanPropertyAssocOne) prop; + private void readManyToOne(ManyToOne propAnn, DeployBeanPropertyAssocOne beanProp) { setCascadeTypes(propAnn.cascade(), beanProp.getCascadeInfo()); - - beanProp.setBeanTable(beanTable(beanProp)); + setTargetType(propAnn.targetEntity(), beanProp); + setBeanTable(beanProp); beanProp.setDbInsertable(true); beanProp.setDbUpdateable(true); beanProp.setNullable(propAnn.optional()); @@ -232,7 +215,8 @@ public class AnnotationAssocOnes extends AnnotationParser { } setCascadeTypes(propAnn.cascade(), prop.getCascadeInfo()); - prop.setBeanTable(beanTable(prop)); + setTargetType(propAnn.targetEntity(), prop); + setBeanTable(prop); } private boolean readOrphanRemoval(OneToOne property) { @@ -261,7 +245,7 @@ public class AnnotationAssocOnes extends AnnotationParser { BeanTable baseBeanTable = factory.getBeanTable(info.getDescriptor().getBeanType()); String localPrimaryKey = baseBeanTable.getIdColumn(); - String foreignColumn = beanTable(prop).getIdColumn(); + String foreignColumn = getBeanTable(prop).getIdColumn(); prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false)); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployCreateProperties.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployCreateProperties.java index 691fa7cf5..6fb54b46d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployCreateProperties.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployCreateProperties.java @@ -145,14 +145,6 @@ public class DeployCreateProperties { private DeployBeanProperty createProp(DeployBeanDescriptor desc, Field field) { Class propertyType = field.getType(); - - ManyToOne manyToOne = AnnotationUtil.get(field, ManyToOne.class); - if (manyToOne != null) { - Class tt = manyToOne.targetEntity(); - if (!tt.equals(void.class)) { - propertyType = tt; - } - } if (isSpecialScalarType(field)) { return new DeployBeanProperty(desc, propertyType, field.getGenericType()); } diff --git a/ebean-core/src/test/java/org/tests/basic/TestManyOneInterface.java b/ebean-core/src/test/java/org/tests/basic/TestManyOneInterface.java index ab847eb93..c27e6fc02 100644 --- a/ebean-core/src/test/java/org/tests/basic/TestManyOneInterface.java +++ b/ebean-core/src/test/java/org/tests/basic/TestManyOneInterface.java @@ -16,7 +16,7 @@ public class TestManyOneInterface extends BaseTestCase { ResetBasicData.reset(); - IAddress a = new Address(); + IAddress a = new Address("hello"); IPerson p = new Person(); diff --git a/ebean-core/src/test/java/org/tests/model/interfaces/Address.java b/ebean-core/src/test/java/org/tests/model/interfaces/Address.java index a4f9885bb..052ef63f8 100644 --- a/ebean-core/src/test/java/org/tests/model/interfaces/Address.java +++ b/ebean-core/src/test/java/org/tests/model/interfaces/Address.java @@ -15,6 +15,10 @@ public class Address implements IAddress { private String street; + public Address(String street) { + this.street = street; + } + public long getOid() { return oid; } diff --git a/ebean-core/src/test/java/org/tests/model/interfaces/IPersona.java b/ebean-core/src/test/java/org/tests/model/interfaces/IPersona.java new file mode 100644 index 000000000..321047319 --- /dev/null +++ b/ebean-core/src/test/java/org/tests/model/interfaces/IPersona.java @@ -0,0 +1,6 @@ +package org.tests.model.interfaces; + +public interface IPersona { + + String persona(); +} diff --git a/ebean-core/src/test/java/org/tests/model/interfaces/Persona.java b/ebean-core/src/test/java/org/tests/model/interfaces/Persona.java new file mode 100644 index 000000000..015d8ada0 --- /dev/null +++ b/ebean-core/src/test/java/org/tests/model/interfaces/Persona.java @@ -0,0 +1,39 @@ +package org.tests.model.interfaces; + +import javax.persistence.*; + +@Entity +public class Persona implements IPersona { + + @Id + private long id; + + @Version + private int version; + + private final String persona; + + @OneToOne(orphanRemoval = true, fetch = FetchType.LAZY, targetEntity = Person.class) + private IPerson person; + + public Persona(String persona) { + this.persona = persona; + } + + public long getId() { + return id; + } + + @Override + public String persona() { + return persona; + } + + public void setPerson(IPerson person) { + this.person = person; + } + + public IPerson getPerson() { + return person; + } +} diff --git a/ebean-core/src/test/java/org/tests/model/interfaces/TestTargetEntity.java b/ebean-core/src/test/java/org/tests/model/interfaces/TestTargetEntity.java new file mode 100644 index 000000000..9db04f045 --- /dev/null +++ b/ebean-core/src/test/java/org/tests/model/interfaces/TestTargetEntity.java @@ -0,0 +1,38 @@ +package org.tests.model.interfaces; + +import io.ebean.BaseTestCase; +import io.ebean.DB; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TestTargetEntity extends BaseTestCase { + + @Test + public void test() { + + Person person = setup(); + + Persona persona = new Persona("junk"); + persona.setPerson(person); + DB.save(persona); + + Persona found = DB.find(Persona.class, persona.getId()); + assertThat(found).isNotNull(); + assertThat(found.persona()).isEqualTo("junk"); + assertThat(found.getPerson().getDefaultAddress().getStreet()).isEqualTo("street"); + + DB.delete(persona); + DB.delete(person); + DB.delete(person.getDefaultAddress()); + } + + private Person setup() { + Address address = new Address("street"); + DB.save(address); + Person person = new Person(); + person.setDefaultAddress(address); + DB.save(person); + return person; + } +}