Zombie Entities? Constraint violation when modifying removed Entity [message #1818530] |
Wed, 18 December 2019 20:03  |
Uwe Pachler Messages: 1 Registered: December 2019 |
Junior Member |
|
|
Hi all,
I'm encountering quite a weird issue with code that modifies an entity after it was removed (EntityManager.remove()) - and I know the suggested fix will be 'don't do it', but unfortunately things are not that simple, so that's not really a solution for me.
But first things fist, this is what I'm doing:
* I have entityies Employee and Company. A company can have many employees (bidirectional one-to-many). The employee MUST have a company (NOT NULL constraint). In my test code, the tables are generated by EclipseLink, so it itself thinks generating that NOT NULL constraint is the correct thing to do.
* I create a company and an employee, and associate them (both sides updated correctly)
* (0) I persist them and flush them to the database
* (1) I remove the employee (so it is REMOVED)
* (2) then I set company to NULL on the employee (IMHO this shouldn't do anything, but in fact later triggers an UPDATE, which causes trouble) (2)
* (3) Calling em.flush() at the end causes the changes to be written to the database. However, before the Eclipselink tries to DELETE our employe, it performs an UPDATE on it, attempting to set company_id to NULL - which breaks the test, since company_id is NOT NULL constrained.
Now I know changing removed entities may not be the smartest thing to do, however, there are reasons why this may happen anyways (which I think are beyond scope for now).
I'm wondering if I'm doing something even more stupid than modifying the entity after removing it, or if this is an EclipseLink feature, or worse, a bug...
Cheers,
Uwe
P.S.: Tested with EclipseLink 2.7.5.
---- TEST CODE ----
// NOTE: we inherit 'EntityManager em' from outside the test code
@Test
public void test() {
// I create a company with one employee and associate them...
Employee e = Employee.builder()
.firstname("John")
.surname("Doe")
.build();
Company c = Company.builder()
.name("Acme")
.build();
e.setCompany(c);
c.getEmployee().add(e);
em.persist(e);
em.persist(c);
// (0) make sure objects are in the database
em.flush();
// (1) I remove (DELETE) the employee
em.remove(e);
// (2) I change the association on the removed entity
e.setCompany(null);
// (3) The call to flush fails, complaining about a failed
// NOT NULL contstraint
em.flush();
}
---- OUTPUT ----
javax.persistence.PersistenceException:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.1.v20171221-bd47e8f): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10099 table: EMPLOYEE column: COMPANY_ID
Error Code: -10
Call: UPDATE EMPLOYEE SET COMPANY_ID = ? WHERE (ID = ?)
bind => [null, 1]
Query: UpdateObjectQuery(com.github.gentity.test.test1a_many_to_one.Employee@7ae0a9ec)
at com.github.gentity.test.Test1a_many_to_one.test(Test1a_many_to_one.java:59)
Caused by: org.eclipse.persistence.exceptions.DatabaseException:
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10099 table: EMPLOYEE column: COMPANY_ID
Error Code: -10
Call: UPDATE EMPLOYEE SET COMPANY_ID = ? WHERE (ID = ?)
bind => [null, 1]
Query: UpdateObjectQuery(com.github.gentity.test.test1a_many_to_one.Employee@7ae0a9ec)
at com.github.gentity.test.Test1a_many_to_one.test(Test1a_many_to_one.java:59)
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10099 table: EMPLOYEE column: COMPANY_ID
at com.github.gentity.test.Test1a_many_to_one.test(Test1a_many_to_one.java:59)
Caused by: org.hsqldb.HsqlException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10099 table: EMPLOYEE column: COMPANY_ID
at com.github.gentity.test.Test1a_many_to_one.test(Test1a_many_to_one.java:59)
---- ENTITIES ----
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
protected Long id;
@Column(name = "FIRSTNAME", length = 100)
protected String firstname;
@Column(name = "SURNAME", length = 100)
protected String surname;
@ManyToOne
@JoinColumn(name = "COMPANY_ID", nullable = false)
protected Company company;
//... methods omitted
}
@Entity
@Table(name = "COMPANY")
public class Company implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
protected Long id;
@Column(name = "NAME", length = 100, nullable = false)
protected String name;
@OneToMany(mappedBy = "company")
protected List<Employee> employee = new ArrayList();
//... methods omitted
}
|
|
|
|
Powered by
FUDForum. Page generated in 0.02141 seconds