/* * 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 java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Version; import org.hibernate.Session; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.dialect.H2Dialect; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * @author Zhenlei Huang */ @TestForIssue(jiraKey = "HHH-10649") @RequiresDialect(value = {H2Dialect.class}) public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase { @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] { ReadWriteCacheableItem.class, ReadWriteVersionedCacheableItem.class, NonStrictReadWriteCacheableItem.class, NonStrictReadWriteVersionedCacheableItem.class, }; } @Override protected void configure(Configuration cfg) { super.configure( cfg ); Properties properties = Environment.getProperties(); if ( H2Dialect.class.getName().equals( properties.get( Environment.DIALECT ) ) ) { cfg.setProperty( Environment.URL, "jdbc:h2:mem:db-mvcc;MVCC=true" ); } cfg.setProperty( Environment.CACHE_REGION_PREFIX, "" ); cfg.setProperty( Environment.GENERATE_STATISTICS, "true" ); cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" ); cfg.setProperty( Environment.CACHE_PROVIDER_CONFIG, "true" ); } @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") @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") @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") @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") @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; } } }