/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.cache; import org.hibernate.ObjectNotFoundException; import org.hibernate.Session; import org.hibernate.cache.internal.CollectionCacheInvalidator; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; /** * @author Andreas Berger */ @TestForIssue(jiraKey = "HHH-4910") public class CollectionCacheEvictionTest extends BaseCoreFunctionalTestCase { @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] { User.class, Company.class }; } @Before public void before() { CollectionCacheInvalidator.PROPAGATE_EXCEPTION = true; } @After public void after() { CollectionCacheInvalidator.PROPAGATE_EXCEPTION = false; } @Override protected void configure(Configuration cfg) { super.configure( 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" ); } @Override protected void prepareTest() throws Exception { Session s = openSession(); s.beginTransaction(); Company company1 = new Company( 1 ); s.save( company1 ); User user = new User( 1, company1 ); s.save( user ); Company company2 = new Company( 2 ); s.save( company2 ); s.getTransaction().commit(); s.close(); } @Override protected void cleanupTest() throws Exception { Session s = openSession(); s.beginTransaction(); s.createQuery( "delete from org.hibernate.test.cache.User" ).executeUpdate(); s.createQuery( "delete from org.hibernate.test.cache.Company" ).executeUpdate(); s.getTransaction().commit(); s.close(); } @Test public void testCachedValueAfterEviction() { CollectionPersister persister = sessionFactory().getCollectionPersister( Company.class.getName() + ".users" ); Session session = openSession(); SessionImplementor sessionImplementor = (SessionImplementor) session; CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy(); Object key = cache.generateCacheKey( 1, persister, sessionFactory(), session.getTenantIdentifier() ); Object cachedValue = cache.get( sessionImplementor, key, sessionImplementor.getTimestamp() ); assertNull( cachedValue ); Company company = session.get( Company.class, 1 ); //should add in cache assertEquals( 1, company.getUsers().size() ); session.close(); session = openSession(); sessionImplementor = (SessionImplementor) session; key = cache.generateCacheKey( 1, persister, sessionFactory(), session.getTenantIdentifier() ); cachedValue = cache.get( sessionImplementor, key, sessionImplementor.getTimestamp() ); assertNotNull( "Collection wasn't cached", cachedValue ); session.close(); } @Test public void testCollectionCacheEvictionInsert() { Session s = openSession(); s.beginTransaction(); Company company = (Company) s.get( Company.class, 1 ); // init cache of collection assertEquals( 1, company.getUsers().size() ); User user = new User( 2, company ); s.save( user ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); company = (Company) s.get( Company.class, 1 ); // fails if cache is not evicted assertEquals( 2, company.getUsers().size() ); s.close(); } @Test public void testCollectionCacheEvictionInsertWithEntityOutOfContext() { Session s = openSession(); Company company = s.get( Company.class, 1 ); assertEquals( 1, company.getUsers().size() ); s.close(); s = openSession(); s.beginTransaction(); User user = new User( 2, company ); s.save( user ); s.getTransaction().commit(); s.close(); s = openSession(); company = s.get( Company.class, 1 ); assertEquals( 2, company.getUsers().size() ); s.close(); } @Test public void testCollectionCacheEvictionRemove() { Session s = openSession(); s.beginTransaction(); Company company = (Company) s.get( Company.class, 1 ); // init cache of collection assertEquals( 1, company.getUsers().size() ); s.delete( company.getUsers().get( 0 ) ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); company = (Company) s.get( Company.class, 1 ); // fails if cache is not evicted try { assertEquals( 0, company.getUsers().size() ); } catch ( ObjectNotFoundException e ) { fail( "Cached element not found" ); } s.close(); } @Test public void testCollectionCacheEvictionRemoveWithEntityOutOfContext() { Session s = openSession(); Company company = s.get( Company.class, 1 ); assertEquals( 1, company.getUsers().size() ); s.close(); s = openSession(); s.beginTransaction(); s.delete( company.getUsers().get( 0 ) ); s.getTransaction().commit(); s.close(); s = openSession(); company = s.get( Company.class, 1 ); try { assertEquals( 0, company.getUsers().size() ); } catch ( ObjectNotFoundException e ) { fail( "Cached element not found" ); } s.close(); } @Test public void testCollectionCacheEvictionUpdate() { Session s = openSession(); s.beginTransaction(); Company company1 = (Company) s.get( Company.class, 1 ); Company company2 = (Company) s.get( Company.class, 2 ); // init cache of collection assertEquals( 1, company1.getUsers().size() ); assertEquals( 0, company2.getUsers().size() ); User user = (User) s.get( User.class, 1 ); user.setCompany( company2 ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); company1 = (Company) s.get( Company.class, 1 ); company2 = (Company) s.get( Company.class, 2 ); assertEquals( 1, company2.getUsers().size() ); // fails if cache is not evicted try { assertEquals( 0, company1.getUsers().size() ); } catch ( ObjectNotFoundException e ) { fail( "Cached element not found" ); } s.close(); } @Test @TestForIssue(jiraKey = "HHH-10631") public void testCollectionCacheEvictionUpdateWhenChildIsSetToNull() { Session s = openSession(); s.beginTransaction(); Company company1 = (Company) s.get( Company.class, 1 ); Company company2 = (Company) s.get( Company.class, 2 ); // init cache of collection assertEquals( 1, company1.getUsers().size() ); assertEquals( 0, company2.getUsers().size() ); User user = (User) s.get( User.class, 1 ); user.setCompany( null ); s.getTransaction().commit(); s.close(); s = openSession(); company1 = (Company) s.get( Company.class, 1 ); company2 = (Company) s.get( Company.class, 2 ); assertEquals( 0, company1.getUsers().size() ); assertEquals( 0, company2.getUsers().size() ); s.close(); } @Test public void testCollectionCacheEvictionUpdateWithEntityOutOfContext() { Session s = openSession(); Company company1 = s.get( Company.class, 1 ); Company company2 = s.get( Company.class, 2 ); assertEquals( 1, company1.getUsers().size() ); assertEquals( 0, company2.getUsers().size() ); s.close(); s = openSession(); s.beginTransaction(); User user = s.get( User.class, 1 ); user.setCompany( company2 ); s.getTransaction().commit(); s.close(); s = openSession(); company1 = s.get( Company.class, 1 ); company2 = s.get( Company.class, 2 ); assertEquals( 1, company2.getUsers().size() ); try { assertEquals( 0, company1.getUsers().size() ); } catch ( ObjectNotFoundException e ) { fail( "Cached element not found" ); } s.close(); } @Test public void testUpdateWithNullRelation() { Session session = openSession(); session.beginTransaction(); User user = new User(); user.setName( "User1" ); session.persist( user ); session.getTransaction().commit(); session.close(); session = openSession(); session.beginTransaction(); user.setName( "UserUpdate" ); session.merge( user ); session.getTransaction().commit(); session.close(); } }