HHH-9231 HHH-5690 : Test cases for transactional cache strategy

This commit is contained in:
Gail Badner 2014-06-04 13:45:04 -07:00
parent dad4c64d56
commit af5791f6dd
3 changed files with 357 additions and 3 deletions

View File

@ -32,10 +32,12 @@ import java.util.concurrent.TimeUnit;
import org.hibernate.Cache; import org.hibernate.Cache;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.NaturalIdLoadAccess; import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.cache.infinispan.access.PutFromLoadValidator; import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import org.junit.After; import org.junit.After;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.hibernate.Session; import org.hibernate.Session;
@ -44,6 +46,7 @@ import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.stat.SecondLevelCacheStatistics; import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics; import org.hibernate.stat.Statistics;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
@ -141,6 +144,254 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
}); });
} }
@Test
@TestForIssue( jiraKey = "HHH-9231")
public void testAddNewOneToManyElementInitFlushLeaveCacheConsistent() throws Exception {
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
Item item = null;
Transaction txn = null;
Session s = null;
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = new Item();
item.setName( "steve" );
item.setDescription( "steve's item" );
s.save( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
// create an element for item.itsms
Item itemElement = new Item();
itemElement.setName( "element" );
itemElement.setDescription( "element item" );
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
assertFalse( Hibernate.isInitialized( item.getItems() ) );
// Add an element to item.items (a Set); it will initialize the Set.
item.addItem( itemElement );
assertTrue( Hibernate.isInitialized( item.getItems() ) );
s.persist( itemElement );
s.flush();
setRollbackOnlyTx();
}
catch (Exception e) {
setRollbackOnlyTxExpected(e);
}
finally {
commitOrRollbackTx();
if ( s != null && s.isOpen() ) {
try {
s.close();
}
catch (Throwable ignore) {
}
}
}
beginTx();
try {
// cleanup
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
Hibernate.initialize( item.getItems() );
assertTrue( item.getItems().isEmpty() );
s.delete( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
}
@Test
@TestForIssue( jiraKey = "HHH-9231")
public void testAddNewOneToManyElementNoInitFlushLeaveCacheConsistent() throws Exception {
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
Item item = null;
Transaction txn = null;
Session s = null;
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = new Item();
item.setName( "steve" );
item.setDescription( "steve's item" );
s.save( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
// create an element for item.bagOfItems
Item itemElement = new Item();
itemElement.setName( "element" );
itemElement.setDescription( "element item" );
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
assertFalse( Hibernate.isInitialized( item.getItems() ) );
// Add an element to item.bagOfItems (a bag); it will not initialize the bag.
item.addItemToBag( itemElement );
assertFalse( Hibernate.isInitialized( item.getBagOfItems() ) );
s.persist( itemElement );
s.flush();
setRollbackOnlyTx();
}
catch (Exception e) {
setRollbackOnlyTxExpected(e);
}
finally {
commitOrRollbackTx();
if ( s != null && s.isOpen() ) {
try {
s.close();
}
catch (Throwable ignore) {
}
}
}
beginTx();
try {
// cleanup
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
Hibernate.initialize( item.getItems() );
assertTrue( item.getItems().isEmpty() );
s.delete( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
}
@Test
@FailureExpected( jiraKey = "HHH-9231")
public void testAddNewOneToManyElementNoInitFlushInitLeaveCacheConsistent() throws Exception {
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
Item item = null;
Transaction txn = null;
Session s = null;
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = new Item();
item.setName( "steve" );
item.setDescription( "steve's item" );
s.save( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
// create an element for item.bagOfItems
Item itemElement = new Item();
itemElement.setName( "element" );
itemElement.setDescription( "element item" );
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
assertFalse( Hibernate.isInitialized( item.getBagOfItems() ) );
// Add an element to item.bagOfItems (a bag); it will not initialize the bag.
item.addItemToBag( itemElement );
assertFalse( Hibernate.isInitialized( item.getBagOfItems() ) );
s.persist( itemElement );
s.flush();
// Now initialize the collection; it will contain the uncommitted itemElement.
Hibernate.initialize( item.getBagOfItems() );
setRollbackOnlyTx();
}
catch (Exception e) {
setRollbackOnlyTxExpected(e);
}
finally {
commitOrRollbackTx();
if ( s != null && s.isOpen() ) {
try {
s.close();
}
catch (Throwable ignore) {
}
}
}
beginTx();
try {
// cleanup
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
// Because of HHH-9231, the following will fail due to ObjectNotFoundException because the
// collection will be read from the cache and it still contains the uncommitted element,
// which cannot be found.
Hibernate.initialize( item.getBagOfItems() );
assertTrue( item.getBagOfItems().isEmpty() );
s.delete( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
}
@Test @Test
public void testStaleWritesLeaveCacheConsistent() throws Exception { public void testStaleWritesLeaveCacheConsistent() throws Exception {
Statistics stats = sessionFactory().getStatistics(); Statistics stats = sessionFactory().getStatistics();
@ -227,6 +478,8 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
Statistics stats = sessionFactory().getStatistics(); Statistics stats = sessionFactory().getStatistics();
stats.clear(); stats.clear();
SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics( Item.class.getName() );
Item item = null; Item item = null;
Transaction txn = null; Transaction txn = null;
Session s = null; Session s = null;
@ -240,6 +493,7 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
item.setDescription( "steve's item" ); item.setDescription( "steve's item" );
s.persist( item ); s.persist( item );
s.flush(); s.flush();
assertNotNull( slcs.getEntries().get( item.getId() ) );
setRollbackOnlyTx(); setRollbackOnlyTx();
} }
catch (Exception e) { catch (Exception e) {
@ -247,11 +501,81 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
} }
finally { finally {
commitOrRollbackTx(); commitOrRollbackTx();
if ( s != null && s.isOpen() ) {
try {
s.close(); s.close();
} }
catch (Throwable ignore) {
}
}
}
// item should not be in entity cache. // item should not be in entity cache.
assertTrue( slcs.getEntries().isEmpty() );
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = (Item) s.get( Item.class, item.getId() );
assertNull( item );
txn.commit();
s.close();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
}
}
@Test
@TestForIssue( jiraKey = "HHH-5690")
public void testPersistEntityFlushEvictGetRollbackNotInEntityCache() throws Exception {
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics( Item.class.getName() ); SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics( Item.class.getName() );
Item item = null;
Transaction txn = null;
Session s = null;
beginTx();
try {
s = openSession();
txn = s.beginTransaction();
item = new Item();
item.setName( "steve" );
item.setDescription( "steve's item" );
s.persist( item );
s.flush();
// item is cached on insert.
assertNotNull( slcs.getEntries().get( item.getId() ) );
s.evict( item );
assertEquals( slcs.getHitCount(), 0 );
item = (Item) s.get( Item.class, item.getId() );
assertNotNull( item );
assertEquals( slcs.getHitCount(), 1 );
assertNotNull( slcs.getEntries().get( item.getId() ) );
setRollbackOnlyTx();
}
catch (Exception e) {
setRollbackOnlyTx( e );
}
finally {
commitOrRollbackTx();
if ( s != null && s.isOpen() ) {
try {
s.close();
}
catch (Throwable ignore) {
}
}
}
// item should not be in entity cache.
//slcs = stats.getSecondLevelCacheStatistics( Item.class.getName() );
assertTrue( slcs.getEntries().isEmpty() ); assertTrue( slcs.getEntries().isEmpty() );
beginTx(); beginTx();

View File

@ -22,7 +22,9 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cache.infinispan.functional; package org.hibernate.test.cache.infinispan.functional;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
@ -34,6 +36,8 @@ public class Item {
private String description; private String description;
private Item owner; private Item owner;
private Set<Item> items = new HashSet<Item>( ); private Set<Item> items = new HashSet<Item>( );
private Item bagOwner;
private List<Item> bagOfItems = new ArrayList<Item>( );
public Item() {} public Item() {}
@ -86,4 +90,25 @@ public class Item {
item.setOwner( this ); item.setOwner( this );
getItems().add( item ); getItems().add( item );
} }
public Item getBagOwner() {
return bagOwner;
}
public void setBagOwner( Item bagOwner ) {
this.bagOwner = bagOwner;
}
public List<Item> getBagOfItems() {
return bagOfItems;
}
public void setBagOfItems( List<Item> bagOfItems ) {
this.bagOfItems = bagOfItems;
}
public void addItemToBag( Item item ) {
item.setBagOwner( this );
getBagOfItems().add( item );
}
} }

View File

@ -31,10 +31,15 @@
<property name="name" not-null="true" /> <property name="name" not-null="true" />
<property name="description" not-null="true" /> <property name="description" not-null="true" />
<many-to-one name="owner" column="owner_id" class="Item" /> <many-to-one name="owner" column="owner_id" class="Item" />
<many-to-one name="bagOwner" column="bagowner_id" class="Item" />
<set name="items" inverse="true"> <set name="items" inverse="true">
<key column="owner_id" /> <key column="owner_id" />
<one-to-many class="Item" /> <one-to-many class="Item" />
</set> </set>
<bag name="bagOfItems" inverse="true">
<key column="bagowner_id" />
<one-to-many class="Item" />
</bag>
</class> </class>
<class name="VersionedItem" table="VersionedItems"> <class name="VersionedItem" table="VersionedItems">