Author: faywang
Date: Thu Apr 2 15:38:34 2009
New Revision: 761326
URL: http://svn.apache.org/viewvc?rev=761326&view=rev
Log:
OPENJPA-1004: fix problems with IdClass which has a derived identity and the
relation corresponding to the derived identity uses generatedKey
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Dependent4.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/DependentId4.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Employee4.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java?rev=761326&r1=761325&r2=761326&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
Thu Apr 2 15:38:34 2009
@@ -79,7 +79,7 @@
}
}
- private Collection flush(Collection states, JDBCStore store,
+ protected Collection flush(Collection states, JDBCStore store,
PreparedStatementManager psMgr) {
// run through all the states and update them as necessary
RowManager rowMgr = newRowManager();
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java?rev=761326&r1=761325&r2=761326&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java
Thu Apr 2 15:38:34 2009
@@ -30,14 +30,17 @@
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.Row;
import org.apache.openjpa.jdbc.sql.RowImpl;
import org.apache.openjpa.jdbc.sql.SQLExceptions;
import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.StateManagerImpl;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.ValueStrategies;
import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.OptimisticException;
@@ -123,7 +126,16 @@
}
if (autoAssignColNames != null)
populateAutoAssignCols(stmnt, autoAssign, autoAssignColNames,
row);
-
+ else {
+ StateManagerImpl sm = (StateManagerImpl)row.getPrimaryKey();
+ if (sm != null) {
+ ClassMapping meta = (ClassMapping)sm.getMetaData();
+ if (hasGeneratedKey(meta)) {
+ sm.setObjectId(ApplicationIds.create(
+ sm.getPersistenceCapable(), meta));
+ }
+ }
+ }
} catch (SQLException se) {
throw SQLExceptions.getStore(se, row.getFailedObject(), _dict);
} finally {
@@ -135,6 +147,18 @@
}
}
}
+
+ private boolean hasGeneratedKey(ClassMapping meta) {
+ FieldMapping[] pks = meta.getPrimaryKeyFieldMappings();
+ for (int i = 0; i < pks.length; i++) {
+ ClassMapping pkMeta = pks[i].getTypeMapping();
+ if (pkMeta != null) {
+ return hasGeneratedKey(pkMeta);
+ } else if (pks[i].getValueStrategy() == ValueStrategies.AUTOASSIGN)
+ return true;
+ }
+ return false;
+ }
/**
* This method will only be called when there is auto assign columns.
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?rev=761326&r1=761325&r2=761326&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
Thu Apr 2 15:38:34 2009
@@ -1472,6 +1472,9 @@
public Object fetchObjectId() {
try {
+ if (hasGeneratedKey() && _state instanceof PNewState &&
+ _oid == null)
+ return _oid;
assignObjectId(true);
if (_oid == null || !_broker.getConfiguration().
getCompatibilityInstance().getCopyObjectIds())
@@ -1484,6 +1487,15 @@
throw translate(re);
}
}
+
+ private boolean hasGeneratedKey() {
+ FieldMetaData[] pkFields = _meta.getPrimaryKeyFields();
+ for (int i = 0; i < pkFields.length; i++) {
+ if (pkFields[i].getValueStrategy() == ValueStrategies.AUTOASSIGN)
+ return true;
+ }
+ return false;
+ }
public Object getPCPrimaryKey(Object oid, int field) {
FieldMetaData fmd = _meta.getField(field);
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Dependent4.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Dependent4.java?rev=761326&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Dependent4.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Dependent4.java
Thu Apr 2 15:38:34 2009
@@ -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.enhance.identity;
+import java.io.Serializable;
+
+import javax.persistence.*;
+
+...@entity
+...@idclass(DependentId4.class)
+public class Dependent4 implements Serializable {
+
+ @Id
+ @Column(name = "id", unique = false, nullable = false)
+ private long id;
+
+ @Id
+ @ManyToOne
+ @JoinColumn(name = "parent_id", referencedColumnName = "id")
+ private Employee4 parent;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Employee4 getParent() {
+ return parent;
+ }
+
+ public void setParent(Employee4 parent) {
+ this.parent = parent;
+ }
+}
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/DependentId4.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/DependentId4.java?rev=761326&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/DependentId4.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/DependentId4.java
Thu Apr 2 15:38:34 2009
@@ -0,0 +1,35 @@
+/*
+ * 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.enhance.identity;
+
+public class DependentId4 {
+ public long id;
+ public long parent;
+
+ public boolean equals(Object o) {
+ if (!(o instanceof DependentId4)) return false;
+ if (id != ((DependentId4)o).id) return false;
+ if (parent != ((DependentId4)o).parent) return false;
+ return true;
+ }
+
+ public int hashCode() {
+ return (int) (id + 31 * parent);
+ }
+}
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Employee4.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Employee4.java?rev=761326&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Employee4.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Employee4.java
Thu Apr 2 15:38:34 2009
@@ -0,0 +1,63 @@
+/*
+ * 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.enhance.identity;
+
+import javax.persistence.*;
+
+import java.util.*;
+
+...@entity
+public class Employee4 {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id", insertable = false, updatable = false, nullable =
false)
+ private long id;
+
+ @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")
+ private List<Dependent4> children = new ArrayList<Dependent4>();
+
+ private int age;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public List<Dependent4> getChildren() {
+ return children;
+ }
+
+ public void addChild(Dependent4 child) {
+ if (child == null) {
+ throw new IllegalArgumentException("Cannot add a null Child");
+ }
+ this.getChildren().add(child);
+ }
+
+ public void setChildren(List<Dependent4> children) {
+ this.children = children;
+ }
+}
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java?rev=761326&r1=761325&r2=761326&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java
Thu Apr 2 15:38:34 2009
@@ -27,8 +27,6 @@
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
-import junit.framework.Assert;
-
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.kernel.StateManagerImpl;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
@@ -66,6 +64,8 @@
public int eId2 = 1;
public int dId2 = 1;
public int eId3 = 1;
+ public int eId4 = 1;
+ public int dId4 = 1;
public int dId3 = 1;
public int pId1 = 1;
public int mId1 = 1;
@@ -84,7 +84,7 @@
Person2.class, Person3.class, MedicalHistory3.class,
Person4.class, PersonId4.class, MedicalHistory4.class,
Dependent3.class, Employee3.class, DependentId3.class,
- Parent3.class);
+ Parent3.class, Dependent4.class, Employee4.class);
}
/**
@@ -641,4 +641,66 @@
MedicalHistory4 m1 = m.getPatient().getMedical();
assertEquals(m1, m);
}
+
+ /**
+ * Derived Identity with IdClass and generatedKey
+ */
+ public void testPersistDerivedIdentityUsingIdClassAndGeneratedKey() {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ for (int i = 0; i < numEmployees; i++)
+ persistEmployee4(em, eId4++);
+ tran.begin();
+ em.flush();
+ tran.commit();
+ em.close();
+ }
+
+ /**
+ * Derived Identity with IdClass and generatedKey
+ */
+ public void testMergeDerivedIdentityUsingIdClassAndGeneratedKey() {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ for (int i = 0; i < numEmployees; i++)
+ mergeEmployee4(em, eId4++);
+ tran.begin();
+ em.flush();
+ tran.commit();
+ em.close();
+ }
+
+ public Employee4 persistEmployee4(EntityManager em, int id) {
+ Employee4 p = new Employee4();
+ p.setAge(id);
+ for (int i = 0; i < numDependentsPerEmployee; i++) {
+ Dependent4 c = persistDependent4(em, dId4++, p);
+ p.addChild(c);
+ }
+ em.persist(p);
+ return p;
+ }
+
+ public Dependent4 persistDependent4(EntityManager em, int id, Employee4 p)
{
+ Dependent4 c = new Dependent4();
+ c.setId(id);
+ c.setParent(p);
+ em.persist(c);
+ return c;
+ }
+
+ public Employee4 mergeEmployee4(EntityManager em, int id) {
+ Employee4 e = new Employee4();
+ e.setAge(id);
+ e = em.merge(e);
+ for (int i = 0; i < numDependentsPerEmployee; i++) {
+ Dependent4 d = new Dependent4();
+ d.setId(dId4++);
+ d.setParent(e);
+ // do not need to merge d, as Employee is cascade.All
+ d = em.merge(d);
+ e.addChild(d);
+ }
+ return e;
+ }
}