diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java index bb0911b11..ef7cbb403 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java @@ -315,7 +315,7 @@ public class BeanProperty implements ElPropertyValue { if (softDelete) { ScalarTypeBoolean.BooleanBase boolType = (ScalarTypeBoolean.BooleanBase)scalarType; this.softDeleteDbSet = dbColumn+"="+boolType.getDbTrueLiteral(); - this.softDeleteDbPredicate = dbColumn+"="+boolType.getDbFalseLiteral(); + this.softDeleteDbPredicate = "."+dbColumn+","+boolType.getDbFalseLiteral()+")="+boolType.getDbFalseLiteral(); } else { this.softDeleteDbSet = null; this.softDeleteDbPredicate = null; @@ -650,7 +650,8 @@ public class BeanProperty implements ElPropertyValue { * Return the DB literal predicate used to filter out soft deleted rows from a query. */ public String getSoftDeleteDbPredicate(String tableAlias) { - return tableAlias+"."+softDeleteDbPredicate; + // use coalesce to handle null values from optional relationships + return "coalesce(" + tableAlias + softDeleteDbPredicate; } /** diff --git a/src/test/java/com/avaje/tests/model/softdelete/ESoftDelMid.java b/src/test/java/com/avaje/tests/model/softdelete/ESoftDelMid.java index 499d33e40..2596583a0 100644 --- a/src/test/java/com/avaje/tests/model/softdelete/ESoftDelMid.java +++ b/src/test/java/com/avaje/tests/model/softdelete/ESoftDelMid.java @@ -2,7 +2,6 @@ package com.avaje.tests.model.softdelete; import javax.persistence.CascadeType; import javax.persistence.Entity; -import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import java.util.List; @@ -10,7 +9,7 @@ import java.util.List; @Entity public class ESoftDelMid extends BaseSoftDelete { - @ManyToOne(optional = false) + @ManyToOne ESoftDelTop top; String mid; diff --git a/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteBasic.java b/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteBasic.java index 83284c385..719b986ad 100644 --- a/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteBasic.java +++ b/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteBasic.java @@ -135,8 +135,8 @@ public class TestSoftDeleteBasic extends BaseTestCase { String generatedSql = query1.getGeneratedSql(); // first statement is a single bulk update of the children with SoftDelete - assertThat(generatedSql).contains("t0.deleted="); - assertThat(generatedSql).contains("t1.deleted="); + assertThat(generatedSql).contains("coalesce(t0.deleted,"); + assertThat(generatedSql).contains("coalesce(t1.deleted,"); assertThat(fetch1.get(0).getChildren()).hasSize(2); assertThat(fetch1.get(0).getNosdChildren()).hasSize(2); diff --git a/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteOptionalRelationship.java b/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteOptionalRelationship.java new file mode 100644 index 000000000..916299bff --- /dev/null +++ b/src/test/java/com/avaje/tests/softdelete/TestSoftDeleteOptionalRelationship.java @@ -0,0 +1,28 @@ +package com.avaje.tests.softdelete; + +import com.avaje.ebean.BaseTestCase; +import com.avaje.ebean.Ebean; +import com.avaje.tests.model.softdelete.ESoftDelMid; +import org.junit.Test; + +import static org.assertj.core.api.StrictAssertions.assertThat; + +public class TestSoftDeleteOptionalRelationship extends BaseTestCase { + + @Test + public void testFindWhenNullRelationship() { + + ESoftDelMid mid1 = new ESoftDelMid(null, "mid1"); + Ebean.save(mid1); + + ESoftDelMid bean = Ebean.find(ESoftDelMid.class) + .setId(mid1.getId()) + .fetch("top") + .findUnique(); + + assertThat(bean).isNotNull(); + assertThat(bean.getTop()).isNull(); + } + + +}