mirror of https://github.com/apache/openjpa.git
OPENJPA-679 java.lang.ArrayIndexOutOfBoundsException may occur when a relation field is annotated as a primary key and a foreign key
Commit patch provided by Fay Wang git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@685042 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ffb59c35fc
commit
f4845dae9b
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.jdbc.meta;
|
package org.apache.openjpa.jdbc.meta;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -32,12 +30,12 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.apache.openjpa.enhance.PersistenceCapable;
|
import org.apache.openjpa.enhance.PersistenceCapable;
|
||||||
import org.apache.openjpa.enhance.Reflection;
|
import org.apache.openjpa.enhance.Reflection;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCStore;
|
import org.apache.openjpa.jdbc.kernel.JDBCStore;
|
||||||
import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
|
import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
|
||||||
|
import org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy;
|
||||||
import org.apache.openjpa.jdbc.schema.Column;
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
import org.apache.openjpa.jdbc.schema.ColumnIO;
|
import org.apache.openjpa.jdbc.schema.ColumnIO;
|
||||||
import org.apache.openjpa.jdbc.schema.ForeignKey;
|
import org.apache.openjpa.jdbc.schema.ForeignKey;
|
||||||
|
@ -91,6 +89,7 @@ public class ClassMapping
|
||||||
|
|
||||||
// maps columns to joinables
|
// maps columns to joinables
|
||||||
private final Map _joinables = Collections.synchronizedMap(new HashMap());
|
private final Map _joinables = Collections.synchronizedMap(new HashMap());
|
||||||
|
private boolean redoPrimaryKeyColumns = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Supply described type and owning repository.
|
* Constructor. Supply described type and owning repository.
|
||||||
|
@ -418,18 +417,26 @@ public class ClassMapping
|
||||||
* class uses to link to its superclass table.
|
* class uses to link to its superclass table.
|
||||||
*/
|
*/
|
||||||
public Column[] getPrimaryKeyColumns() {
|
public Column[] getPrimaryKeyColumns() {
|
||||||
if (_cols.length == 0 && getIdentityType() == ID_APPLICATION
|
if (getIdentityType() == ID_APPLICATION && isMapped()) {
|
||||||
&& isMapped()) {
|
if (_cols.length == 0 || redoPrimaryKeyColumns) {
|
||||||
FieldMapping[] pks = getPrimaryKeyFieldMappings();
|
FieldMapping[] pks = getPrimaryKeyFieldMappings();
|
||||||
Collection cols = new ArrayList(pks.length);
|
Collection cols = new ArrayList(pks.length);
|
||||||
Column[] fieldCols;
|
Column[] fieldCols;
|
||||||
for (int i = 0; i < pks.length; i++) {
|
for (int i = 0; i < pks.length; i++) {
|
||||||
fieldCols = pks[i].getColumns();
|
fieldCols = pks[i].getColumns();
|
||||||
|
if (fieldCols.length == 0) {
|
||||||
|
// some pk columns depends on fk. At this moment,
|
||||||
|
// the fk may not contain complete information.
|
||||||
|
// need to redo the primary key again later on
|
||||||
|
redoPrimaryKeyColumns = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (int j = 0; j < fieldCols.length; j++)
|
for (int j = 0; j < fieldCols.length; j++)
|
||||||
cols.add(fieldCols[j]);
|
cols.add(fieldCols[j]);
|
||||||
}
|
}
|
||||||
_cols = (Column[]) cols.toArray(new Column[cols.size()]);
|
_cols = (Column[]) cols.toArray(new Column[cols.size()]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return _cols;
|
return _cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,9 +833,27 @@ public class ClassMapping
|
||||||
// recursion, then resolve all fields
|
// recursion, then resolve all fields
|
||||||
resolveNonRelationMappings();
|
resolveNonRelationMappings();
|
||||||
FieldMapping[] fms = getFieldMappings();
|
FieldMapping[] fms = getFieldMappings();
|
||||||
for (int i = 0; i < fms.length; i++)
|
for (int i = 0; i < fms.length; i++) {
|
||||||
if (fms[i].getDefiningMetaData() == this)
|
if (fms[i].getDefiningMetaData() == this) {
|
||||||
|
if (fms[i].getForeignKey() != null &&
|
||||||
|
fms[i].getStrategy() instanceof RelationFieldStrategy) {
|
||||||
|
// set resolve mode to force this field mapping to be
|
||||||
|
// resolved again. The need to resolve again occurs when
|
||||||
|
// a primary key is a relation field with the foreign key
|
||||||
|
// annotation. In this situation, this primary key field
|
||||||
|
// mapping is resolved during the call to
|
||||||
|
// resolveNonRelationMapping. Since it is a relation
|
||||||
|
// field, the foreign key will be constructed. However,
|
||||||
|
// the primary key of the parent entity may not have been
|
||||||
|
// resolved yet, resulting in missing informaiton in the fk
|
||||||
|
fms[i].setResolve(MODE_META);
|
||||||
|
|
||||||
|
// set strategy to null to force fk to be re-constructed
|
||||||
|
fms[i].setStrategy(null, false);
|
||||||
|
}
|
||||||
fms[i].resolve(MODE_MAPPING);
|
fms[i].resolve(MODE_MAPPING);
|
||||||
|
}
|
||||||
|
}
|
||||||
fms = getDeclaredUnmanagedFieldMappings();
|
fms = getDeclaredUnmanagedFieldMappings();
|
||||||
for (int i = 0; i < fms.length; i++)
|
for (int i = 0; i < fms.length; i++)
|
||||||
fms[i].resolve(MODE_MAPPING);
|
fms[i].resolve(MODE_MAPPING);
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.jdbc.ForeignKey;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@IdClass(C.CId.class)
|
||||||
|
@Table(name="C4")
|
||||||
|
public class C {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String cId;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@ForeignKey
|
||||||
|
@Id
|
||||||
|
private CM cm;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy="c")
|
||||||
|
private Set<D> ds = new HashSet<D>();
|
||||||
|
|
||||||
|
public C() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCId() {
|
||||||
|
return cId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCId(String cId) {
|
||||||
|
this.cId = cId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CM getCm() {
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCm(CM cm) {
|
||||||
|
this.cm = cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<D> getDs() {
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDs(Set<D> ds) {
|
||||||
|
this.ds = ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CId{
|
||||||
|
String cId;
|
||||||
|
CM.CMId cm;
|
||||||
|
|
||||||
|
public String getCId() {
|
||||||
|
return cId;
|
||||||
|
}
|
||||||
|
public void setCId(String id) {
|
||||||
|
cId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public CM.CMId getCm() {
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
public void setCm(CM.CMId cm) {
|
||||||
|
this.cm = cm;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || !(obj instanceof CId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CId id = (CId) obj;
|
||||||
|
|
||||||
|
return (this.getCId() == id.getCId() || (this.getCId() != null &&
|
||||||
|
this.getCId().equals(id.getCId())))
|
||||||
|
&& (this.getCm() == id.getCm() || (this.getCm() != null &&
|
||||||
|
this.getCm().equals(id.getCm())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return ((this.getCId() != null) ? this.getCId().hashCode():0)
|
||||||
|
^ ((this.getCm() != null)? this.getCm().hashCode():0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.jdbc.ForeignKey;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@IdClass(CM.CMId.class)
|
||||||
|
@Table(name="CM4")
|
||||||
|
public class CM {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String cmId;
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="cm")
|
||||||
|
private Set<C> cs = new HashSet<C>();
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@ForeignKey
|
||||||
|
@Id
|
||||||
|
private E e;
|
||||||
|
|
||||||
|
public CM() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCmId() {
|
||||||
|
return cmId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCmId(String cmId) {
|
||||||
|
this.cmId = cmId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<C> getCs() {
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCs(Set<C> cs) {
|
||||||
|
this.cs = cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addC(C c){
|
||||||
|
cs.add(c);
|
||||||
|
c.setCm(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public E getE() {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setE(E e) {
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CMId{
|
||||||
|
private String cmId;
|
||||||
|
private String e;
|
||||||
|
|
||||||
|
public String getCmId() {
|
||||||
|
return cmId;
|
||||||
|
}
|
||||||
|
public void setCmId(String id) {
|
||||||
|
cmId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getE() {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
public void setE(String e) {
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null && ! (obj instanceof CMId))
|
||||||
|
return false;
|
||||||
|
CMId id = (CMId) obj;
|
||||||
|
return ( this.getCmId() == id.getCmId() ||
|
||||||
|
(this.getCmId() != null && this.getCmId().equals(id.getCmId())))
|
||||||
|
&& ( this.getE() == id.getE() || (this.getE() != null &&
|
||||||
|
this.getE().equals(id.getE())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (this.getCmId() != null? this.getCmId().hashCode():0)
|
||||||
|
^ (this.getE()!= null ? this.getE().hashCode():0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* 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.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.jdbc.ForeignKey;
|
||||||
|
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="D4")
|
||||||
|
@IdClass(D.CId.class)
|
||||||
|
public class D {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@ForeignKey
|
||||||
|
private C c;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String a;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@ForeignKey
|
||||||
|
@Id
|
||||||
|
private VC vc;
|
||||||
|
|
||||||
|
public D() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getA() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setA(String a) {
|
||||||
|
this.a = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public C getC() {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setC(C c) {
|
||||||
|
this.c = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VC getVc() {
|
||||||
|
return vc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVc(VC vc) {
|
||||||
|
this.vc = vc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class CId{
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private VC.VCId vc;
|
||||||
|
|
||||||
|
public VC.VCId getVc() {
|
||||||
|
return vc;
|
||||||
|
}
|
||||||
|
public void setVc(VC.VCId vc) {
|
||||||
|
this.vc = vc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || ! (obj instanceof CId))
|
||||||
|
return false;
|
||||||
|
CId id = (CId) obj;
|
||||||
|
return (this.getId() == id.getId() || (this.getId() != null &&
|
||||||
|
this.getId().equals(id.getId())))
|
||||||
|
&& (this.getVc() == id.getVc() || (this.getVc() != null &&
|
||||||
|
this.getVc().equals(id.getVc())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (this.getId() != null ? this.getId().hashCode():0)
|
||||||
|
^ (this.getVc() != null ? this.getVc().hashCode():0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="E4")
|
||||||
|
public class E {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String eId;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, mappedBy = "e")
|
||||||
|
private Set<VCS> vcss = new HashSet<VCS>();
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, mappedBy = "e")
|
||||||
|
private Set<CM> cms = new HashSet<CM>();
|
||||||
|
|
||||||
|
public E() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<CM> getCms() {
|
||||||
|
return cms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCms(Set<CM> cms) {
|
||||||
|
this.cms = cms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEId() {
|
||||||
|
return eId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEId(String id) {
|
||||||
|
eId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<VCS> getVcss() {
|
||||||
|
return vcss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcss(Set<VCS> vcss) {
|
||||||
|
this.vcss = vcss;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
|
||||||
|
|
||||||
|
public class TestRelationFieldAsPrimaryKeyAndForeignKey
|
||||||
|
extends SingleEMFTestCase {
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
setUp(C.class, CM.class, D.class, E.class, VC.class, VCS.class);
|
||||||
|
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
try {
|
||||||
|
em.getTransaction().begin();
|
||||||
|
List<E> es = (List<E>) em.createQuery(
|
||||||
|
"Select e from E e").getResultList();
|
||||||
|
for (E e : es)
|
||||||
|
em.remove(e);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
E e = new E();
|
||||||
|
e.setEId("E1");
|
||||||
|
e.setName("E1");
|
||||||
|
|
||||||
|
VC vc = new VC();
|
||||||
|
vc.setVcId("VC1");
|
||||||
|
|
||||||
|
VCS vcset = new VCS();
|
||||||
|
vcset.setVcsId("VCS1");
|
||||||
|
vcset.setName("VCSET1");
|
||||||
|
vcset.addVC(vc);
|
||||||
|
vcset.setE(e);
|
||||||
|
|
||||||
|
C c = new C();
|
||||||
|
c.setCId("C1");
|
||||||
|
|
||||||
|
CM cm = new CM();
|
||||||
|
cm.setCmId("CM1");
|
||||||
|
cm.setE(e);
|
||||||
|
cm.addC(c);
|
||||||
|
|
||||||
|
D d = new D();
|
||||||
|
d.setA("addr");
|
||||||
|
d.setVc(vc);
|
||||||
|
d.setId("IM1");
|
||||||
|
|
||||||
|
em.persist(e);
|
||||||
|
em.persist(vc);
|
||||||
|
em.persist(vcset);
|
||||||
|
em.persist(c);
|
||||||
|
em.persist(cm);
|
||||||
|
em.persist(d);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnboundEntities() {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
VCS vcSet = new VCS();
|
||||||
|
vcSet.setVcsId("VCSET2");
|
||||||
|
vcSet.setName("VCSET2");
|
||||||
|
try {
|
||||||
|
em.persist(vcSet);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
Assert.fail("didn't throw expected PersistenceException");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// test pass
|
||||||
|
} finally {
|
||||||
|
if (em.getTransaction().isActive())
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
VC vc = new VC();
|
||||||
|
vc.setVcId("VC2");
|
||||||
|
try {
|
||||||
|
em.persist(vc);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
Assert.fail("didn't throw expected PersistenceException");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// test pass
|
||||||
|
} finally {
|
||||||
|
if (em.getTransaction().isActive())
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
CM cm = new CM();
|
||||||
|
cm.setCmId("CMID2");
|
||||||
|
try {
|
||||||
|
em.persist(cm);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
Assert.fail("didn't throw expected PersistenceException");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// test pass
|
||||||
|
} finally {
|
||||||
|
if (em.getTransaction().isActive())
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
C c = new C();
|
||||||
|
c.setCId("CID2");
|
||||||
|
try {
|
||||||
|
em.persist(c);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
Assert.fail("didn't throw expected PersistenceException");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// test pass
|
||||||
|
} finally {
|
||||||
|
if (em.getTransaction().isActive())
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQuery() {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
List<E> es = (List<E>) em.createQuery(
|
||||||
|
"Select e from E e where e.name='E1'").getResultList();
|
||||||
|
Assert.assertEquals(1, es.size());
|
||||||
|
E e = (E) es.get(0);
|
||||||
|
Assert.assertEquals("E1", e.getName());
|
||||||
|
Assert.assertEquals(1, e.getVcss().size());
|
||||||
|
Assert.assertEquals(1, e.getCms().size());
|
||||||
|
Assert.assertEquals(1, e.getVcss().size());
|
||||||
|
|
||||||
|
// Get virtual container set and check that it has a reference to the
|
||||||
|
// ensemble
|
||||||
|
List<VCS> vcss = (List<VCS>) em.createQuery(
|
||||||
|
"Select vcset from VCS vcset where vcset.vcsId='VCS1'")
|
||||||
|
.getResultList();
|
||||||
|
Assert.assertEquals(1, vcss.size());
|
||||||
|
Assert.assertEquals(e, ((VCS) vcss.get(0)).getE());
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeletes() {
|
||||||
|
// Remove VC set and check that all VCs belonging to that set are
|
||||||
|
// deleted but not the ensemble itself
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
VCS vcset = (VCS) em.createQuery(
|
||||||
|
"Select vcset from VCS vcset where vcset.vcsId='VCS1'")
|
||||||
|
.getSingleResult();
|
||||||
|
em.remove(vcset);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Get virtualContainer
|
||||||
|
List<VC> vcs = (List<VC>) em.createQuery(
|
||||||
|
"Select vc from VC vc where vc.vcId='VC1'")
|
||||||
|
.getResultList();
|
||||||
|
Assert.assertEquals(0, vcs.size());
|
||||||
|
|
||||||
|
// Make sure E and I are still there
|
||||||
|
List<E> es = (List<E>) em.createQuery(
|
||||||
|
"Select e from E e").getResultList();
|
||||||
|
Assert.assertEquals(1, es.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
List<E> es = (List<E>) em.createQuery(
|
||||||
|
"Select e from E e").getResultList();
|
||||||
|
for (E e : es) {
|
||||||
|
em.remove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.relations.VCS.VCSId;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.jdbc.ForeignKey;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="VC4")
|
||||||
|
@IdClass(VC.VCId.class)
|
||||||
|
|
||||||
|
public class VC {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String vcId;
|
||||||
|
|
||||||
|
// @ManyToOne
|
||||||
|
// @ForeignKey
|
||||||
|
// private I i;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@ForeignKey
|
||||||
|
@Id
|
||||||
|
private VCS vcs;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "vc")
|
||||||
|
private Set<D> ds = new HashSet<D>();
|
||||||
|
|
||||||
|
public VC() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVcId() {
|
||||||
|
return vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcId(String vcId) {
|
||||||
|
this.vcId = vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<D> getDs() {
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDs(Set<D> ds) {
|
||||||
|
this.ds = ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VCS getVcs() {
|
||||||
|
return vcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcs(VCS vcs) {
|
||||||
|
this.vcs = vcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class VCId {
|
||||||
|
private String vcId;
|
||||||
|
|
||||||
|
private VCSId vcs;
|
||||||
|
|
||||||
|
public String getVcId() {
|
||||||
|
return vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcId(String vcId) {
|
||||||
|
this.vcId = vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VCSId getVcs() {
|
||||||
|
return vcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcs(VCSId vcs) {
|
||||||
|
this.vcs = vcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || !(obj instanceof VCId))
|
||||||
|
return false;
|
||||||
|
VCId id = (VCId) obj;
|
||||||
|
return (this.getVcId() == id.getVcId() ||
|
||||||
|
(this.getVcId() == null &&
|
||||||
|
this.getVcId().equals(id.getVcId()))) &&
|
||||||
|
(this.getVcs() == id.getVcs() ||
|
||||||
|
(this.getVcs() == null && this
|
||||||
|
.getVcs().equals(id.getVcs())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (this.getVcId() != null ? this.getVcId().hashCode() : 0)
|
||||||
|
^ (this.getVcs() != null ? this.getVcs().hashCode() : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.jdbc.ForeignKey;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="VCS4")
|
||||||
|
@IdClass(VCS.VCSId.class)
|
||||||
|
public class VCS {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String vcsId;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@ForeignKey
|
||||||
|
@Id
|
||||||
|
private E e;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy = "vcs")
|
||||||
|
private Set<VC> vcs = new HashSet<VC>();
|
||||||
|
|
||||||
|
public VCS() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getVcsId() {
|
||||||
|
return vcsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setVcsId(String vcsId) {
|
||||||
|
this.vcsId = vcsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public E getE() {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setE(E e) {
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Set<VC> getVcs() {
|
||||||
|
return vcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setVcs(Set<VC> vcs) {
|
||||||
|
this.vcs = vcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addVC(VC vc){
|
||||||
|
vcs.add(vc);
|
||||||
|
vc.setVcs(this);
|
||||||
|
}
|
||||||
|
public static class VCSId{
|
||||||
|
private String vcsId;
|
||||||
|
private String e;
|
||||||
|
|
||||||
|
|
||||||
|
public String getE() {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setE(String e) {
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVcsId() {
|
||||||
|
return vcsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcsId(String vcsId) {
|
||||||
|
this.vcsId = vcsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || ! (obj instanceof VCSId))
|
||||||
|
return false;
|
||||||
|
VCSId id = (VCSId) obj;
|
||||||
|
return (this.getVcsId() == id.getVcsId() ||
|
||||||
|
(this.getVcsId() != null &&
|
||||||
|
this.getVcsId().equals(id.getVcsId())))
|
||||||
|
&& (this.getE() == id.getE() || (this.getE() != null
|
||||||
|
&& this.getE().equals(id.getE())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (this.getVcsId() != null ?this.getVcsId().hashCode():0)
|
||||||
|
^ (this.getE() != null ? this.getE().hashCode():0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue