/* * 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.jcache.functional; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import org.hibernate.Session; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.H2Dialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * @author Zhenlei Huang */ @TestForIssue(jiraKey = "HHH-10649") public class RefreshUpdatedDataTest extends BaseNonConfigCoreFunctionalTestCase { @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] { ReadWriteCacheableItem.class, ReadWriteVersionedCacheableItem.class, NonStrictReadWriteCacheableItem.class, NonStrictReadWriteVersionedCacheableItem.class, }; } @Override @SuppressWarnings("unchecked") protected void addSettings(Map settings) { super.addSettings( settings ); if ( H2Dialect.class.equals( Dialect.getDialect().getClass() ) ) { settings.put( Environment.URL, "jdbc:h2:mem:db-mvcc;MVCC=true" ); } settings.put( AvailableSettings.GENERATE_STATISTICS, "true" ); } @Override protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { super.configureStandardServiceRegistryBuilder( ssrb ); ssrb.configure( "hibernate-config/hibernate.cfg.xml" ); } @Test public void testUpdateAndFlushThenRefresh() { // prepare data Session s = openSession(); s.beginTransaction(); final String BEFORE = "before"; ReadWriteCacheableItem readWriteCacheableItem = new ReadWriteCacheableItem( BEFORE ); readWriteCacheableItem.getTags().add( "Hibernate" ); readWriteCacheableItem.getTags().add( "ORM" ); s.persist( readWriteCacheableItem ); ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem = new ReadWriteVersionedCacheableItem( BEFORE ); readWriteVersionedCacheableItem.getTags().add( "Hibernate" ); readWriteVersionedCacheableItem.getTags().add( "ORM" ); s.persist( readWriteVersionedCacheableItem ); NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem = new NonStrictReadWriteCacheableItem( BEFORE ); nonStrictReadWriteCacheableItem.getTags().add( "Hibernate" ); nonStrictReadWriteCacheableItem.getTags().add( "ORM" ); s.persist( nonStrictReadWriteCacheableItem ); NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem = new NonStrictReadWriteVersionedCacheableItem( BEFORE ); nonStrictReadWriteVersionedCacheableItem.getTags().add( "Hibernate" ); nonStrictReadWriteVersionedCacheableItem.getTags().add( "ORM" ); s.persist( nonStrictReadWriteVersionedCacheableItem ); s.getTransaction().commit(); s.close(); Session s1 = openSession(); s1.beginTransaction(); final String AFTER = "after"; ReadWriteCacheableItem readWriteCacheableItem1 = s1.get( ReadWriteCacheableItem.class, readWriteCacheableItem.getId() ); readWriteCacheableItem1.setName( AFTER ); readWriteCacheableItem1.getTags().remove("ORM"); ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem1 = s1.get( ReadWriteVersionedCacheableItem.class, readWriteVersionedCacheableItem.getId() ); readWriteVersionedCacheableItem1.setName( AFTER ); readWriteVersionedCacheableItem1.getTags().remove("ORM"); NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem1 = s1.get( NonStrictReadWriteCacheableItem.class, nonStrictReadWriteCacheableItem.getId() ); nonStrictReadWriteCacheableItem1.setName( AFTER ); nonStrictReadWriteCacheableItem1.getTags().remove("ORM"); NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem1 = s1.get( NonStrictReadWriteVersionedCacheableItem.class, nonStrictReadWriteVersionedCacheableItem.getId() ); nonStrictReadWriteVersionedCacheableItem1.setName( AFTER ); nonStrictReadWriteVersionedCacheableItem1.getTags().remove("ORM"); s1.flush(); s1.refresh( readWriteCacheableItem1 ); s1.refresh( readWriteVersionedCacheableItem1 ); s1.refresh( nonStrictReadWriteCacheableItem1 ); s1.refresh( nonStrictReadWriteVersionedCacheableItem1 ); assertEquals( AFTER, readWriteCacheableItem1.getName() ); assertEquals( 1, readWriteCacheableItem1.getTags().size() ); assertEquals( AFTER, readWriteVersionedCacheableItem1.getName() ); assertEquals( 1, readWriteVersionedCacheableItem1.getTags().size() ); assertEquals( AFTER, nonStrictReadWriteCacheableItem1.getName() ); assertEquals( 1, nonStrictReadWriteCacheableItem1.getTags().size() ); assertEquals( AFTER, nonStrictReadWriteVersionedCacheableItem1.getName() ); assertEquals( 1, nonStrictReadWriteVersionedCacheableItem1.getTags().size() ); // open another session Session s2 = sessionFactory().openSession(); try { s2.beginTransaction(); ReadWriteCacheableItem readWriteCacheableItem2 = s2.get( ReadWriteCacheableItem.class, readWriteCacheableItem.getId() ); ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem2 = s2.get( ReadWriteVersionedCacheableItem.class, readWriteVersionedCacheableItem.getId() ); NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem2 = s2.get( NonStrictReadWriteCacheableItem.class, nonStrictReadWriteCacheableItem.getId() ); NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem2 = s2.get( NonStrictReadWriteVersionedCacheableItem.class, nonStrictReadWriteVersionedCacheableItem.getId() ); assertEquals( BEFORE, readWriteCacheableItem2.getName() ); assertEquals( 2, readWriteCacheableItem2.getTags().size() ); assertEquals( BEFORE, readWriteVersionedCacheableItem2.getName() ); assertEquals( 2, readWriteVersionedCacheableItem2.getTags().size() ); //READ_UNCOMMITTED because there is no locking to prevent collections from being cached in the first Session assertEquals( BEFORE, nonStrictReadWriteCacheableItem2.getName() ); assertEquals( 1, nonStrictReadWriteCacheableItem2.getTags().size()); assertEquals( BEFORE, nonStrictReadWriteVersionedCacheableItem2.getName() ); assertEquals( 1, nonStrictReadWriteVersionedCacheableItem2.getTags().size() ); s2.getTransaction().commit(); } finally { if ( s2.getTransaction().getStatus().canRollback() ) { s2.getTransaction().rollback(); } s2.close(); } s1.getTransaction().rollback(); s1.close(); s = openSession(); s.beginTransaction(); s.delete( readWriteCacheableItem ); s.delete( readWriteVersionedCacheableItem ); s.delete( nonStrictReadWriteCacheableItem ); s.delete( nonStrictReadWriteVersionedCacheableItem ); s.getTransaction().commit(); s.close(); } @Entity(name = "ReadWriteCacheableItem") @Table(name = "RW_ITEM") @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "item") public static class ReadWriteCacheableItem { @Id @GeneratedValue private Long id; private String name; @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @ElementCollection private List<String> tags = new ArrayList<>(); public ReadWriteCacheableItem() { } public ReadWriteCacheableItem(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getTags() { return tags; } } @Entity(name = "ReadWriteVersionedCacheableItem") @Table(name = "RW_VERSIONED_ITEM") @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "item") public static class ReadWriteVersionedCacheableItem { @Id @GeneratedValue private Long id; private String name; @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @ElementCollection private List<String> tags = new ArrayList<>(); @Version private int version; public ReadWriteVersionedCacheableItem() { } public ReadWriteVersionedCacheableItem(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getTags() { return tags; } } @Entity(name = "NonStrictReadWriteCacheableItem") @Table(name = "RW_NOSTRICT_ITEM") @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "item") public static class NonStrictReadWriteCacheableItem { @Id @GeneratedValue private Long id; private String name; @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) @ElementCollection private List<String> tags = new ArrayList<>(); public NonStrictReadWriteCacheableItem() { } public NonStrictReadWriteCacheableItem(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getTags() { return tags; } } @Entity(name = "NonStrictReadWriteVersionedCacheableItem") @Table(name = "RW_NOSTRICT_VER_ITEM") @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "item") public static class NonStrictReadWriteVersionedCacheableItem { @Id @GeneratedValue private Long id; private String name; @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) @ElementCollection private List<String> tags = new ArrayList<>(); @Version private int version; public NonStrictReadWriteVersionedCacheableItem() { } public NonStrictReadWriteVersionedCacheableItem(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getTags() { return tags; } } }