Search code examples
javajdo

Jdo error duplicate key


i have 2 classes A, B.

This is class Main:

public class Main
{ 
    static PersistenceManagerFactory pmf ;

    static Transaction tx1 ;
    static PersistenceManager pm1 ;

    public Main(){

       pmf = JDOHelper.getPersistenceManagerFactory("datanucleus.properties");

    }

    public static void testB(B b){

        pm1 = pmf.getPersistenceManager();
        tx1=pm1.currentTransaction();

        try {
            tx1.begin();


            B bb=b;

            pm1.makePersistent(bb);


            tx1.commit();

         } finally {
             if (tx1.isActive())
             {
                 tx1.rollback();
             }
             pm1.close();
         }
    }

    public static void main(String args[]) {

        Main n=new Main();

        String id="4";


        A a=new A(id,"prova");

        B b2=new B("4a",a);
        B b3=new B("5a",a);  //// error HERE ////////////////////////////////

        Main.testB(b2);
        Main.testB(b3);
    }
}

When I run the Main class I get an error, namely:

Exception in thread "main" javax.jdo.JDODataStoreException: Insert of object "B@95973d" using statement "INSERT INTO `B` (`ID`,`IDR`) VALUES (?,?)" failed : Duplicate entry '4' for key 'PRIMARY'
at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:421)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:735)
at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:755)
at Main.testB(Main.java:167)
at Main.main(Main.java:322)

As I understand it, in the Main class, specifically in this line of code:

    A a=new A(id,"prova");

    B b2=new B("4a",a);
    B b3=new B("5a",a);  //// error HERE ////////////////////////////////

    Main.testB(b2);
    Main.testB(b3);

I get the error "Duplicate entry '4 'for key' PRIMARY '"

In Table B, I want to insert multiple values ​​for a PK of table A, how can I fix it?


Solution

  • So the "A" object is in "transient" state when you persist the B, hence it will try to persist a new A each time. If instead you persist the A and then detach it (pm.detachCopy, when the object is marked as detachable) and set the A field of the B to that, it will work. Any JDO docs has references to detaching and object states. Create the A like this

    pm.currentTransaction().begin();
    A a = new A(id,"prova");
    a = pm.makePersistent(a);
    A detachedA = pm.detachCopy(a);
    pm.currentTransaction().commit();
    

    then use "detachedA" with the persist of the B's.