"Attempt to lock a non entity object" error

#1

Probably a simple answer for someone who's been using ObjectDB for awhile:

I'm reading objects from the database outside a transaction (inside doesn't seem to matter).

First cycle of doEdit and then doCancelEdit works fine.

Second time I doEdit produces the error "Attempt to lock a non entity object"

session.rollback() is somehow causing the problem (found through debugging)

Is this enough information for someone to suggest what might be happening and how to fix it?

public void doEdit() {
try {
    session.beginTransaction();
    session.lock(subjectJList.getSelectedValue(),
      LockModeType.PESSIMISTIC_WRITE);
.
.
} //doEdit
//-----------------------------------------------------------
public void doCancelEdit() {
try {
    session.rollback();
.
.
.
} //doCancelEdit
-------------------------------------------------------------
Attempt to lock a non entity object

 

#2

Error was caused - from the ObjectDB manual - by:

"The following operations clear the entire persistence context and detach all managed entity objects:

... Rolling back a transaction - either by invocation of rollback or by a commit failure."

Quite different behavior from what I expected and would prefer. 

#3

It is correct. All the entity objects are detached on rollback.

This is how it should work in JPA and it is different from JDO.

A new build (2.4.7_15) enables now using JDO behavior on rollback with JPA.

To keep the entity objects managed with their current changes:

    PersistenceManager pm = em.unwrap(PersistenceManager.class);
    pm.currentTransaction().setRestoreValues(false);

To keep the entity objects managed but restore their content (discarding changes if any):

    PersistenceManager pm = em.unwrap(PersistenceManager.class);
    pm.currentTransaction().setRestoreValues(true);

The first option may be more efficient.

You need to call setRetainValues once per EntityManager.

ObjectDB Support
#4

I've downloaded the new build and tried the code above that uses a JDO Transaction with beginTransaction(), lock(), and rollback() on the same JDO Transaction, and then beginTransaction(), lock(), and rollback() on a JPA EntityTransaction and I'm still getting the same error. Am I missing something that would be obvious to someone else?

#5

Please follow the posting instructions and provide a minimal test case that demonstrates the problem.

ObjectDB Support
#6
[ObjectDB 2.4.7_15 Enhancer]
1 persistable type has been enhanced:
    Person

[ObjectDB 2.4.7_15 Enhancer]
1 persistable type has been enhanced:
    Test

Stored: Ron
After find and first lock: Ron
Exception in thread "main" [ObjectDB 2.4.7_15] java.lang.IllegalArgumentException
Attempt to lock a non entity object (error 635)
at com.objectdb.jpa.EMImpl.lock(EMImpl.java:783)
at com.objectdb.jpa.EMImpl.lock(EMImpl.java:753)
at Test.main(Test.java:34)
at Enhance.main(Enhance.java:7)
import javax.persistence.Entity;
//----------------
@Entity
    class Person {
        String name;
        //----------------
        public Person(String name) {
            this.name = name;
        } //Person
        //----------------
        public void setName(String name) {
            this.name = name;
        } //setName
    //----------------
} //Person

import javax.jdo.PersistenceManager;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.LockModeType;
import javax.persistence.Persistence;

//----------------
@Entity
public class Test {
//----------------
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(
          "objectdb:D:\\eclipse\\workspace\\TestProject\\Storage.odb");
        EntityManager em = emf.createEntityManager();
        Person p = new Person("Ron");
        em.getTransaction().begin();
        em.persist(p);
        em.getTransaction().commit();
        System.out.println("Stored: " + p.name);
        emf.close();
        //-------
        emf = Persistence.createEntityManagerFactory(
          "objectdb:D:\\eclipse\\workspace\\TestProject\\Storage.odb");
        em = emf.createEntityManager();
        PersistenceManager pm = em.unwrap(PersistenceManager.class);
        pm.currentTransaction().setRetainValues(true);
        em.getTransaction().begin();
        p = em.find(Person.class, 1);
        em.lock(p, LockModeType.PESSIMISTIC_WRITE);
        System.out.println("After find and first lock: " + p.name);
        em.getTransaction().rollback();
        em.getTransaction().begin();
        // next line throws IllegalArgumentException
        em.lock(p, LockModeType.PESSIMISTIC_WRITE);
        System.out.println("After second lock before update: " + p.name);
        p.setName("Jim");
        System.out.println("After update before second rollback: " + p.name);
        em.getTransaction().rollback();
        System.out.println("After second rollback: " + p.name);
        emf.close();
    } //main
//----------------
} //Test
#7

You are right. Unfortunately in #3 above setRestoreValues was replaced with setRetainValues (it is fixed now).

Sorry for the error.  After switching to setRestoreValues your test works.

ObjectDB Support
#8

(You overlooked the needed change to the last line of #3 above:

"You need to call setRetainValues once per EntityManager.")

Yup, my application also works with the fix.

The new behavior and your quick fix are greatly appreciated.

Reply