You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by cu...@apache.org on 2012/09/27 21:36:44 UTC
svn commit: r1391185 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/
Author: curtisr7
Date: Thu Sep 27 19:36:44 2012
New Revision: 1391185
URL: http://svn.apache.org/viewvc?rev=1391185&view=rev
Log:
OPENJPA-2269: Fix duplicate key exception when inserting into sequence table on multithreaded init.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestTableGeneratorMultithreadedInitialization.java (with props)
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java?rev=1391185&r1=1391184&r2=1391185&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java Thu Sep 27 19:36:44 2012
@@ -474,6 +474,7 @@ public class TableJDBCSeq extends Abstra
*/
private void insertSequence(ClassMapping mapping, Connection conn)
throws SQLException {
+
if (_log.isTraceEnabled())
_log.trace(_loc.get("insert-seq"));
@@ -895,12 +896,20 @@ public class TableJDBCSeq extends Abstra
closeConnection(conn);
if (!sequenceSet) {
- // insert a new sequence column.
- // Prefer connection2 / non-jta-data-source when inserting
- // a sequence column regardless of Seq.type.
- conn = _conf.getDataSource2(store.getContext())
- .getConnection();
- insertSequence(mapping, conn);
+ // insert a new sequence column. Prefer connection2 / non-jta-data-source when inserting a
+ // sequence column regardless of Seq.type.
+ conn = _conf.getDataSource2(store.getContext()).getConnection();
+ try {
+ insertSequence(mapping, conn);
+ } catch (SQLException e) {
+ // it is possible another thread already got in and inserted this sequence. Try to keep going
+ if (_log.isTraceEnabled()) {
+ _log.trace(
+ "Caught an exception while trying to insert sequence. Will try to reselect the " +
+ "seqence. ", e);
+ }
+ }
+
conn.close();
// now we should be able to update using the connection per
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog.java?rev=1391185&r1=1391184&r2=1391185&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog.java Thu Sep 27 19:36:44 2012
@@ -50,4 +50,45 @@ public class Dog {
public void setName(String name) {
this.name = name;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Dog other = (Dog) obj;
+ if (id != other.id) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Dog [id=" + id + ", name=" + name + "]";
+ }
+
+
}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestTableGeneratorMultithreadedInitialization.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestTableGeneratorMultithreadedInitialization.java?rev=1391185&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestTableGeneratorMultithreadedInitialization.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestTableGeneratorMultithreadedInitialization.java Thu Sep 27 19:36:44 2012
@@ -0,0 +1,116 @@
+/*
+ * 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.generationtype;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase;
+
+public class TestTableGeneratorMultithreadedInitialization extends AbstractPersistenceTestCase {
+ Object[] props = new Object[] { Dog.class
+ // , "openjpa.Log", "SQL=trace"
+ };
+
+ public void setUp() throws Exception {
+ EntityManagerFactory emf = createNamedEMF(getPersistenceUnitName(), props);
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.createNativeQuery("DROP TABLE ID_Gen").executeUpdate();
+ em.createNativeQuery("DROP TABLE dog").executeUpdate();
+ em.getTransaction().commit();
+ emf.close();
+ }
+
+ public void test() throws Exception {
+
+ EntityManagerFactory emf1 = createNamedEMF(getPersistenceUnitName(), props);
+ EntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(), props);
+ EntityManagerFactory emf3 = createNamedEMF(getPersistenceUnitName(), props);
+
+ assertNotEquals(emf1, emf2);
+
+ emf1.createEntityManager().close();
+ emf2.createEntityManager().close();
+
+ final EntityManager em1 = emf1.createEntityManager();
+ final EntityManager em2 = emf2.createEntityManager();
+ final EntityManager em3 = emf3.createEntityManager();
+
+ Worker w1 = new Worker(em1);
+ Worker w2 = new Worker(em2);
+
+ w1.start();
+ w2.start();
+
+ w1.join();
+ w2.join();
+
+ assertNull("Caught an exception in worker 1" + w1.getException(), w1.getException());
+ assertNull("Caught an exception in worker 2" + w2.getException(), w2.getException());
+
+ Dog d1 = w1.getDog();
+ Dog d2 = w2.getDog();
+ assertNotNull(d1);
+ assertNotNull(d2);
+ assertNotEquals(d1, d2);
+
+ Dog d1_found = em3.find(Dog.class, d1.getId());
+ Dog d2_found = em3.find(Dog.class, d2.getId());
+
+ assertEquals(d1_found, d1);
+ assertEquals(d2_found, d2);
+
+ emf1.close();
+ emf2.close();
+ emf3.close();
+ }
+
+ class Worker extends Thread {
+ final EntityManager em;
+ Dog dog = new Dog();
+ Exception exception;
+
+ Worker(EntityManager e) {
+ em = e;
+ }
+
+ public Dog getDog() {
+ return dog;
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+ @Override
+ public void run() {
+ try {
+ em.getTransaction().begin();
+ em.persist(dog);
+ em.getTransaction().commit();
+ em.close();
+ } catch (Exception e) {
+ exception = e;
+ e.printStackTrace();
+ // TODO: handle exception
+ }
+ }
+ }
+}
Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestTableGeneratorMultithreadedInitialization.java
------------------------------------------------------------------------------
svn:eol-style = native