HHH-9231 HHH-5690 : Test cases for transactional cache strategy
This commit is contained in:
parent
dad4c64d56
commit
af5791f6dd
|
@ -32,10 +32,12 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.hibernate.Cache;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.NaturalIdLoadAccess;
|
||||
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
|
@ -44,6 +46,7 @@ import org.hibernate.cache.spi.entry.CacheEntry;
|
|||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
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
|
||||
public void testStaleWritesLeaveCacheConsistent() throws Exception {
|
||||
Statistics stats = sessionFactory().getStatistics();
|
||||
|
@ -227,6 +478,8 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
|
|||
Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics( Item.class.getName() );
|
||||
|
||||
Item item = null;
|
||||
Transaction txn = null;
|
||||
Session s = null;
|
||||
|
@ -240,6 +493,7 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
|
|||
item.setDescription( "steve's item" );
|
||||
s.persist( item );
|
||||
s.flush();
|
||||
assertNotNull( slcs.getEntries().get( item.getId() ) );
|
||||
setRollbackOnlyTx();
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -247,11 +501,81 @@ public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
|
|||
}
|
||||
finally {
|
||||
commitOrRollbackTx();
|
||||
s.close();
|
||||
if ( s != null && s.isOpen() ) {
|
||||
try {
|
||||
s.close();
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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() );
|
||||
|
||||
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() );
|
||||
|
||||
beginTx();
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.cache.infinispan.functional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -33,7 +35,9 @@ public class Item {
|
|||
private String name;
|
||||
private String description;
|
||||
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() {}
|
||||
|
||||
|
@ -81,9 +85,30 @@ public class Item {
|
|||
public void setItems( Set<Item> items ) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
|
||||
public void addItem( Item item ) {
|
||||
item.setOwner( this );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,15 @@
|
|||
<property name="name" not-null="true" />
|
||||
<property name="description" not-null="true" />
|
||||
<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">
|
||||
<key column="owner_id" />
|
||||
<one-to-many class="Item" />
|
||||
</set>
|
||||
<bag name="bagOfItems" inverse="true">
|
||||
<key column="bagowner_id" />
|
||||
<one-to-many class="Item" />
|
||||
</bag>
|
||||
</class>
|
||||
|
||||
<class name="VersionedItem" table="VersionedItems">
|
||||
|
|
Loading…
Reference in New Issue