OPENJPA-2175 Fix problem with multiple foreign keys of the same type

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.1.x@1339677 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dianne E. Richards 2012-05-17 16:04:13 +00:00
parent 0176a4005c
commit f80acc3f91
8 changed files with 328 additions and 7 deletions

View File

@ -1117,6 +1117,10 @@ public class FieldMapping
throws SQLException {
_val.setForeignKey(row, sm);
}
public void setForeignKey(Row row, OpenJPAStateManager sm, int targetNumber)
throws SQLException {
_val.setForeignKey(row, sm, targetNumber);
}
public void whereForeignKey(Row row, OpenJPAStateManager sm)
throws SQLException {

View File

@ -178,6 +178,13 @@ public interface ValueMapping
*/
public void setForeignKey(Row row, OpenJPAStateManager rel)
throws SQLException;
/**
* Sets this value's foreign key to the given related object. The object
* may be null. If the object is one of2or more foreign keys with the
* same target, the targetNumber specifies the one to set.
*/
public void setForeignKey(Row row, OpenJPAStateManager rel, int targetNumber)
throws SQLException;
/**
* Sets this value's foreign key to the given related object. The object

View File

@ -159,7 +159,7 @@ public class ValueMappingImpl
_join = JOIN_FORWARD;
}
public ForeignKey getForeignKey(ClassMapping target) {
public ForeignKey getForeignKey(ClassMapping target, int targetNumber) {
if (_fk == null && getValueMappedBy() != null)
return getValueMappedByMapping().getForeignKey(target);
if (target == null)
@ -167,10 +167,15 @@ public class ValueMappingImpl
ClassMapping embeddedMeta = (ClassMapping)getEmbeddedMetaData();
if (embeddedMeta != null) {
FieldMapping[] fields = embeddedMeta.getFieldMappings();
int j = 0;
for (int i = 0; i < fields.length; i++) {
ValueMapping val = fields[i].getValueMapping();
if (val.getDeclaredTypeMapping() == target)
if (val.getDeclaredTypeMapping() == target) {
if (targetNumber == j)
return val.getForeignKey();
else
j++;
}
}
}
if (_fk == null && _cols.length == 0)
@ -198,7 +203,9 @@ public class ValueMappingImpl
return newfk;
}
}
public ForeignKey getForeignKey(ClassMapping target) {
return getForeignKey(target, 0);
}
/**
* Create a forward foreign key to the given target.
*/
@ -323,11 +330,12 @@ public class ValueMappingImpl
_join = direction;
}
public void setForeignKey(Row row, OpenJPAStateManager rel)
public void setForeignKey(Row row, OpenJPAStateManager rel, int targetNumber)
throws SQLException {
if (rel != null)
row.setForeignKey(getForeignKey((ClassMapping) rel.getMetaData()),
if (rel != null) {
row.setForeignKey(getForeignKey((ClassMapping) rel.getMetaData(), targetNumber),
_io, rel);
}
else if (_fk != null)
row.setForeignKey(_fk, _io, null);
else {
@ -340,6 +348,11 @@ public class ValueMappingImpl
}
}
}
public void setForeignKey(Row row, OpenJPAStateManager rel)
throws SQLException {
setForeignKey(row, rel, 0);
}
public void whereForeignKey(Row row, OpenJPAStateManager rel)
throws SQLException {

View File

@ -161,8 +161,17 @@ public class HandlerCollectionTableFieldStrategy
Collection rels = new ArrayList();
if (isEmbedded) {
getRelations(esm, rels, ctx);
Map<ClassMapping,Integer> targets = new HashMap<ClassMapping,Integer>();
for (Object rel : rels) {
elem.setForeignKey(row, (StateManagerImpl)rel);
StateManagerImpl relSm = (StateManagerImpl)rel;
ClassMapping cm =(ClassMapping) relSm.getMetaData();
if(!targets.containsKey(cm)){
targets.put(cm, 0);
}
Integer n = targets.get(cm);
elem.setForeignKey(row, (StateManagerImpl)rel, n);
n++;
targets.put(cm, n);
}
}
}

View File

@ -0,0 +1,69 @@
/*
* 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.foreign.keys;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Embeddable
public class ContainsMultSimpleEntity implements Serializable {
private static final long serialVersionUID = -8576236113079133657L;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(nullable=false)
private SimpleEntity simpleEntity1;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(nullable=false)
private SimpleEntity simpleEntity2;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(nullable=false)
private SimpleEntity simpleEntity3;
public SimpleEntity getSimpleEntity1() {
return simpleEntity1;
}
public void setSimpleEntity1(SimpleEntity simpleEntity1) {
this.simpleEntity1 = simpleEntity1;
}
public SimpleEntity getSimpleEntity2() {
return simpleEntity2;
}
public void setSimpleEntity2(SimpleEntity simpleEntity2) {
this.simpleEntity2 = simpleEntity2;
}
public SimpleEntity getSimpleEntity3() {
return simpleEntity3;
}
public void setSimpleEntity3(SimpleEntity simpleEntity3) {
this.simpleEntity3 = simpleEntity3;
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.foreign.keys;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="FK_SIMPLE")
public class SimpleEntity implements Serializable {
private static final long serialVersionUID = -7535244143281520213L;
@Id
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.foreign.keys;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.EntityManager;
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
/**
* Test multiple keys that have the same Entity as
* the type.
*/
public class TestMultForeignKeys extends SQLListenerTestCase {
public void setUp() {
setUp(SimpleEntity.class,
ContainsMultSimpleEntity.class,
TopLevel.class,
DROP_TABLES);
assertNotNull(emf);
create();
}
public void testCreated() {
EntityManager em = emf.createEntityManager();
TopLevel tl = em.find(TopLevel.class, 1);
assertNotNull(tl);
ArrayList<ContainsMultSimpleEntity> contMultSEColl =
(ArrayList<ContainsMultSimpleEntity>)tl.getContMultSEColl();
assertNotNull(contMultSEColl);
assertEquals(contMultSEColl.size(), 1);
ContainsMultSimpleEntity contMultSE = contMultSEColl.get(0);
assertNotNull(contMultSE);
SimpleEntity se1 = contMultSE.getSimpleEntity1();
assertNotNull(se1);
assertEquals(se1.getId(), 1);
assertEquals(se1.getName(), "name1");
SimpleEntity se2 = contMultSE.getSimpleEntity2();
assertNotNull(se2);
assertEquals(se2.getId(), 2);
assertEquals(se2.getName(), "name2");
SimpleEntity se3 = contMultSE.getSimpleEntity3();
assertNotNull(se3);
assertEquals(se3.getId(), 3);
assertEquals(se3.getName(), "name3");
em.close();
}
private void create() {
EntityManager em = emf.createEntityManager();
assertNotNull(em);
em.getTransaction().begin();
ContainsMultSimpleEntity contMultSE = new ContainsMultSimpleEntity();
SimpleEntity se3 = new SimpleEntity();
se3.setId(3);
se3.setName("name3");
SimpleEntity se1 = new SimpleEntity();
se1.setId(1);
se1.setName("name1");
SimpleEntity se2 = new SimpleEntity();
se2.setId(2);
se2.setName("name2");
contMultSE.setSimpleEntity3(se3);
contMultSE.setSimpleEntity1(se1);
contMultSE.setSimpleEntity2(se2);
Collection<ContainsMultSimpleEntity> contMultSEColl = new ArrayList<ContainsMultSimpleEntity>();
contMultSEColl.add(contMultSE);
TopLevel tl = new TopLevel();
tl.setId(1);
tl.setContMultSEColl(contMultSEColl);
em.persist(tl);
em.getTransaction().commit();
em.close();
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.foreign.keys;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class TopLevel implements Serializable {
private static final long serialVersionUID = -4677719724853263855L;
@Id
private long id;
@ElementCollection
private Collection<ContainsMultSimpleEntity> contMultSEColl;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Collection<ContainsMultSimpleEntity> getContMultSEColl() {
return contMultSEColl;
}
public void setContMultSEColl(Collection<ContainsMultSimpleEntity> contMultSEColl) {
this.contMultSEColl = contMultSEColl;
}
}