Bug #51914 ClusterJPA deletes causing exception
Submitted: 10 Mar 2010 13:53 Modified: 28 Jun 2017 20:59
Reporter: Andrew Morgan Email Updates:
Status: Won't fix Impact on me:
None 
Category:MySQL Cluster: Cluster/J Severity:S3 (Non-critical)
Version:mysql-5.1-telco-7.1 OS:Linux (Fedora 12)
Assigned to: Bogdan Kecman CPU Architecture:Any
Tags: MySQL Cluster 7.1.1
Triage: Triaged: D3 (Medium) / R6 (Needs Assessment) / E6 (Needs Assessment)

[10 Mar 2010 13:53] Andrew Morgan
Description:
I have a test application using OpenJPA with ClusterJ; everything is working as expected until I try to clean up by deleting all of the rows that have been created.

When I run this code, I get the following exception:

userTransaction.begin();
    Query delEmp = em.createQuery("DELETE FROM Employee e");
    int deleted = delEmp.executeUpdate();
    System.out.println(deleted + " Employees deleted.");
userTransaction.commit();

101 Employees deleted.
Exception in thread "main" <openjpa-1.2.1-r752877:753278 fatal store error> org.apache.openjpa.persistence.RollbackException: Commit failed: com.mysql.clusterj.ClusterJDatastoreException: Error in NdbJTie: returnCode -1, code 626, mysqlCode 120, status 2, classification 2, message Tuple did not exist .
        at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:523)
        at Main.main(Main.java:140)
Caused by: <openjpa-1.2.1-r752877:753278 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Commit failed: com.mysql.clusterj.ClusterJDatastoreException: Error in NdbJTie: returnCode -1, code 626, mysqlCode 120, status 2, classification 2, message Tuple did not exist .
        at org.apache.openjpa.kernel.BrokerImpl.afterCompletion(BrokerImpl.java:1870)
        at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:94)
        at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1350)
        at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:877)
        at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:512)
        ... 1 more
Caused by: com.mysql.clusterj.ClusterJException: Commit failed: com.mysql.clusterj.ClusterJDatastoreException: Error in NdbJTie: returnCode -1, code 626, mysqlCode 120, status 2, classification 2, message Tuple did not exist .
        at com.mysql.clusterj.openjpa.NdbOpenJPAStoreManager.commit(NdbOpenJPAStoreManager.java:397)
        at org.apache.openjpa.kernel.DelegatingStoreManager.commit(DelegatingStoreManager.java:94)
        at org.apache.openjpa.kernel.BrokerImpl.endStoreManagerTransaction(BrokerImpl.java:1308)
        at org.apache.openjpa.kernel.BrokerImpl.endTransaction(BrokerImpl.java:2177)
        at org.apache.openjpa.kernel.BrokerImpl.afterCompletion(BrokerImpl.java:1846)
        ... 5 more

How to repeat:
Run this code:

/*

javac -classpath /usr/local/mysql/share/mysql/java/*.jar:/usr/local/openjpa/openjpa-1.2.1.jar:/usr/local/openjpa/lib/geronimo-jpa_3.0_spec-1.0.jar:. Main.java Employee.java Department.java

java -Djava.library.path=/usr/local/mysql/lib -classpath /usr/local/mysql/share/mysql/java/*:/usr/local/mysql/share/java/*:/usr/local/openjpa/openjpa-1.2.1.jar:/usr/local/openjpa/lib/*:/usr/local/connectorj/mysql-connector-java-5.1.12-bin.jar:. Main

mysql> create database clusterdb;
mysql> alter table clusterdb.employee engine=ndb;
mysql> alter table clusterdb.department engine=ndb;
mysql> describe clusterdb.employee;
+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id           | int(11)      | NO   | PRI | NULL    |       |
| municipality | varchar(255) | YES  |     | NULL    |       |
| department   | int(11)      | YES  |     | NULL    |       |
| ended        | varchar(255) | YES  |     | NULL    |       |
| first        | varchar(255) | YES  |     | NULL    |       |
| last         | varchar(255) | YES  |     | NULL    |       |
| started      | varchar(255) | YES  |     | NULL    |       |
| dept         | int(11)      | YES  |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

mysql> describe department;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id       | int(11)      | NO   | PRI | NULL    |       |
| location | varchar(255) | YES  |     | NULL    |       |
+----------+--------------+------+-----+---------+-------+

*/

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import java.io.*;

public class Main {
	
  public static void main (String[] args) throws java.io.IOException {
      
    EntityManagerFactory entityManagerFactory =  Persistence.createEntityManagerFactory("clusterdb");
    EntityManager em = entityManagerFactory.createEntityManager();
    EntityTransaction userTransaction = em.getTransaction();
    
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
    
    System.out.println("Check engine used for clusterdb.employee & change to ndb if needed.");
    System.out.println("mysql> alter table clusterdb.employee engine=ndb;");
    System.out.println("mysql> alter table clusterdb.department engine=ndb;");
    System.out.println("Hit return when you are done");
    String ignore = br.readLine();
    
    userTransaction.begin();
    
    Employee emp = new Employee();
    emp.setId(1);
    emp.setDepartment(666);
    emp.setFirst("Billy");
    emp.setLast("Fish");
    emp.setStarted("1st February 2009");
	
    em.persist(emp);
    
    userTransaction.commit();

    userTransaction.begin();
    
    Employee theEmployee = em.find(Employee.class, 1);
    
    userTransaction.commit();

    System.out.println(theEmployee.toString());
    
    System.out.println("Chance to check the database before City is set");
    System.out.println("Hit return when you are done");
    ignore = br.readLine();
    
    userTransaction.begin();
    
    theEmployee.setCity("London");
    theEmployee.setDepartment(777);
    
    userTransaction.commit();
    
    System.out.println("Chance to check the City is set in the database");
    System.out.println("Hit return when you are done");
    ignore = br.readLine();

    Department dept;
    
    userTransaction.begin();
 
    for (int i=700;i<800;i++) {
	emp = new Employee();
	dept = new Department();
	emp.setId(i+1000);
	emp.setDepartment(i);
	emp.setFirst("Billy");
	emp.setLast("No-Mates-"+i);
	emp.setStarted("1st February 2009");
	em.persist(emp);
	dept.setId(i);
	dept.setSite("Building-"+i);
	em.persist(dept);
    }
   
    userTransaction.commit();
    

    userTransaction.begin();
	
    Query q = em.createQuery("select x from Employee x where x.department=777");
    Query qd;    

    for (Employee m : (List<Employee>) q.getResultList()) {
	System.out.println(m.toString());
	qd = em.createQuery("select x from Department x where x.id=777");
	for (Department d : (List<Department>) qd.getResultList()) {
	    System.out.println(d.toString());
	}
    }
    userTransaction.commit();
    
    System.out.println("Last chance to check the database before all entries are deleted.");
    System.out.println("Hit return when you are done");
    ignore = br.readLine();

    userTransaction.begin();
    Query delEmp = em.createQuery("DELETE FROM Employee e");
    int deleted = delEmp.executeUpdate();
    System.out.println(deleted + " Employees deleted.");
    userTransaction.commit();
    /*
    userTransaction.begin();
    Query delDept = em.createQuery("DELETE FROM Department d");
    deleted = delDept.executeUpdate();
    System.out.println(deleted + " Departments deleted.");
    userTransaction.commit();
    */

    em.close();
    entityManagerFactory.close();	
  }
}

import javax.persistence.*;

@Entity(name = "department") //Name of the table

public class Department {
   
    private int Id;
    private String Site;

    public Department(){}

    @Id public int getId() {return Id;}
    public void setId(int id) {Id=id;}
 
    @Column(name="location")    
    public String getSite() {return Site;}
    public void setSite(String site) {Site=site;}

    public String toString() {
   	return "Department: " + getId() + " based in " + getSite();
    }
}

import javax.persistence.*;

@Entity(name = "employee") //Name of the table

public class Employee {
   
    private int Id;
    private String First;
    private String Last;
    private String City;
    private String Started;  
    private String Ended;  
    private int Department;

    public Employee(){}

    @Id public int getId() {return Id;}
    public void setId(int id) {Id=id;}
 
    public String getFirst() {return First;}
    public void setFirst(String first) {First=first;}

    public String getLast() {return Last;}
    public void setLast(String last) {Last=last;}
    
    @Column(name="municipality")    
    public String getCity() {return City;}
    public void setCity(String city) {City=city;}
    
    public String getStarted() {return Started;}
    public void setStarted(String date) {Started=date;}
    
    public String getEnded() {return Ended;}
    public void setEnded(String date) {Ended=date;}

    public int getDepartment() {return Department;}
    public void setDepartment(int department) {Department=department;}

    public String toString() {
   	return getFirst() + " " + getLast() + " (Dept " + getDepartment()+ ") from " + getCity() 
          + " started on " + getStarted() + " & left on " + getEnded();
    }
}
[10 Mar 2010 13:54] Andrew Morgan
persistence.xml

Attachment: persistence.xml (text/xml), 1010 bytes.

[10 Mar 2010 13:54] Andrew Morgan
Department.java

Attachment: Department.java (application/octet-stream, text), 493 bytes.

[10 Mar 2010 13:55] Andrew Morgan
Employee.java

Attachment: Employee.java (application/octet-stream, text), 1.24 KiB.

[10 Mar 2010 13:55] Andrew Morgan
Main.java

Attachment: Main.java (application/octet-stream, text), 5.09 KiB.

[10 Mar 2010 16:10] Craig Russell
Great bug report.

This is probably an interaction between the different transactions used by the JDBC part and the clusterj part. I've got a fix that I'll check in shortly and see if that fixes this issue.