I seem to have found a race condition that overwrites rows in the join table in a @ManyToMany relationship. Here's a simplified example:
class Employee { @Id @Column( name = "EMPLOYEE_ID" ) private long id;
@Column( name = "NAME" ) private String name;
@ManyToMany( mappedBy = "employees", cascade = CascadeType.ALL ) private List< Employer > employers = new ArrayList< Employer >(); }
class Employer { @Id @Column( name = "EMPLOYER_ID" ) private long id;
@ManyToMany @JoinTable( name = "JOIN_TABLE", joinColumns = { @JoinColumn( name = "EMPLOYEE_ID" ) }, inverseJoinColumns = { @JoinColumn( name = "EMPLOYER_ID" ) } ) private List< Employee > employees = new ArrayList< Employee >(); }
My code looks something like:
Employee john = new Employee(); john.setName( "John" ); Employer employer = employerDao.findEmployer( employerName ); john.getEmployers().add( employer ); employer.getEmployees().add( john ); employeeDao.persist( john );
While running single-threaded, everything works perfectly. However, when running multi-threaded, the entries in the JOIN_TABLE are not consistently persisted. For instance, say I am trying persist employee "John" and employee "Jane", both linked to the same employer, in two different threads with two different transactions. Occasionally, after both threads commit, the JOIN_TABLE only includes a mapping from "Jane" to the employer, and "John" is nowhere to be seen. No exceptions are thrown.
I noticed that if I change the order of the mappings by making the Employee the "parent" association, it always works as expected.
Has anyone seen this error before? Is it a bug, or am I doing something wrong?
I'm using Hibernate Annotations 3.4.0.GA, Hibernate Core 3.3.2.GA, and Hibernate Entity Manager 3.4.0.GA. Spring 2.5.5 and Bitronix 1.3.3 are also in use.
Thanks, Dan Nawrocki
|