diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java index 74a95e39e..b45962e06 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java @@ -376,7 +376,7 @@ public class BeanDescriptor implements BeanType, STreeType { private final BeanProperty[] propertiesGenInsert; private final BeanProperty[] propertiesGenUpdate; private final List propertiesUnique = new ArrayList<>(); - + private final boolean idOnlyReference; private BeanNaturalKey beanNaturalKey; /** @@ -512,7 +512,6 @@ public class BeanDescriptor implements BeanType, STreeType { this.propertiesOneImported = listHelper.getOneImported(); this.propertiesOneImportedSave = listHelper.getOneImportedSave(); this.propertiesOneImportedDelete = listHelper.getOneImportedDelete(); - this.propertiesMany = listHelper.getMany(); this.propertiesNonMany = listHelper.getNonMany(); this.propertiesAggregate = listHelper.getAggregates(); @@ -521,6 +520,7 @@ public class BeanDescriptor implements BeanType, STreeType { this.propertiesManyToMany = listHelper.getManyToMany(); this.propertiesGenInsert = listHelper.getGeneratedInsert(); this.propertiesGenUpdate = listHelper.getGeneratedUpdate(); + this.idOnlyReference = isIdOnlyReference(propertiesBaseScalar); boolean noRelationships = propertiesOne.length + propertiesMany.length == 0; @@ -568,6 +568,19 @@ public class BeanDescriptor implements BeanType, STreeType { } } + /** + * Return true if the bean should be treated as a reference bean when it only has its id populated. + * To be true it has other scalar properties that are not generated on insert. + */ + private boolean isIdOnlyReference(BeanProperty[] baseScalar) { + for (BeanProperty beanProperty : baseScalar) { + if (!beanProperty.isGeneratedOnInsert()) { + return true; + } + } + return false; + } + /** * Derive an array of property positions for properties that are initialised in the constructor. * These properties need to be unloaded when populating beans for queries. @@ -1809,7 +1822,6 @@ public class BeanDescriptor implements BeanType, STreeType { * Find a property annotated with @WhenCreated or @CreatedTimestamp. */ private BeanProperty findWhenCreatedProperty() { - for (BeanProperty aPropertiesBaseScalar : propertiesBaseScalar) { if (aPropertiesBaseScalar.isGeneratedWhenCreated()) { return aPropertiesBaseScalar; @@ -3301,11 +3313,11 @@ public class BeanDescriptor implements BeanType, STreeType { } public boolean isReference(EntityBeanIntercept ebi) { - return ebi.isReference() || hasIdPropertyOnly(ebi); + return ebi.isReference() || referenceIdPropertyOnly(ebi); } - boolean hasIdPropertyOnly(EntityBeanIntercept ebi) { - return propertiesBaseScalar.length > 0 && ebi.hasIdOnly(idPropertyIndex); + boolean referenceIdPropertyOnly(EntityBeanIntercept ebi) { + return idOnlyReference && ebi.hasIdOnly(idPropertyIndex); } public boolean isIdLoaded(EntityBeanIntercept ebi) { diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java index 4af68241a..830c8d6d2 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java @@ -1160,6 +1160,10 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty { return isVersion() || (generatedProperty != null && generatedProperty.isDDLNotNullable()); } + boolean isGeneratedOnInsert() { + return generatedProperty != null && generatedProperty.includeInInsert(); + } + /** * Return true if this is a generated property mapping to @WhenCreated or @CreatedTimestamp. */ diff --git a/src/main/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertDate.java b/src/main/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertDate.java index 209500300..2bb206e3d 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertDate.java +++ b/src/main/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertDate.java @@ -8,7 +8,7 @@ import java.util.Date; /** * Used to generate a (java.util.Date) timestamp when a bean is inserted. */ -public class GeneratedInsertDate implements GeneratedProperty { +public class GeneratedInsertDate implements GeneratedProperty, GeneratedWhenCreated { /** * Return the current time as a Timestamp. diff --git a/src/test/java/io/ebeaninternal/server/deploy/TestBeanDescriptorHasIdProperty.java b/src/test/java/io/ebeaninternal/server/deploy/TestBeanDescriptorHasIdProperty.java index a355c5577..815ba9888 100644 --- a/src/test/java/io/ebeaninternal/server/deploy/TestBeanDescriptorHasIdProperty.java +++ b/src/test/java/io/ebeaninternal/server/deploy/TestBeanDescriptorHasIdProperty.java @@ -11,6 +11,8 @@ import org.tests.model.basic.Order; import org.tests.model.composite.RCustomer; import org.tests.model.composite.RCustomerKey; import org.junit.Test; +import org.tests.model.embedded.UserInterestLive; +import org.tests.model.embedded.UserInterestLiveKey; import java.sql.Timestamp; import java.util.Map; @@ -56,13 +58,21 @@ public class TestBeanDescriptorHasIdProperty extends BaseTestCase { Customer order = new Customer(); EntityBeanIntercept ebi = getIntercept(order); - assertFalse(beanDescriptor.hasIdPropertyOnly(ebi)); + assertFalse(beanDescriptor.referenceIdPropertyOnly(ebi)); order.setId(23); - assertTrue(beanDescriptor.hasIdPropertyOnly(ebi)); + assertTrue(beanDescriptor.referenceIdPropertyOnly(ebi)); order.setName("custName"); - assertFalse(beanDescriptor.hasIdPropertyOnly(ebi)); + assertFalse(beanDescriptor.referenceIdPropertyOnly(ebi)); + } + + @Test + public void isReference_withGeneratedOnInsertOnlyProperty_expect_false() { + BeanDescriptor descriptor = spiServer.getBeanDescriptor(UserInterestLive.class); + UserInterestLive bean = new UserInterestLive(new UserInterestLiveKey(1L, 2L)); + EntityBeanIntercept ebi = getIntercept(bean); + assertFalse(descriptor.referenceIdPropertyOnly(ebi)); } @Test diff --git a/src/test/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertJavaTimeTest.java b/src/test/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertJavaTimeTest.java new file mode 100644 index 000000000..3d469c783 --- /dev/null +++ b/src/test/java/io/ebeaninternal/server/deploy/generatedproperty/GeneratedInsertJavaTimeTest.java @@ -0,0 +1,17 @@ +package io.ebeaninternal.server.deploy.generatedproperty; + + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class GeneratedInsertJavaTimeTest { + + @Test + public void test_generatedOnInsert() { + + GeneratedProperty gen = new GeneratedInsertJavaTime.InstantDT(); + assertTrue(GeneratedWhenCreated.class.isInstance(gen)); + assertTrue(gen instanceof GeneratedWhenCreated); + } +} diff --git a/src/test/java/org/tests/model/embedded/TestEmbeddedEqualsWhenCreated.java b/src/test/java/org/tests/model/embedded/TestEmbeddedEqualsWhenCreated.java new file mode 100644 index 000000000..f5dcb38b9 --- /dev/null +++ b/src/test/java/org/tests/model/embedded/TestEmbeddedEqualsWhenCreated.java @@ -0,0 +1,19 @@ +package org.tests.model.embedded; + +import io.ebean.DB; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class TestEmbeddedEqualsWhenCreated { + + @Test + public void test() { + + UserInterestLive bean = new UserInterestLive(new UserInterestLiveKey(1L, 2L)); + bean.save(); + + final UserInterestLive found = DB.find(UserInterestLive.class, bean.getKey()); + assertEquals(found, bean); // <- failed as bean not inserted + } +} diff --git a/src/test/java/org/tests/model/embedded/UserInterestLive.java b/src/test/java/org/tests/model/embedded/UserInterestLive.java new file mode 100644 index 000000000..286ef97fb --- /dev/null +++ b/src/test/java/org/tests/model/embedded/UserInterestLive.java @@ -0,0 +1,34 @@ +package org.tests.model.embedded; + +import io.ebean.Model; +import io.ebean.annotation.CreatedTimestamp; + +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import java.util.Date; + +@Entity +public class UserInterestLive extends Model { + + @EmbeddedId + private final UserInterestLiveKey key; + + @CreatedTimestamp + private Date createdAt; + + public UserInterestLive(UserInterestLiveKey key) { + this.key = key; + } + + public UserInterestLiveKey getKey() { + return key; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } +} diff --git a/src/test/java/org/tests/model/embedded/UserInterestLiveKey.java b/src/test/java/org/tests/model/embedded/UserInterestLiveKey.java new file mode 100644 index 000000000..52b6583cd --- /dev/null +++ b/src/test/java/org/tests/model/embedded/UserInterestLiveKey.java @@ -0,0 +1,30 @@ +package org.tests.model.embedded; + +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class UserInterestLiveKey { + + private long userId; + private long liveId; + + public UserInterestLiveKey(long userId, long liveId) { + this.userId = userId; + this.liveId = liveId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UserInterestLiveKey that = (UserInterestLiveKey) o; + return userId == that.userId && + liveId == that.liveId; + } + + @Override + public int hashCode() { + return Objects.hash(userId, liveId); + } +}