mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#919 - io.ebean package initial
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
package org.tests.singleTableInheritance;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.tests.singleTableInheritance.model.PalletLocation;
|
||||
import org.tests.singleTableInheritance.model.PalletLocationExternal;
|
||||
import org.tests.singleTableInheritance.model.Warehouse;
|
||||
import org.tests.singleTableInheritance.model.Zone;
|
||||
import org.tests.singleTableInheritance.model.ZoneExternal;
|
||||
import org.tests.singleTableInheritance.model.ZoneInternal;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TestInheritQuery extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ZoneExternal zone = new ZoneExternal();
|
||||
zone.setAttribute("ABC");
|
||||
Ebean.save(zone);
|
||||
|
||||
PalletLocationExternal location = new PalletLocationExternal();
|
||||
location.setZone(zone);
|
||||
location.setAttribute("123");
|
||||
Ebean.save(location);
|
||||
|
||||
// This line should work too:
|
||||
List<PalletLocation> locations = Ebean.find(PalletLocation.class).where().eq("zone", zone)
|
||||
.findList();
|
||||
// List<PalletLocation> locations =
|
||||
// Ebean.find(PalletLocation.class).where().eq("zone.id",
|
||||
// zone.getId()).findList();
|
||||
|
||||
Assert.assertNotNull(locations);
|
||||
Assert.assertEquals(1, locations.size());
|
||||
PalletLocation rereadLoc = locations.get(0);
|
||||
Assert.assertTrue(rereadLoc instanceof PalletLocation);
|
||||
Zone rereadZone = rereadLoc.getZone();
|
||||
Assert.assertNotNull(rereadZone);
|
||||
Assert.assertTrue(rereadZone instanceof ZoneExternal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiscriminator_bug417() {
|
||||
|
||||
|
||||
Ebean.deleteAll(Ebean.find(Warehouse.class).findList());
|
||||
Ebean.deleteAll(Ebean.find(PalletLocation.class).findList());
|
||||
Ebean.deleteAll(Ebean.find(Zone.class).findList());
|
||||
Ebean.deleteAll(Ebean.find(ZoneInternal.class).findList());
|
||||
Ebean.deleteAll(Ebean.find(ZoneInternal.class).findList());
|
||||
|
||||
ZoneInternal zoneInt = new ZoneInternal();
|
||||
zoneInt.setAttribute("some zone 1");
|
||||
Ebean.save(zoneInt);
|
||||
|
||||
ZoneExternal zoneExt = new ZoneExternal();
|
||||
zoneExt.setAttribute("some zone 2");
|
||||
Ebean.save(zoneExt);
|
||||
|
||||
// queries of Zone and subclasses as root node of query
|
||||
|
||||
// query abstract class on attribute (root of heirarchy)
|
||||
List<Zone> zones = Ebean.find(Zone.class).where().startsWith("attribute", "some zone").findList();
|
||||
// select t0.type c0, t0.ID c1, t0.attribute c2, t0.attribute c3 from zones t0 where t0.attribute like ? ; --bind(some zone%)
|
||||
Assert.assertEquals(2, zones.size());
|
||||
Assert.assertTrue(zones.contains(zoneInt));
|
||||
Assert.assertTrue(zones.contains(zoneExt));
|
||||
|
||||
// query internal zones only
|
||||
// discriminator is in WHERE clause where it belongs
|
||||
List<ZoneInternal> internalZones = Ebean.find(ZoneInternal.class).where().startsWith("attribute", "some zone").findList();
|
||||
// select t0.type c0, t0.ID c1, t0.attribute c2 from zones t0 where t0.type = 'INT' and t0.attribute like ? ; --bind(some zone%)
|
||||
Assert.assertEquals(1, internalZones.size());
|
||||
Assert.assertTrue(internalZones.contains(zoneInt));
|
||||
Assert.assertFalse(internalZones.contains(zoneExt));
|
||||
Assert.assertTrue(internalZones.get(0) instanceof ZoneInternal);
|
||||
|
||||
// query external zones only
|
||||
List<ZoneExternal> externalZones = Ebean.find(ZoneExternal.class).where().startsWith("attribute", "some zone").findList();
|
||||
// select t0.type c0, t0.ID c1, t0.attribute c2 from zones t0 where t0.type = 'EXT' and t0.attribute like ? ; --bind(some zone%)
|
||||
Assert.assertEquals(1, externalZones.size());
|
||||
Assert.assertTrue(externalZones.contains(zoneExt));
|
||||
Assert.assertFalse(externalZones.contains(zoneInt));
|
||||
Assert.assertTrue(externalZones.get(0) instanceof ZoneExternal);
|
||||
|
||||
// parents with children of Zones and subclasses
|
||||
|
||||
Warehouse wh = new Warehouse();
|
||||
wh.setOfficeZone(zoneInt); // many-to-one
|
||||
wh.getShippingZones().add(zoneExt); // many-to-many
|
||||
Ebean.save(wh);
|
||||
|
||||
// JOIN clause, no discriminator
|
||||
// parent with many-to-one, doesn't put in discriminator, why not, PK sufficient?
|
||||
// eager join
|
||||
Warehouse wh2 = Ebean.find(Warehouse.class, wh.getId());
|
||||
Assert.assertNotNull(wh2);
|
||||
Assert.assertEquals(wh.getId(), wh2.getId());
|
||||
Assert.assertEquals(wh.getOfficeZone(), wh2.getOfficeZone());
|
||||
Assert.assertEquals(wh.getOfficeZone().getAttribute(), wh2.getOfficeZone().getAttribute());
|
||||
|
||||
// before the fix, next assertion runs this lazy query:
|
||||
|
||||
// select t0.ID c0, t1.type c1, t1.ID c2 from warehouses t0
|
||||
// left join WarehousesShippingZones t1z_ on t1z_.warehouseId = t0.ID
|
||||
// left join zones t1 on t1.ID = t1z_.shippingZoneId
|
||||
// where t1.type = 'EXT' // this should be in the join clause
|
||||
// and t0.ID = ?
|
||||
// order by t0.ID; --bind(1)
|
||||
|
||||
// this works here because we have at least one shipping zone
|
||||
|
||||
Assert.assertEquals(1, wh2.getShippingZones().size());
|
||||
Assert.assertTrue(wh2.getShippingZones().contains(zoneExt));
|
||||
|
||||
// set optional concrete to null to set stage for failure
|
||||
wh.setOfficeZone(null);
|
||||
Ebean.save(wh);
|
||||
|
||||
// no discriminator here
|
||||
wh2 = Ebean.find(Warehouse.class)
|
||||
.where().eq("id", wh.getId())
|
||||
.findUnique();
|
||||
|
||||
Assert.assertNotNull(wh2);
|
||||
// discriminator is used here, should be in join
|
||||
// assuming this "manual" fetch is equivalent to autofetch (i.e., autofetch should work the same way)
|
||||
// before Daryl's fix
|
||||
// select t0.ID c0, t1.type c1, t1.ID c2, t1.attribute c3 from warehouses t0 left join zones t1 on t1.ID = t0.officeZoneId where t1.type = 'INT' and t0.ID = ?
|
||||
// todo: after Daryl's fix, not sure if this is proper, no discriminator at all, isn't PK/FK sufficient?
|
||||
// select t0.ID c0, t1.type c1, t1.ID c2, t1.attribute c3 from warehouses t0 left join zones t1 on t1.ID = t0.officeZoneId where t0.ID = ? ; --bind(1)
|
||||
wh2 = Ebean.find(Warehouse.class)
|
||||
.fetch("officeZone")
|
||||
.where().eq("id", wh.getId())
|
||||
.findUnique();
|
||||
// key assertion #1 - fails due to left join with discriminator in WHERE
|
||||
Assert.assertNotNull(wh2);
|
||||
|
||||
// clear children to set the stage for left join failure
|
||||
wh.getShippingZones().clear();
|
||||
Ebean.save(wh);
|
||||
|
||||
wh2 = Ebean.find(Warehouse.class, wh.getId());
|
||||
Assert.assertNotNull(wh2);
|
||||
Assert.assertEquals(wh.getId(), wh2.getId());
|
||||
Assert.assertEquals(0, wh.getShippingZones().size());
|
||||
|
||||
// query with lazy load of abstract children
|
||||
wh = Ebean.find(Warehouse.class)
|
||||
.where().eq("id", wh.getId())
|
||||
.findUnique();
|
||||
Assert.assertNotNull(wh);
|
||||
Assert.assertEquals(wh.getId(), wh2.getId());
|
||||
Assert.assertEquals(0, wh.getShippingZones().size());
|
||||
|
||||
// query with fetch of abstract children
|
||||
wh = Ebean.find(Warehouse.class)
|
||||
.fetch("shippingZones")
|
||||
.where().eq("id", wh.getId())
|
||||
.findUnique();
|
||||
// key assertion #2 - fails due to left join with discriminator in WHERE
|
||||
Assert.assertNotNull(wh);
|
||||
Assert.assertEquals(wh.getId(), wh2.getId());
|
||||
Assert.assertEquals(0, wh.getShippingZones().size());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.tests.singleTableInheritance.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
|
||||
public class PalletLocation {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "ZONE_SID")
|
||||
private Zone zone;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Zone getZone() {
|
||||
return zone;
|
||||
}
|
||||
|
||||
public void setZone(Zone zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.tests.singleTableInheritance.model;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("EXT")
|
||||
public class PalletLocationExternal extends PalletLocation {
|
||||
private String attribute;
|
||||
|
||||
public String getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public void setAttribute(String attribute) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.tests.singleTableInheritance.model;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "warehouses")
|
||||
public class Warehouse {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne//(optional = false) //todo: should this be nullable with assertions made?
|
||||
@JoinColumn(name = "officeZoneId")
|
||||
private ZoneInternal officeZone;
|
||||
|
||||
@ManyToMany(cascade = CascadeType.PERSIST)
|
||||
@JoinTable(name = "warehousesshippingzones",
|
||||
joinColumns = {@JoinColumn(name = "warehouseId", referencedColumnName = "ID")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "shippingZoneId", referencedColumnName = "ID")}
|
||||
)
|
||||
private Set<ZoneExternal> shippingZones;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ZoneInternal getOfficeZone() {
|
||||
return officeZone;
|
||||
}
|
||||
|
||||
public void setOfficeZone(ZoneInternal officeZone) {
|
||||
this.officeZone = officeZone;
|
||||
}
|
||||
|
||||
public Set<ZoneExternal> getShippingZones() {
|
||||
return shippingZones;
|
||||
}
|
||||
|
||||
public void setShippingZones(Set<ZoneExternal> shippingZones) {
|
||||
this.shippingZones = shippingZones;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.tests.singleTableInheritance.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
|
||||
@Table(name = "zones")
|
||||
public class Zone {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Integer id;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
if (getId() != null) return getId().hashCode();
|
||||
else return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Zone) {
|
||||
return ((Zone) obj).getId().equals(getId());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.tests.singleTableInheritance.model;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("EXT")
|
||||
public class ZoneExternal extends Zone {
|
||||
private String attribute;
|
||||
|
||||
public String getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public void setAttribute(String attribute) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ZoneExternal " + getId() + " \"" + getAttribute() + "\"";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.tests.singleTableInheritance.model;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("INT")
|
||||
public class ZoneInternal extends Zone {
|
||||
|
||||
private String attribute;
|
||||
|
||||
public String getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public void setAttribute(String attribute) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ZoneInternal " + getId() + " \"" + getAttribute() + "\"";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user