From 081cb202607ebb1a016f07e3e562b609e820560f Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Fri, 12 Jul 2019 14:14:29 +0200 Subject: [PATCH] always add main ID property, if no foreign key (=noConstraint) is present (cherry picked from commit ea562151a8e3043df13381abd0d076d592618340) --- .../server/query/SqlTreeBuilder.java | 5 ++ .../org/tests/lazyforeignkeys/MainEntity.java | 16 ++++- .../lazyforeignkeys/TestLazyForeignKeys.java | 63 ++++++++++++++----- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java index 7b7530dfd..cfe96a5d8 100644 --- a/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java +++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java @@ -248,10 +248,14 @@ public final class SqlTreeBuilder { List myJoinList = new ArrayList<>(); + List extraProps = new ArrayList<>(); for (STreePropertyAssocOne one : desc.propsOne()) { String propPrefix = SplitName.add(prefix, one.getName()); if (isIncludeBean(propPrefix)) { selectIncludes.add(propPrefix); + if (!one.hasForeignKey()) { + extraProps.add(one); + } buildSelectChain(propPrefix, one, one.target(), myJoinList); } } @@ -273,6 +277,7 @@ public final class SqlTreeBuilder { } addManyWhereJoins(myJoinList); } + extraProps.forEach(props::add); SqlTreeNode selectNode = buildNode(prefix, prop, desc, myJoinList, props); if (joinList != null) { diff --git a/src/test/java/org/tests/lazyforeignkeys/MainEntity.java b/src/test/java/org/tests/lazyforeignkeys/MainEntity.java index 8d76a0a84..ec92722db 100644 --- a/src/test/java/org/tests/lazyforeignkeys/MainEntity.java +++ b/src/test/java/org/tests/lazyforeignkeys/MainEntity.java @@ -4,6 +4,10 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import io.ebean.annotation.Formula; +import io.ebean.annotation.Platform; +import io.ebean.annotation.SoftDelete; + @Entity @Table(name = "main_entity") public class MainEntity { @@ -12,9 +16,15 @@ public class MainEntity { private String id; private String attr1; - + private String attr2; + @SoftDelete + @Formula(select = "${ta}.id is null") + @Formula(select = "CASE WHEN ${ta}.id is null THEN 1 ELSE 0 END", platforms = Platform.SQLSERVER17) + // evaluates to true in a left join if bean has been deleted. + boolean deleted; + public String getId() { return id; } @@ -38,4 +48,8 @@ public class MainEntity { public void setAttr2(String attr2) { this.attr2 = attr2; } + + public boolean isDeleted() { + return deleted; + } } diff --git a/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java b/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java index bb249ce9d..5d5583903 100644 --- a/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java +++ b/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java @@ -1,10 +1,13 @@ package org.tests.lazyforeignkeys; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.*; import java.util.List; +import org.ebeantest.LoggedSqlCollector; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import io.ebean.BaseTestCase; @@ -15,39 +18,65 @@ import io.ebean.text.PathProperties; public class TestLazyForeignKeys extends BaseTestCase { - @Test - public void test() { + @Before + public void prepare() { MainEntity ent1 = new MainEntity(); ent1.setId("ent1"); ent1.setAttr1("attr1"); DB.save(ent1); - + MainEntityRelation rel1 = new MainEntityRelation(); rel1.setId1("ent1"); rel1.setId2("ent2"); DB.save(rel1); - + } + @After + public void cleanup() { + DB.find(MainEntity.class).delete(); + DB.find(MainEntityRelation.class).delete(); + } + + @Test + public void testFindOne() throws Exception { + // use findOne without select, so lazy loading will occur + LoggedSqlCollector.start(); + ViewMainEntityRelation vwRel1 = DB.find(ViewMainEntityRelation.class).findOne(); - + assertEquals("ent1", vwRel1.getEntity1().getId()); assertEquals("ent2", vwRel1.getEntity2().getId()); - + assertEquals("attr1", vwRel1.getEntity1().getAttr1()); - //assertNull(vwRel1.getEntity2().getAttr1()); - + assertFalse(vwRel1.getEntity1().isDeleted()); + assertTrue(vwRel1.getEntity2().isDeleted()); + + List loggedSql = LoggedSqlCollector.stop(); + assertThat(loggedSql).hasSize(3); + assertThat(loggedSql.get(0)).contains("select t0.id, t0.attr1, t0.id1, t0.id2 from vw_main_entity_relation"); + assertThat(loggedSql.get(1)).contains("select t0.id, t0.attr1, t0.attr2, t0.id is null from main_entity t0"); + assertThat(loggedSql.get(2)).contains("select t0.id, t0.attr1, t0.attr2, t0.id is null from main_entity t0"); + } + @Test + public void testFindListWithSelect() { PathProperties pathProp = new PathProperties(); pathProp.addToPath(null, "attr1"); pathProp.addToPath("entity1", "id"); pathProp.addToPath("entity2", "id"); - + Query query = Ebean.find(ViewMainEntityRelation.class).apply(pathProp); List list = query.findList(); assertEquals(1, list.size()); - - assertEquals("ent1", list.get(0).getEntity1().getId()); - assertEquals("ent2", list.get(0).getEntity2().getId()); - - assertEquals("select t0.id, t0.attr1, t0.id1, t0.id2 from vw_main_entity_relation t0", - query.getGeneratedSql()); + + System.out.println(query.getGeneratedSql()); + assertThat(query.getGeneratedSql()).contains("t0.id, t0.attr1, t0.id1, t0.id2, t1.id, t2.id"); + + ViewMainEntityRelation vwRel1 = list.get(0); + assertEquals("ent1", vwRel1.getEntity1().getId()); + assertEquals("ent2", vwRel1.getEntity2().getId()); + + assertEquals("attr1", vwRel1.getEntity1().getAttr1()); + assertFalse(vwRel1.getEntity1().isDeleted()); + assertTrue(vwRel1.getEntity2().isDeleted()); + } }