2nd level collection cache has not been invalidated after hql delete queries
Description
Activity
Show:

balram patel May 4, 2022 at 9:55 AM
Its failing after this change https://hibernate.atlassian.net/browse/HHH-13792

balram patel May 4, 2022 at 9:30 AM
Test is passing in 5.4.10 and failing since 5.4.11.
When we delete oneToMany collections with hql and then remove with hibernate session it fails with below error.
Consider one to may relations for X → Y.
package org.hibernate.test.cache.test; import java.util.ArrayList; import java.util.List; import javax.persistence.Cacheable; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "X") @Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class X { private Long id; private List<Y> y = new ArrayList<>(); public X() { } @Id @GeneratedValue(generator = "increment") @GenericGenerator(name = "increment", strategy = "increment") public Long getId() { return id; } public void setId(Long id) { this.id = id; } @OneToMany(mappedBy = "x", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public List<Y> getY() { return y; } public void setY(List<Y> y) { this.y = y; } }
package org.hibernate.test.cache.test; import javax.persistence.Cacheable; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "Y") @Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Y { private static final long serialVersionUID = 3876303350505676207L; private Long id; private String operation; private X x; public Y() { } @Column public String getOperation() { return operation; } public void setOperation(String operation) { this.operation = operation; } @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.MERGE }) @JoinColumn(name = "x") public X getX() { return x; } public void setX(X x) { this.x = x; } @Id @GeneratedValue(generator = "increment") @GenericGenerator(name = "increment", strategy = "increment") public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
Below test fails with same error in 5.4.18 hibernate version. If I remove 2nd level collections cache for Y in X.java then same test passes.
package org.hibernate.test.cache.test; import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.List; import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.query.Query; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; public class RemoveSecondLevelCachedCollectionsWithHqlTest extends BaseCoreFunctionalTestCase { @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] { X.class, Y.class }; } @Override protected void configure(Configuration cfg) { cfg.setProperty(Environment.AUTO_EVICT_COLLECTION_CACHE, "true"); cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); cfg.setProperty(Environment.CACHE_PROVIDER_CONFIG, "true"); } @Test public void testRemove() { // create Y y = new Y(); y.setOperation("delete"); X x = new X(); ArrayList<Y> yList = new ArrayList<>(); yList.add(y); x.setY(yList); y.setX(x); // save Session s = openSession(); s.beginTransaction(); s.save(x); s.getTransaction().commit(); s.close(); // verify s = openSession(); s.beginTransaction(); X verifyX = s.get(X.class, 1L); assertEquals(1, verifyX.getY().size()); s.getTransaction().commit(); s.close(); // delete with hql s = openSession(); s.beginTransaction(); X x2 = s.get(X.class, 1L); Query query = s.createQuery("delete Y relation where relation.x.id=:xid"); query.setParameter("xid", x2.getId()); query.executeUpdate(); s.clear(); s.remove(s.get(X.class, 1L)); s.getTransaction().commit(); s.close(); } }