2012-03-08 101 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

缺少閱讀日誌的人。這會告訴你對象狀態,以及當你調用persist時發生了什麼。我個人會看它,並理解持久性的過程 – DataNucleus 2012-03-09 07:32:11

+0

感謝您的評論,我剛剛更新了我的問題與輸出。問題是批量更新,因爲研究路徑已經存在而不應該發生 – tilo 2012-03-09 08:56:32

+0

您省略了大部分日誌(例如生命週期),因此看不到發生了什麼(除了某些SQL的最終結果) – DataNucleus 2012-03-09 10:05:43

回答

1

我不知道這是猶太以一種超然的JDO關聯到一個短暫的一個。 ORM沒有簡單的方法知道關係是一個現有的JDO。

如果它真的在同一個代碼路徑,我會持久實例相關聯:

c.addStudypath(dbStudypath); 

否則我會makePersistent這個(detachedStudypath)關聯之前(假設你的類是@Detachable)

+0

有一個簡單的方法可以知道它是分離的...因爲這就是爲什麼我們字節碼增強它們;-) – DataNucleus 2012-03-09 10:00:15

1

您可以通過調用JDOHelper.getObjectState(obj)輕鬆檢查對象的狀態。我強烈建議你,你的對象處於TRANSIENT狀態而不是DETACHED狀態,可能是因爲你還沒有宣佈你的課程是可拆卸的。