Package org.hibernate.test.cache.infinispan.functional

Source Code of org.hibernate.test.cache.infinispan.functional.BasicTransactionalTestCase

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.test.cache.infinispan.functional;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import org.hibernate.Criteria;
import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
import org.hibernate.criterion.Restrictions;
import org.junit.After;
import org.junit.Test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cfg.Configuration;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;

import static junit.framework.Assert.assertNotNull;
import static org.infinispan.test.TestingUtil.withTx;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
* Functional entity transactional tests.
*
* @author Galder Zamarreño
* @since 3.5
*/
public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {

  @Override
  public void configure(Configuration cfg) {
    super.configure( cfg );
  }

   @Override
   protected Class<?>[] getAnnotatedClasses() {
      return new Class[] {
            Citizen.class, State.class,
            NaturalIdOnManyToOne.class
      };
   }

   @After
   public void cleanupData() throws Exception {
      super.cleanupCache();
      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = sessionFactory().openSession();
            s.beginTransaction();
            s.createQuery( "delete NaturalIdOnManyToOne" ).executeUpdate();
            s.createQuery( "delete Citizen" ).executeUpdate();
            s.createQuery( "delete State" ).executeUpdate();
            s.getTransaction().commit();
            s.close();
            return null;
         }
      });
   }

  @Test
  public void testCollectionCache() throws Exception {
    final Statistics stats = sessionFactory().getStatistics();
    stats.clear();

    final Item item = new Item( "chris", "Chris's Item" );
    final Item another = new Item( "another", "Owned Item" );
    item.addItem( another );

      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            s.getTransaction().begin();
            s.persist( item );
            s.persist( another );
            s.getTransaction().commit();
            s.close();
            return null;
         }
      });

      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            Item loaded = (Item) s.load( Item.class, item.getId() );
            assertEquals( 1, loaded.getItems().size() );
            s.close();
            return null;
         }
      });

      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
            Item loadedWithCachedCollection = (Item) s.load( Item.class, item.getId() );
            stats.logSummary();
            assertEquals( item.getName(), loadedWithCachedCollection.getName() );
            assertEquals( item.getItems().size(), loadedWithCachedCollection.getItems().size() );
            assertEquals( 1, cStats.getHitCount() );
            Map cacheEntries = cStats.getEntries();
            assertEquals( 1, cacheEntries.size() );
            s.close();
            return null;
         }
      });
  }

  @Test
  public void testStaleWritesLeaveCacheConsistent() throws Exception {
    Statistics stats = sessionFactory().getStatistics();
    stats.clear();

    VersionedItem item = null;
    Transaction txn = null;
    Session s = null;

    beginTx();
    try {
      s = openSession();
      txn = s.beginTransaction();
      item = new VersionedItem();
      item.setName( "steve" );
      item.setDescription( "steve's item" );
      s.save( item );
      txn.commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }

    Long initialVersion = item.getVersion();

    // manually revert the version property
    item.setVersion( new Long( item.getVersion().longValue() - 1 ) );

    beginTx();
    try {
      s = openSession();
      txn = s.beginTransaction();
      s.update(item);
      txn.commit();
      fail("expected stale write to fail");
    }
    catch (Exception e) {
      setRollbackOnlyTxExpected(e);
    }
    finally {
      commitOrRollbackTx();
      if ( s != null && s.isOpen() ) {
        try {
          s.close();
        }
        catch (Throwable ignore) {
        }
      }
    }

    // check the version value in the cache...
    SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics( VersionedItem.class.getName() );

    Object entry = slcs.getEntries().get( item.getId() );
    Long cachedVersionValue;
    cachedVersionValue = (Long) ((CacheEntry) entry).getVersion();
    assertEquals(initialVersion.longValue(), cachedVersionValue.longValue());

    beginTx();
    try {
      // cleanup
      s = openSession();
      txn = s.beginTransaction();
      item = (VersionedItem) s.load( VersionedItem.class, item.getId() );
      s.delete( item );
      txn.commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }
  }

  @Test
  public void testQueryCacheInvalidation() throws Exception {
    Statistics stats = sessionFactory().getStatistics();
    stats.clear();

    SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics( Item.class.getName() );
    sessionFactory().getCache().evictEntityRegion( Item.class.getName() );

    assertEquals(0, slcs.getPutCount());
    assertEquals( 0, slcs.getElementCountInMemory() );
    assertEquals( 0, slcs.getEntries().size() );

    Session s = null;
    Transaction t = null;
    Item i = null;

    beginTx();
    try {
      s = openSession();
      t = s.beginTransaction();
      i = new Item();
      i.setName( "widget" );
      i.setDescription( "A really top-quality, full-featured widget." );
      s.persist( i );
      t.commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }


    assertEquals( 1, slcs.getPutCount() );
    assertEquals( 1, slcs.getElementCountInMemory() );
    assertEquals( 1, slcs.getEntries().size() );

    beginTx();
    try {
      s = openSession();
      t = s.beginTransaction();
      i = (Item) s.get( Item.class, i.getId() );
      assertEquals( slcs.getHitCount(), 1 );
      assertEquals( slcs.getMissCount(), 0 );
      i.setDescription( "A bog standard item" );
      t.commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }

    assertEquals( slcs.getPutCount(), 2 );

    CacheEntry entry = (CacheEntry) slcs.getEntries().get( i.getId() );
    Serializable[] ser = entry.getDisassembledState();
    assertTrue( ser[0].equals( "widget" ) );
    assertTrue( ser[1].equals( "A bog standard item" ) );

    beginTx();
    try {
      // cleanup
      s = openSession();
      t = s.beginTransaction();
      s.delete(i);
      t.commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }
  }

  @Test
  public void testQueryCache() throws Exception {
    Statistics stats = sessionFactory().getStatistics();
    stats.clear();

    Session s;
    Item item = new Item( "chris", "Chris's Item" );

    beginTx();
    try {
      s = openSession();
      s.getTransaction().begin();
      s.persist( item );
      s.getTransaction().commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }

    // Delay added to guarantee that query cache results won't be considered
    // as not up to date due to persist session and query results from first
    // query happening within same 100ms gap.
    Thread.sleep( 100 );

    beginTx();
    try {
      s = openSession();
      s.createQuery( "from Item" ).setCacheable( true ).list();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }

    beginTx();
    try {
      s = openSession();
      s.createQuery( "from Item" ).setCacheable( true ).list();
      assertEquals( 1, stats.getQueryCacheHitCount() );
      s.createQuery( "delete from Item" ).executeUpdate();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }
  }

  @Test
  public void testQueryCacheHitInSameTransaction() throws Exception {
    Statistics stats = sessionFactory().getStatistics();
    stats.clear();

    Session s = null;
    Item item = new Item( "galder", "Galder's Item" );

    beginTx();
    try {
      s = openSession();
      s.getTransaction().begin();
      s.persist( item );
      s.getTransaction().commit();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }

    // Delay added to guarantee that query cache results won't be considered
    // as not up to date due to persist session and query results from first
    // query happening within same 100ms gap.
    Thread.sleep( 100 );

    beginTx();
    try {
      s = openSession();
      s.createQuery( "from Item" ).setCacheable( true ).list();
      s.createQuery( "from Item" ).setCacheable( true ).list();
      assertEquals( 1, stats.getQueryCacheHitCount() );
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }

    beginTx();
    try {
      s = openSession();
      s.createQuery( "delete from Item" ).executeUpdate();
      s.close();
    }
    catch (Exception e) {
      setRollbackOnlyTx( e );
    }
    finally {
      commitOrRollbackTx();
    }
  }

   @Test
   public void testNaturalIdCached() throws Exception {
      saveSomeCitizens();

      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            Transaction tx = s.beginTransaction();
            State france = BasicTransactionalTestCase.this.getState(s, "Ile de France");
            Criteria criteria = s.createCriteria( Citizen.class );
            criteria.add( Restrictions.naturalId().set( "ssn", "1234" ).set( "state", france ) );
            criteria.setCacheable( true );

            BasicTransactionalTestCase.this.cleanupCache();

            Statistics stats = sessionFactory().getStatistics();
            stats.setStatisticsEnabled( true );
            stats.clear();
            assertEquals(
                  "Cache hits should be empty", 0, stats
                  .getNaturalIdCacheHitCount()
            );

            // first query
            List results = criteria.list();
            assertEquals( 1, results.size() );
            assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
            assertEquals( "NaturalId Cache Misses", 1, stats.getNaturalIdCacheMissCount() );
            assertEquals( "NaturalId Cache Puts", 1, stats.getNaturalIdCachePutCount() );
            assertEquals( "NaturalId Cache Queries", 1, stats.getNaturalIdQueryExecutionCount() );

            // query a second time - result should be cached in session
            criteria.list();
            assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
            assertEquals( "NaturalId Cache Misses", 1, stats.getNaturalIdCacheMissCount() );
            assertEquals( "NaturalId Cache Puts", 1, stats.getNaturalIdCachePutCount() );
            assertEquals( "NaturalId Cache Queries", 1, stats.getNaturalIdQueryExecutionCount() );

            // cleanup
            tx.rollback();
            s.close();
            return null;
         }
      });
   }

   @Test
   public void testNaturalIdLoaderCached() throws Exception {
      final Statistics stats = sessionFactory().getStatistics();
      stats.setStatisticsEnabled( true );
      stats.clear();

      assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
      assertEquals( "NaturalId Cache Misses", 0, stats.getNaturalIdCacheMissCount() );
      assertEquals( "NaturalId Cache Puts", 0, stats.getNaturalIdCachePutCount() );
      assertEquals( "NaturalId Cache Queries", 0, stats.getNaturalIdQueryExecutionCount() );

      saveSomeCitizens();

      assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
      assertEquals( "NaturalId Cache Misses", 0, stats.getNaturalIdCacheMissCount() );
      assertEquals( "NaturalId Cache Puts", 2, stats.getNaturalIdCachePutCount() );
      assertEquals( "NaturalId Cache Queries", 0, stats.getNaturalIdQueryExecutionCount() );

      //Try NaturalIdLoadAccess after insert
      final Citizen citizen = withTx(tm, new Callable<Citizen>() {
         @Override
         public Citizen call() throws Exception {
            Session s = openSession();
            Transaction tx = s.beginTransaction();
            State france = BasicTransactionalTestCase.this.getState(s, "Ile de France");
            NaturalIdLoadAccess naturalIdLoader = s.byNaturalId(Citizen.class);
            naturalIdLoader.using("ssn", "1234").using("state", france);

            //Not clearing naturalId caches, should be warm from entity loading
            stats.clear();

            // first query
            Citizen citizen = (Citizen) naturalIdLoader.load();
            assertNotNull(citizen);
            assertEquals("NaturalId Cache Hits", 1, stats.getNaturalIdCacheHitCount());
            assertEquals("NaturalId Cache Misses", 0, stats.getNaturalIdCacheMissCount());
            assertEquals("NaturalId Cache Puts", 0, stats.getNaturalIdCachePutCount());
            assertEquals("NaturalId Cache Queries", 0, stats.getNaturalIdQueryExecutionCount());

            // cleanup
            tx.rollback();
            s.close();
            return citizen;
         }
      });

      // TODO: Clear caches manually via cache manager (it's faster!!)
      this.cleanupCache();
      Thread.sleep(PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD + TimeUnit.SECONDS.toMillis(1));
      stats.setStatisticsEnabled( true );
      stats.clear();

      //Try NaturalIdLoadAccess
      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            Transaction tx = s.beginTransaction();

            // first query
            Citizen loadedCitizen = (Citizen) s.get( Citizen.class, citizen.getId() );
            assertNotNull( loadedCitizen );
            assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
            assertEquals( "NaturalId Cache Misses", 0, stats.getNaturalIdCacheMissCount() );
            assertEquals( "NaturalId Cache Puts", 1, stats.getNaturalIdCachePutCount() );
            assertEquals( "NaturalId Cache Queries", 0, stats.getNaturalIdQueryExecutionCount() );

            // cleanup
            tx.rollback();
            s.close();
            return null;
         }
      });

      // Try NaturalIdLoadAccess after load
      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            Transaction tx = s.beginTransaction();
            State france = BasicTransactionalTestCase.this.getState(s, "Ile de France");
            NaturalIdLoadAccess naturalIdLoader = s.byNaturalId(Citizen.class);
            naturalIdLoader.using( "ssn", "1234" ).using( "state", france );

            //Not clearing naturalId caches, should be warm from entity loading
            stats.setStatisticsEnabled( true );
            stats.clear();

            // first query
            Citizen loadedCitizen = (Citizen) naturalIdLoader.load();
            assertNotNull( loadedCitizen );
            assertEquals( "NaturalId Cache Hits", 1, stats.getNaturalIdCacheHitCount() );
            assertEquals( "NaturalId Cache Misses", 0, stats.getNaturalIdCacheMissCount() );
            assertEquals( "NaturalId Cache Puts", 0, stats.getNaturalIdCachePutCount() );
            assertEquals( "NaturalId Cache Queries", 0, stats.getNaturalIdQueryExecutionCount() );

            // cleanup
            tx.rollback();
            s.close();
            return null;
         }
      });

   }

   private void saveSomeCitizens() throws Exception {
      final Citizen c1 = new Citizen();
      c1.setFirstname( "Emmanuel" );
      c1.setLastname( "Bernard" );
      c1.setSsn( "1234" );

      final State france = new State();
      france.setName( "Ile de France" );
      c1.setState( france );

      final Citizen c2 = new Citizen();
      c2.setFirstname( "Gavin" );
      c2.setLastname( "King" );
      c2.setSsn( "000" );
      final State australia = new State();
      australia.setName( "Australia" );
      c2.setState( australia );

      withTx(tm, new Callable<Void>() {
         @Override
         public Void call() throws Exception {
            Session s = openSession();
            Transaction tx = s.beginTransaction();
            s.persist( australia );
            s.persist( france );
            s.persist( c1 );
            s.persist( c2 );
            tx.commit();
            s.close();
            return null;
         }
      });
   }

   private State getState(Session s, String name) {
      Criteria criteria = s.createCriteria( State.class );
      criteria.add( Restrictions.eq("name", name) );
      criteria.setCacheable(true);
      return (State) criteria.list().get( 0 );
   }

}
TOP

Related Classes of org.hibernate.test.cache.infinispan.functional.BasicTransactionalTestCase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.