When loading entities that have a field referencing itself (representing a parent-child-relationship), the field may be filled with wrong data if the second-level cache is used along with BatchSize. In the example below (it is also attached), an entity which does not have a parent category set is loaded with a parent category. The last assertion fails in 6.2.0.CR2 but passes in 6.1.7.Final, as it should. Entity:
@NamedQueries(
{
@NamedQuery(name = "Category.selectAll",
query = " SELECT c" +
" FROM Category c" +
" ORDER BY c.name")
})
@Entity
@BatchSize(size = 500)
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Category {
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@ManyToOne
@JoinColumn
@Fetch(value = FetchMode.SELECT)
private Category parentCategory;
}
Test:
@Test
public void hhh123Test() throws Exception {
createEntities();
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
List<Category> categories =
entityManager.createNamedQuery("Category.selectAll", Category.class).getResultList();
entityManager.getTransaction().commit();
entityManager.close();
Assert.assertNull(categories.get(0).getParentCategory());
Assert.assertEquals("A", categories.get(1).getParentCategory().getName());
Assert.assertNull(categories.get(2).getParentCategory()); }
private void createEntities() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Category categoryA = new Category();
categoryA.setName("A");
entityManager.persist(categoryA);
Category categoryB = new Category();
categoryB.setName("B");
categoryB.setParentCategory(categoryA);
entityManager.persist(categoryB);
Category categoryC = new Category();
categoryC.setName("C");
entityManager.persist(categoryC);
entityManager.getTransaction().commit();
entityManager.close();
}
|