mirror of https://github.com/apache/openjpa.git
Fix a bug in which joined classes using an application identity hierarchy
couldn't be loaded correctly as an inverse relation. git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@679152 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2ed656a2a0
commit
37d610ca2c
|
@ -189,34 +189,27 @@ public class ClassMapping
|
|||
return null;
|
||||
}
|
||||
}
|
||||
Object oid = ApplicationIds.fromPKValues(vals, cls);
|
||||
|
||||
/**
|
||||
* For polymorphic relations,
|
||||
* the type field in the oid is initially set to base type.
|
||||
* If the discriminator value is preset in the current result,
|
||||
* then the type field needs reset based on the discriminator value.
|
||||
* If the discriminator value is not present or invalid,
|
||||
* ignore any exceptions being thrown.
|
||||
*/
|
||||
|
||||
// the oid data is loaded by the base type, but if discriminator data
|
||||
// is present, make sure to use it to construct the actual oid instance
|
||||
// so that we get the correct app id class, etc
|
||||
ClassMapping dcls = cls;
|
||||
if (subs) {
|
||||
res.startDataRequest(cls.getDiscriminator());
|
||||
try {
|
||||
Class dtype = cls.getDiscriminator().getClass(store, cls, res);
|
||||
if (dtype != cls.getDescribedType())
|
||||
dcls = cls.getMappingRepository().getMapping(dtype,
|
||||
store.getContext().getClassLoader(), true);
|
||||
} catch (Exception e) {
|
||||
// intentionally ignored
|
||||
}
|
||||
res.endDataRequest();
|
||||
}
|
||||
Object oid = ApplicationIds.fromPKValues(vals, dcls);
|
||||
if (oid instanceof OpenJPAId) {
|
||||
Class type = cls.getDescribedType();
|
||||
if (!subs)
|
||||
// non-polymorphic relations
|
||||
((OpenJPAId) oid).setManagedInstanceType(type);
|
||||
else if (cls.getDiscriminator() != null
|
||||
&& !StringUtils.equals("none",
|
||||
cls.getDiscriminator().getStrategy().getAlias())) {
|
||||
// polymorphic relations
|
||||
res.startDataRequest(cls.getDiscriminator());
|
||||
try {
|
||||
type = cls.getDiscriminator().getClass(store, cls, res);
|
||||
((OpenJPAId) oid).setManagedInstanceType(type, true);
|
||||
} catch (Exception e) {
|
||||
// intentionally ignored
|
||||
}
|
||||
res.endDataRequest();
|
||||
}
|
||||
((OpenJPAId) oid).setManagedInstanceType(dcls.getDescribedType(),
|
||||
subs);
|
||||
}
|
||||
return oid;
|
||||
}
|
||||
|
|
|
@ -193,12 +193,16 @@ public class ApplicationIds {
|
|||
return new ObjectId(meta.getDescribedType(), val);
|
||||
case JavaTypes.BIGDECIMAL:
|
||||
if (!convert && !(val instanceof BigDecimal))
|
||||
throw new ClassCastException("!(x instanceof BigDecimal)");
|
||||
return new BigDecimalId(meta.getDescribedType(), (BigDecimal)val);
|
||||
throw new ClassCastException(
|
||||
"!(x instanceof BigDecimal)");
|
||||
return new BigDecimalId(meta.getDescribedType(),
|
||||
(BigDecimal)val);
|
||||
case JavaTypes.BIGINTEGER:
|
||||
if (!convert && !(val instanceof BigInteger))
|
||||
throw new ClassCastException("!(x instanceof BigInteger)");
|
||||
return new BigIntegerId(meta.getDescribedType(), (BigInteger)val);
|
||||
throw new ClassCastException(
|
||||
"!(x instanceof BigInteger)");
|
||||
return new BigIntegerId(meta.getDescribedType(),
|
||||
(BigInteger)val);
|
||||
default:
|
||||
throw new InternalException();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public abstract class OpenJPAId
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the persitent class which this id instance represents.
|
||||
* Return the persistent class which this id instance represents.
|
||||
*/
|
||||
public Class getType() {
|
||||
return type;
|
||||
|
@ -73,8 +73,7 @@ public abstract class OpenJPAId
|
|||
* Set the exact type of the described instance once it is known.
|
||||
*/
|
||||
public void setManagedInstanceType(Class type) {
|
||||
this.type = type;
|
||||
this.subs = false;
|
||||
setManagedInstanceType(type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,7 +117,7 @@ trans-not-managed: This broker is not configured to use managed transactions.
|
|||
bad-detached-op: You cannot perform operation {0} on detached object "{1}". \
|
||||
This operation only applies to managed objects.
|
||||
persist-detached: Attempt to persist detached object "{0}". If this is a new \
|
||||
instance, make sure any versino and/or auto-generated primary key fields are \
|
||||
instance, make sure any version and/or auto-generated primary key fields are \
|
||||
null/default when persisting.
|
||||
null-value: The field "{0}" of instance "{1}" contained a null value; \
|
||||
the metadata for this field specifies that nulls are illegal.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
|
||||
|
||||
import java.util.*;
|
||||
import javax.persistence.*;
|
||||
|
||||
import org.apache.openjpa.persistence.jdbc.ElementJoinColumn;
|
||||
|
||||
@Entity
|
||||
@Table(name="TEST")
|
||||
public class RelationOwner {
|
||||
|
||||
private Integer id;
|
||||
private Collection<Superclass> supers = new ArrayList<Superclass>();
|
||||
|
||||
@Id
|
||||
@Column(name="ID")
|
||||
public Integer getId() { return id; }
|
||||
public void setId(Integer id) { this.id = id; }
|
||||
|
||||
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
|
||||
@ElementJoinColumn(name="TEST", referencedColumnName="ID")
|
||||
public Collection<Superclass> getSupers() { return supers; }
|
||||
public void setSupers(Collection<Superclass> supers) { this.supers = supers; }
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
|
||||
|
||||
public class SubID extends SuperID {
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@IdClass(SubID.class)
|
||||
@Table(name="SUB")
|
||||
public class Subclass extends Superclass {
|
||||
|
||||
private String attr2;
|
||||
|
||||
@Column(name="ATTR2")
|
||||
public String getAttr2() { return attr2; }
|
||||
public void setAttr2(String attr2) { this.attr2 = attr2; }
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public abstract class SuperID implements Serializable {
|
||||
|
||||
private Integer id;
|
||||
|
||||
public Integer getId() { return id; }
|
||||
public void setId(Integer id) { this.id = id; }
|
||||
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (!(obj instanceof SuperID)) return false;
|
||||
SuperID pk = (SuperID) obj;
|
||||
if ( pk.getId().equals(id)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@IdClass(SuperID.class)
|
||||
@Table(name="SUPER")
|
||||
@Inheritance(strategy=InheritanceType.JOINED)
|
||||
public abstract class Superclass {
|
||||
|
||||
private Integer id;
|
||||
private String attr1;
|
||||
|
||||
@Id
|
||||
@Column(name="ID")
|
||||
public Integer getId() { return id; }
|
||||
public void setId(Integer id) { this.id = id; }
|
||||
|
||||
@Column(name="ATTR1")
|
||||
public String getAttr1() { return attr1; }
|
||||
public void setAttr1(String attr1) { this.attr1 = attr1; }
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import junit.textui.TestRunner;
|
||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||
|
||||
/**
|
||||
* Test that you traverse an inverse key-baesd relation to an abstract
|
||||
* class using joined inheritance.
|
||||
*/
|
||||
public class TestAbstractJoinedAppId
|
||||
extends SingleEMFTestCase {
|
||||
|
||||
public void setUp() {
|
||||
setUp(Superclass.class, Subclass.class, RelationOwner.class,
|
||||
DROP_TABLES);
|
||||
|
||||
Subclass s = new Subclass();
|
||||
s.setId(99);
|
||||
s.setAttr1("supattr");
|
||||
s.setAttr2("subattr");
|
||||
|
||||
RelationOwner ro = new RelationOwner();
|
||||
ro.setId(1);
|
||||
ro.setSupers(Arrays.asList(new Superclass[] { s }));
|
||||
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.persist(ro);
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
public void testTraverseRelation() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
RelationOwner ro = em.find(RelationOwner.class, 1);
|
||||
assertNotNull(ro);
|
||||
|
||||
Collection supers = ro.getSupers();
|
||||
assertEquals(1, supers.size());
|
||||
Superclass s = (Superclass) supers.iterator().next();
|
||||
assertTrue(s instanceof Subclass);
|
||||
assertEquals(new Integer(99), s.getId());
|
||||
assertEquals("supattr", s.getAttr1());
|
||||
assertEquals("subattr", ((Subclass) s).getAttr2());
|
||||
em.close();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRunner.run(TestAbstractJoinedAppId.class);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue