diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java index 5e97cbfbd..9403afa5b 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java +++ b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java @@ -951,6 +951,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap { } if (matchSet.size() == 1) { // all right with the world + prop.clearTableJoin(); return true; } if (matchSet.size() == 2) { diff --git a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java index 6e0394273..7ed3ff164 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java +++ b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanPropertyAssocMany.java @@ -269,5 +269,12 @@ public class DeployBeanPropertyAssocMany extends DeployBeanPropertyAssoc { public BeanDescriptor getElementDescriptor() { return (BeanDescriptor)elementDescriptor; } + + /** + * Clear the table join due to an implied mappedBy. + */ + public void clearTableJoin() { + tableJoin.clear(); + } } diff --git a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployTableJoin.java b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployTableJoin.java index 517318872..d24024774 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployTableJoin.java +++ b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployTableJoin.java @@ -178,4 +178,16 @@ public class DeployTableJoin { columns.get(0).setLocalDbColumn(dbColumn); } } + + /** + * Clear the join columns due to an implied mappedBy. + *

+ * Effectively prior to clear this was considered a unidirectional OneToMany and the + * foreign key was defined by naming convention. Clearing this means that it uses the + * foreign key as defined by the implied mappedBy property (the only ManyToOne that + * maps back to the parent (that holds the OneToMany). + */ + public void clear() { + columns.clear(); + } } diff --git a/src/test/java/org/tests/o2m/OmAccountChildDBO.java b/src/test/java/org/tests/o2m/OmAccountChildDBO.java new file mode 100644 index 000000000..8c6c908b6 --- /dev/null +++ b/src/test/java/org/tests/o2m/OmAccountChildDBO.java @@ -0,0 +1,41 @@ +package org.tests.o2m; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class OmAccountChildDBO { + + @Id + private long id; + + private final String description; + + @ManyToOne + private OmAccountDBO bananaRama; + + public OmAccountChildDBO(String description) { + this.description = description; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public OmAccountDBO getBananaRama() { + return bananaRama; + } + + public void setBananaRama(OmAccountDBO bananaRama) { + this.bananaRama = bananaRama; + } +} diff --git a/src/test/java/org/tests/o2m/OmAccountDBO.java b/src/test/java/org/tests/o2m/OmAccountDBO.java new file mode 100644 index 000000000..b2aa63d00 --- /dev/null +++ b/src/test/java/org/tests/o2m/OmAccountDBO.java @@ -0,0 +1,46 @@ +package org.tests.o2m; + +import io.ebean.Model; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.List; + +import static javax.persistence.CascadeType.ALL; + +@Entity +public class OmAccountDBO extends Model { + + @Id + private long id; + + private final String name; + + @OneToMany(cascade = ALL, orphanRemoval = true)//, mappedBy = "bananaRama") + private List child676; + + public OmAccountDBO(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public List getChild676() { + return child676; + } + + public void setChild676(List child676) { + this.child676 = child676; + } +} diff --git a/src/test/java/org/tests/o2m/TestOneToManyNoMappedBy.java b/src/test/java/org/tests/o2m/TestOneToManyNoMappedBy.java new file mode 100644 index 000000000..f02cff28a --- /dev/null +++ b/src/test/java/org/tests/o2m/TestOneToManyNoMappedBy.java @@ -0,0 +1,41 @@ +package org.tests.o2m; + +import io.ebean.DB; +import org.ebeantest.LoggedSqlCollector; +import org.junit.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +public class TestOneToManyNoMappedBy { + + @Test + public void test() { + + OmAccountDBO account = new OmAccountDBO("one"); + account.getChild676().add(new OmAccountChildDBO("child0")); + account.getChild676().add(new OmAccountChildDBO("child1")); + + account.save(); + + LoggedSqlCollector.start(); + + final OmAccountDBO found = DB.find(OmAccountDBO.class) + .where().eq("name", "one") + .findOne(); + + final List children = found.getChild676(); + for (OmAccountChildDBO child : children) { + final String description = child.getDescription(); + assertNotNull(description); + assertSame(found, child.getBananaRama()); + } + + final List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(1)).contains("select t0.banana_rama_id, t0.id, t0.description, t0.banana_rama_id from om_account_child_dbo t0 where"); + } +}