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:
A. Abram White 2008-07-23 18:20:25 +00:00
parent 2ed656a2a0
commit 37d610ca2c
10 changed files with 198 additions and 35 deletions

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);
}
/**

View File

@ -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.

View File

@ -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; }
}

View File

@ -0,0 +1,5 @@
package org.apache.openjpa.persistence.inheritance.abstractjoinedappid;
public class SubID extends SuperID {
}

View File

@ -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; }
}

View File

@ -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;
}
}
}

View File

@ -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; }
}

View File

@ -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);
}
}