2012-03-08 4 views
0

データベースにオブジェクトを保存するときにMySQLIntegrityConstraintViolationExceptionが表示されます。私はこのエラーの意味を知っていますが、私はそれを回避することはできません。JDO /重複エントリ例外

エラー:Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '12345' for key 'PRIMARY'

は基本的に、私は、データベースへのコースのオブジェクトを保存したいです。各コースオブジェクトは、いくつかのスタッドパスオブジェクトを有していてもよく、いくつかのコースオブジェクトの一部であってもよい。

PersistenceManager pm = pmf.getPersistenceManager(); 
Transaction tx = pm.currentTransaction(); 

try { 
    tx.begin(); 
    Query query = pm.newQuery(Studypath.class,"studypathID == paramStudypathID"); 
    query.declareParameters("Integer paramStudypathID"); 
    query.setUnique(true); 
    Studypath dbStudypath = (Studypath)query.execute(12345); 

    Studypath detachedStudypath = null; 
    if (dbStudypath != null) { 
     detachedStudypath = (Studypath)pm.detachCopy(dbStudypath); 
    } else { 
     Studypath newStudypath = new Studypath(); 
     // ... 
     pm.makePersistent(newStudypath); 
     detachedStudypath = (Studypath)pm.detachCopy(newStudypath); 
    } 

    tx.commit(); 

    // now I want to add this detached studypath to my newly created course 
    Course c = new Course(); 
    c.addStudypath(detachedStudypath); 

    tx.begin(); 
    pm.makePersistent(c); // <== error 
    tx.commit(); 
} 
catch (Exception e) 
{ 
    //... handle exceptions 
} 
finally 
{ 
    if (tx.isActive()) 
    { 
     // Error occurred so rollback the transaction 
     tx.rollback(); 
    } 
    pm.close(); 
} 

Course.java

@PersistenceCabable 
public class Course { 
    // ... 

    @Persistent 
    private Set<Studypath> studypaths; 
} 

Studypath.java

@PersistenceCabable 
public class Studypath { 
    // ... 

    @Persistent 
    @PrimaryKey 
    private Integer studypathID; 
} 

私が欠けている明らかな間違いがありますか?前もって感謝します!

アップデート(ログ):

DEBUG [DataNucleus.Datastore.Native] - SELECT 'Courses.Studypath' AS NUCLEUS_TYPE, ... FROM `STUDYPATH` `A0` WHERE `A0`.`STUDYPATHID` = <12345> // this one already exists 
DEBUG [DataNucleus.Datastore.Retrieve] - Execution Time = 0 ms 
DEBUG [DataNucleus.Datastore.Retrieve] - Retrieving PreparedStatement for connection "jdbc:mysql://127.0.0.1/database, UserName=user, MySQL-AB JDBC Driver" 

DEBUG [DataNucleus.Datastore.Native] - SELECT 'Courses.Course' AS NUCLEUS_TYPE, ... FROM `COURSE` `A0` WHERE `A0`.`COURSEID` = <1111> // there is no such course, thus it gets created 
DEBUG [DataNucleus.Datastore.Retrieve] - Execution Time = 1 ms 
DEBUG [DataNucleus.Datastore.Retrieve] - Retrieving PreparedStatement for connection "jdbc:mysql://127.0.0.1/database, UserName=user, MySQL-AB JDBC Driver" 
DEBUG [DataNucleus.Datastore.Native] - INSERT INTO `COURSE` (...,`COURSEID`) VALUES (...,<1111>) 
DEBUG [DataNucleus.Datastore.Persist] - Execution Time = 1 ms (number of rows = 1) 
DEBUG [DataNucleus.Datastore.Retrieve] - Closing PreparedStatement [email protected]b5 

DEBUG [DataNucleus.Datastore.Persist] - The requested statement "INSERT INTO `STUDYPATH` (...) VALUES (...)" has been made batchable 
DEBUG [DataNucleus.Datastore.Persist] - Batch has been added to statement "INSERT INTO `STUDYPATH` (...) VALUES (...)" for processing (batch size = 1) 
DEBUG [DataNucleus.Datastore.Persist] - Adding statement "INSERT INTO `STUDYPATH` (...) VALUES (...)" to the current batch (new batch size = 2) 
DEBUG [DataNucleus.Datastore.Persist] - Batch has been added to statement "INSERT INTO `STUDYPATH` (...) VALUES (...)" for processing (batch size = 2) 
DEBUG [DataNucleus.Datastore.Native] - BATCH [INSERT INTO `STUDYPATH` (...,`STUDYPATHID`) VALUES (...,<12345>); INSERT INTO `STUDYPATH` (...,`STUDYPATHID`) VALUES (<54321>)] 
ERROR [DataNucleus.Datastore] - Exception thrown 
+0

ログを1つ読み取ることができません。これは、オブジェクトの状態と、あなたがpersistを呼び出すときに何が起こっているかを示します。私は個人的にそれを見て、永続性のプロセスを理解しています – DataNucleus

+0

あなたのコメントをありがとう、私は出力で自分の質問を更新しました。問題はバッチ更新であり、Studypathが既に存在するために発生してはならない – tilo

+0

ログの大部分(Lifecycleなど)を省略したため、何かが起きているのを見ない(一部のSQLの最終結果を除く) – DataNucleus

答えて

1

は、私はそれが一過1に切り離さJDOを関連付けるためにユダヤだかわかりません。 ORMが既存のJDOであることを知るための簡単な方法はありません。それを関連付ける前に

c.addStudypath(dbStudypath); 

そうでなければ私は考えてmakePersistent(detachedStudypath)(あなたのクラスをと仮定すると@Detachableです)

+0

それが分離されていることを知る簡単な方法があります。それが私たちがバイトコードを強化しているからです.-) – DataNucleus

1

それは同じコードパスで本当になら、私は永続的なインスタンスを関連付けたいですJDOHelper.getObjectState(obj)を呼び出すことで、オブジェクトの状態を簡単にチェックすることができます。私はあなたのオブジェクトがTRANSIENT状態でDETACHED状態ではないことを強くお勧めします。あなたのクラスを着脱可能と宣言していない可能性が高いからです。