OPENJPA-925 Bidirectional OneToOne relation incorrectly set in loadEagerJoin

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@745408 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Catalina Wei 2009-02-18 08:06:12 +00:00
parent f08e4e1791
commit d1c23c2d9d
4 changed files with 201 additions and 5 deletions

View File

@ -644,8 +644,11 @@ public class RelationFieldStrategy
if (mappedByFieldMapping != null) { if (mappedByFieldMapping != null) {
ValueMapping val = mappedByFieldMapping.getValueMapping(); ValueMapping val = mappedByFieldMapping.getValueMapping();
ClassMetaData decMeta = val.getTypeMetaData(); ClassMetaData decMeta = val.getTypeMetaData();
// this inverse field does not have corresponding classMapping // eager loading a child from its toOne parent and
// its value may be a collection/map etc. // the parent has @OneToOne(mappedBy="parent") child relation.
// By saving the mapped-by info in 'res' is to
// avoid unneeded SQL pushdown that would otherwise gets
// generated.
if (decMeta != null) { if (decMeta != null) {
mappedByValue = sm.getPersistenceCapable(); mappedByValue = sm.getPersistenceCapable();
res.setMappedByFieldMapping(mappedByFieldMapping); res.setMappedByFieldMapping(mappedByFieldMapping);
@ -655,6 +658,12 @@ public class RelationFieldStrategy
sm.storeObject(field.getIndex(), res.load(cls, store, fetch, sm.storeObject(field.getIndex(), res.load(cls, store, fetch,
eagerJoin(res.newJoins(), cls, false))); eagerJoin(res.newJoins(), cls, false)));
// reset mapped by is needed for OneToOne bidirectional relations
// having a mapped-by parent to correctly set the parent-child
// relation.
res.setMappedByFieldMapping(null);
res.setMappedByValue(null);
} }
public void load(OpenJPAStateManager sm, JDBCStore store, public void load(OpenJPAStateManager sm, JDBCStore store,

View File

@ -0,0 +1,61 @@
/*
* 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.relations;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Version;
@Entity
public class OneOneChild {
@Id
@GeneratedValue
private long id;
private String name;
@OneToOne
private OneOneParent parent;
@Version
private Integer optLock;
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OneOneParent getParent() {
return parent;
}
public void setParent(OneOneParent parent) {
this.parent = parent;
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.relations;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Version;
@Entity
public class OneOneParent {
@Id
@GeneratedValue
private long id;
private String name;
@OneToOne(mappedBy="parent")
private OneOneChild child;
@Version
private Integer optLock;
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OneOneChild getChild() {
return child;
}
public void setChild(OneOneChild child) {
this.child = child;
}
}

View File

@ -35,7 +35,8 @@ public class TestManyEagerSQL
public void setUp() { public void setUp() {
setUp( setUp(
OneManyEagerParent.class, OneManyEagerChild.class, OneManyEagerParent.class, OneManyEagerChild.class,
OneManyLazyChild.class); OneManyLazyChild.class, OneOneParent.class,
OneOneChild.class);
EntityManager em = emf.createEntityManager(); EntityManager em = emf.createEntityManager();
em.getTransaction().begin(); em.getTransaction().begin();
@ -56,6 +57,17 @@ public class TestManyEagerSQL
em.persist(parent); em.persist(parent);
} }
for (int i = 0; i < 3; i++) {
OneOneParent parent = new OneOneParent();
parent.setName("parent" + i);
OneOneChild child = new OneOneChild();
child.setName("child" + i);
parent.setChild(child);
child.setParent(parent);
em.persist(child);
em.persist(parent);
}
em.flush(); em.flush();
em.getTransaction().commit(); em.getTransaction().commit();
em.close(); em.close();
@ -190,6 +202,59 @@ public class TestManyEagerSQL
em.close(); em.close();
} }
public void testOneToOneParentQuery() {
sql.clear();
OpenJPAEntityManager em = emf.createEntityManager();
String query = "select p FROM OneOneParent p";
Query q = em.createQuery(query);
List list = q.getResultList();
assertEquals(3, list.size());
// Expected SQLs:
// SELECT t0.id, t0.optLock, t1.id, t1.optLock, t1.name, t2.id,
// t2.optLock, t2.CHILD_ID, t2.name, t0.name
// FROM OneOneParent t0
// LEFT OUTER JOIN OneOneChild t1 ON t0.CHILD_ID = t1.id
// LEFT OUTER JOIN OneOneParent t2 ON t1.PARENT_ID = t2.id
assertEquals(1, sql.size());
sql.clear();
for (int i = 0; i < list.size(); i++) {
OneOneParent p = (OneOneParent) list.get(i);
assertEquals(p, p.getChild().getParent());
}
assertEquals(0, sql.size());
em.close();
}
public void testOneToOneChildQuery() {
sql.clear();
OpenJPAEntityManager em = emf.createEntityManager();
String query = "select c FROM OneOneChild c";
Query q = em.createQuery(query);
List list = q.getResultList();
assertEquals(3, list.size());
// Expected SQLs:
assertEquals(1, sql.size());
sql.clear();
for (int i = 0; i < list.size(); i++) {
OneOneChild c = (OneOneChild) list.get(i);
assertEquals(c, c.getParent().getChild());
}
assertEquals(0, sql.size());
em.close();
}
public static void main(String[] args) { public static void main(String[] args) {
TestRunner.run(TestManyEagerSQL.class); TestRunner.run(TestManyEagerSQL.class);
} }