mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 08:25:50 +00:00
#416 - RawSql issue with inheritance - PersistenceException: Inheritance type for discriminator value
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.RawSql.ColumnMapping;
|
||||
import com.avaje.ebean.config.dbplatform.SqlLimitResponse;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.type.DataReader;
|
||||
import com.avaje.ebeaninternal.server.type.RsetDataReaderIndexed;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* RawSql based query plan.
|
||||
*/
|
||||
@@ -18,9 +17,7 @@ public class CQueryPlanRawSql extends CQueryPlan {
|
||||
private final int[] rsetIndexPositions;
|
||||
|
||||
public CQueryPlanRawSql(OrmQueryRequest<?> request, SqlLimitResponse sqlRes, SqlTree sqlTree, String logWhereSql) {
|
||||
|
||||
super(request, sqlRes, sqlTree, true, logWhereSql);
|
||||
|
||||
this.rsetIndexPositions = createIndexPositions(request, sqlTree);
|
||||
}
|
||||
|
||||
@@ -34,23 +31,11 @@ public class CQueryPlanRawSql extends CQueryPlan {
|
||||
List<String> chain = sqlTree.buildRawSqlSelectChain();
|
||||
ColumnMapping columnMapping = request.getQuery().getRawSql().getColumnMapping();
|
||||
|
||||
// if the top level bean has inheritance expect first column
|
||||
// to be the discriminator type column (and use offset 1)
|
||||
InheritInfo inheritInfo = request.getBeanDescriptor().getInheritInfo();
|
||||
boolean addDiscriminator = inheritInfo != null;
|
||||
int offset = addDiscriminator ? 1 : 0;
|
||||
|
||||
int[] indexPositions = new int[chain.size() + offset];
|
||||
if (addDiscriminator) {
|
||||
// discriminator column must always be first in the query
|
||||
indexPositions[0] = 1;
|
||||
}
|
||||
int[] indexPositions = new int[chain.size()];
|
||||
|
||||
// set the resultSet index positions for the property expressions
|
||||
for (int i = 0; i < chain.size(); i++) {
|
||||
String expr = chain.get(i);
|
||||
int indexPos = 1 + columnMapping.getIndexPosition(expr);
|
||||
indexPositions[i + offset] = indexPos;
|
||||
indexPositions[i] = 1 + columnMapping.getIndexPosition(chain.get(i));
|
||||
}
|
||||
|
||||
// check and handle the case where a discriminator column for
|
||||
|
||||
@@ -160,6 +160,10 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
public void buildRawSqlSelectChain(List<String> selectChain) {
|
||||
if (readId) {
|
||||
if (desc.hasInheritance()) {
|
||||
// discriminator column always proceeds id column
|
||||
selectChain.add(getPath(prefix, desc.getInheritInfo().getDiscriminatorColumn()));
|
||||
}
|
||||
idBinder.buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
for (int i = 0, x = properties.length; i < x; i++) {
|
||||
|
||||
@@ -4,6 +4,9 @@ import com.avaje.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* A DataReader with indexed positions for the properties to read specifically for RawSql use.
|
||||
*/
|
||||
public class RsetDataReaderIndexed extends RsetDataReader {
|
||||
|
||||
private final int[] rsetIndexPositions;
|
||||
|
||||
@@ -24,15 +24,15 @@ public class ParentQueryTest extends BaseTestCase {
|
||||
exampleData.add(new Data(1));
|
||||
exampleData.add(new Data(2));
|
||||
|
||||
ChildA a = new ChildA(0);
|
||||
ChildA a = new ChildA(0, "PA");
|
||||
a.setData(exampleData);
|
||||
Ebean.save(a);
|
||||
|
||||
ChildB b = new ChildB(1);
|
||||
ChildB b = new ChildB(1, "PB");
|
||||
b.setData(exampleData);
|
||||
Ebean.save(b);
|
||||
|
||||
ChildA c = new ChildA(2);
|
||||
ChildA c = new ChildA(2, "PC");
|
||||
c.setData(exampleData);
|
||||
Ebean.save(c);
|
||||
|
||||
|
||||
@@ -30,15 +30,15 @@ public class ParentRawSqlTest extends BaseTestCase {
|
||||
exampleData.add(new Data(1));
|
||||
exampleData.add(new Data(2));
|
||||
|
||||
ChildA a = new ChildA(0);
|
||||
ChildA a = new ChildA(0, "PA");
|
||||
a.setData(exampleData);
|
||||
Ebean.save(a);
|
||||
|
||||
ChildB b = new ChildB(1);
|
||||
ChildB b = new ChildB(1, "PB");
|
||||
b.setData(exampleData);
|
||||
Ebean.save(b);
|
||||
|
||||
ChildA c = new ChildA(2);
|
||||
ChildA c = new ChildA(2, "PC");
|
||||
c.setData(exampleData);
|
||||
Ebean.save(c);
|
||||
|
||||
@@ -62,15 +62,15 @@ public class ParentRawSqlTest extends BaseTestCase {
|
||||
exampleData.add(new Data(1));
|
||||
exampleData.add(new Data(2));
|
||||
|
||||
ChildA a = new ChildA(0);
|
||||
ChildA a = new ChildA(0, "PA");
|
||||
a.setData(exampleData);
|
||||
Ebean.save(a);
|
||||
|
||||
ChildB b = new ChildB(1);
|
||||
ChildB b = new ChildB(1, "PB");
|
||||
b.setData(exampleData);
|
||||
Ebean.save(b);
|
||||
|
||||
ChildA c = new ChildA(2);
|
||||
ChildA c = new ChildA(2, "PC");
|
||||
c.setData(exampleData);
|
||||
Ebean.save(c);
|
||||
|
||||
@@ -80,25 +80,44 @@ public class ParentRawSqlTest extends BaseTestCase {
|
||||
Ebean.save(e1);
|
||||
|
||||
joinToInheritanceHierarchy_withAliasMapping();
|
||||
joinToInheritanceHierarchy();
|
||||
joinToInheritanceHierarchy_bug416();
|
||||
joinToInheritanceHierarchy_with_queryJoin();
|
||||
joinToInheritanceHierarchy_withIgnore();
|
||||
|
||||
useColumnMappingIgnore();
|
||||
|
||||
useColumnMappingWithDiscriminator();
|
||||
|
||||
useExtraColumnMappingIgnore();
|
||||
}
|
||||
|
||||
|
||||
private void joinToInheritanceHierarchy() {
|
||||
private void joinToInheritanceHierarchy_bug416() {
|
||||
|
||||
// For bug 416 we need the parent.more to trigger it
|
||||
|
||||
RawSql rawSql = RawSqlBuilder
|
||||
.unparsed("select u.id, u.name, p.type as ptype, p.id as pid from rawinherit_uncle u join rawinherit_parent p on p.id = u.parent_id")
|
||||
.unparsed("select u.id, u.name, p.type as p_type, p.id as p_id, p.more as p_more from rawinherit_uncle u join rawinherit_parent p on p.id = u.parent_id")
|
||||
.columnMapping("id", "id")
|
||||
.columnMapping("name", "name")
|
||||
.columnMapping("ptype", "parent.type")
|
||||
.columnMapping("pid", "parent.id")
|
||||
.columnMapping("p_type", "parent.type")
|
||||
.columnMapping("p_id", "parent.id")
|
||||
.columnMapping("p_more", "parent.more")
|
||||
.create();
|
||||
|
||||
List<EUncle> uncles = Ebean.find(EUncle.class).setRawSql(rawSql).findList();
|
||||
|
||||
assertNotNull(uncles.get(0));
|
||||
Parent parent = uncles.get(0).getParent();
|
||||
assertTrue(parent instanceof ChildB);
|
||||
}
|
||||
|
||||
private void joinToInheritanceHierarchy_with_queryJoin() {
|
||||
|
||||
RawSql rawSql = RawSqlBuilder
|
||||
.unparsed("select u.id, u.name, p.type as p_type, p.id as p_id from rawinherit_uncle u join rawinherit_parent p on p.id = u.parent_id")
|
||||
.columnMapping("id", "id")
|
||||
.columnMapping("name", "name")
|
||||
.columnMapping("p_type", "parent.type")
|
||||
.columnMapping("p_id", "parent.id")
|
||||
.create();
|
||||
|
||||
List<EUncle> uncles = Ebean.find(EUncle.class).setRawSql(rawSql)
|
||||
|
||||
@@ -7,12 +7,12 @@ import javax.persistence.Entity;
|
||||
@DiscriminatorValue("A")
|
||||
public class ChildA extends Parent {
|
||||
|
||||
public String getName() {
|
||||
return "A Name";
|
||||
}
|
||||
public String getName() {
|
||||
return "A Name";
|
||||
}
|
||||
|
||||
public ChildA(Integer number) {
|
||||
super(number);
|
||||
}
|
||||
public ChildA(Integer number, String more) {
|
||||
super(number, more);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import javax.persistence.Entity;
|
||||
@DiscriminatorValue("B")
|
||||
public class ChildB extends Parent {
|
||||
|
||||
public String getName() {
|
||||
return "B Name";
|
||||
}
|
||||
public String getName() {
|
||||
return "B Name";
|
||||
}
|
||||
|
||||
public ChildB(Integer number) {
|
||||
super(number);
|
||||
}
|
||||
public ChildB(Integer number, String more) {
|
||||
super(number, more);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,38 +13,48 @@ import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "rawinherit_parent")
|
||||
@Inheritance(strategy= InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name="type")
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "type")
|
||||
public abstract class Parent {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private Integer val;
|
||||
private Integer val;
|
||||
|
||||
@ManyToMany(cascade = CascadeType.PERSIST)
|
||||
private List<Data> data = new ArrayList<Data>();
|
||||
private String more;
|
||||
|
||||
protected Parent(Integer val) {
|
||||
this.val = val;
|
||||
}
|
||||
@ManyToMany(cascade = CascadeType.PERSIST)
|
||||
private List<Data> data = new ArrayList<Data>();
|
||||
|
||||
public abstract String getName();
|
||||
protected Parent(Integer val, String more) {
|
||||
this.val = val;
|
||||
this.more = more;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public abstract String getName();
|
||||
|
||||
public Integer getVal() {
|
||||
return val;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<Data> getData() {
|
||||
return data;
|
||||
}
|
||||
public Integer getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setData(List<Data> datas) {
|
||||
this.data = datas;
|
||||
}
|
||||
public List<Data> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<Data> datas) {
|
||||
this.data = datas;
|
||||
}
|
||||
|
||||
public String getMore() {
|
||||
return more;
|
||||
}
|
||||
|
||||
public void setMore(String more) {
|
||||
this.more = more;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user