Package org.hibernate.search.test.engine.optimizations

Source Code of org.hibernate.search.test.engine.optimizations.CollectionUpdateEventTest

/*
* Hibernate Search, full-text search for your domain model
*
* 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.search.test.engine.optimizations;

import java.lang.annotation.ElementType;

import org.hibernate.Transaction;

import org.hibernate.collection.internal.PersistentBag;
import org.hibernate.collection.internal.PersistentSet;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.cfg.EntityMapping;
import org.hibernate.search.cfg.IndexedMapping;
import org.hibernate.search.cfg.SearchMapping;
import org.hibernate.search.test.util.FullTextSessionBuilder;
import org.hibernate.search.testsupport.TestForIssue;
import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
* Verify that updates to collections that are not indexed do not trigger indexing.
* Updating a collection in an entity which is not indexed, but has some other property marked
* as containedIn, should generally not trigger indexing of the containedIn objects, unless
* we can't tell for sure the index state is not going to be affected.
*
* @author Sanne Grinovero
* @author Tom Waterhouse
*/
@TestForIssue(jiraKey = "HSEARCH-679")
public class CollectionUpdateEventTest {

  private static boolean WITH_CLASS_BRIDGE_ON_ITEM = true;
  private static boolean WITHOUT_CLASS_BRIDGE_ON_ITEM = false;

  private static boolean WITH_CLASS_BRIDGE_ON_CATALOG = true;
  private static boolean WITHOUT_CLASS_BRIDGE_ON_CATALOG = false;

  /**
   * If the top level class has a class bridge or dynamic boost, then we can't safely
   * enable this optimization.
   */
  @Test
  public void testWithClassBridge() {
    testScenario( WITH_CLASS_BRIDGE_ON_ITEM, 2, WITHOUT_CLASS_BRIDGE_ON_CATALOG );
  }

  /**
   * The indexing should be skipped when no custom bridges are used.
   */
  @Test
  public void testWithoutClassBridge() {
    testScenario( WITHOUT_CLASS_BRIDGE_ON_ITEM, 2, WITHOUT_CLASS_BRIDGE_ON_CATALOG );
  }

  /**
   * Test having a depth which is not enough to reach the dirty collection.
   * We should be able to optimize this case.
   */
  @Test
  public void testWithNoEnoughDepth() {
    testScenario( WITH_CLASS_BRIDGE_ON_ITEM, 1, WITHOUT_CLASS_BRIDGE_ON_CATALOG );
  }

  /**
   * Test again with a no-enough-depth scenario, but having the class bridge
   * defined close to the collection (far from the root entity)
   */
  @Test
  public void testWithDeepClassBridge() {
    testScenario( WITHOUT_CLASS_BRIDGE_ON_ITEM, 1, WITH_CLASS_BRIDGE_ON_CATALOG );
  }

  private void testScenario(boolean withClassBridgeOnItem, int depth, boolean withClassBridgeOnCatalog) {
    FullTextSessionBuilder fulltextSessionBuilder = configure(
        withClassBridgeOnItem,
        depth,
        withClassBridgeOnCatalog
    );
    try {
      initializeData( fulltextSessionBuilder );
      FullTextSession fullTextSession = fulltextSessionBuilder.openFullTextSession();
      try {
        Catalog catalog = (Catalog) fullTextSession.get( Catalog.class, 1L );
        PersistentSet catalogItems = (PersistentSet) catalog.getCatalogItems();
        PersistentBag consumers = (PersistentBag) catalog.getConsumers();

        assertFalse( "consumers should not be initialized", consumers.wasInitialized() );
        assertFalse( "catalogItems should not be initialized", consumers.wasInitialized() );

        updateCatalogsCollection( fullTextSession, catalog );

        if ( ( withClassBridgeOnItem || withClassBridgeOnCatalog ) && depth > 1 ) {
          assertTrue( "catalogItems should have been initialized", catalogItems.wasInitialized() );
        }
        else {
          assertFalse( "catalogItems should not be initialized", catalogItems.wasInitialized() );
        }
      }
      finally {
        fullTextSession.close();
      }
    }
    finally {
      fulltextSessionBuilder.close();
    }
  }

  private FullTextSessionBuilder configure(boolean withClassBridgeOnItem, int depth, boolean withClassBridgeOnCatalog) {
    FullTextSessionBuilder builder = new FullTextSessionBuilder()
        .addAnnotatedClass( Catalog.class )
        .addAnnotatedClass( CatalogItem.class )
        .addAnnotatedClass( Consumer.class )
        .addAnnotatedClass( Item.class );
    SearchMapping fluentMapping = builder.fluentMapping();
    // mapping for Catalog
    EntityMapping catalogMapping = fluentMapping
        .entity( Catalog.class );
    if ( withClassBridgeOnCatalog ) {
      catalogMapping.classBridge( NoopClassBridge.class );
    }
    catalogMapping
        .property( "catalogItems", ElementType.FIELD ).containedIn();

    // mapping for CatalogItem
    fluentMapping.entity( CatalogItem.class )
        .property( "item", ElementType.FIELD ).containedIn()
        .property( "catalog", ElementType.FIELD ).indexEmbedded();

    // mapping for Item
    IndexedMapping itemMapping = fluentMapping
        .entity( Item.class )
        .indexed();
    if ( withClassBridgeOnItem ) {
      itemMapping.classBridge( NoopClassBridge.class );
    }
    itemMapping.property( "catalogItems", ElementType.FIELD ).indexEmbedded().depth( depth );
    return builder.build();
  }

  private void initializeData(FullTextSessionBuilder fulltextSessionBuilder) {
    FullTextSession fullTextSession = fulltextSessionBuilder.openFullTextSession();
    try {
      final Transaction transaction = fullTextSession.beginTransaction();

      Catalog catalog = new Catalog();
      catalog.setCatalogId( 1L );
      catalog.setName( "parts" );
      fullTextSession.persist( catalog );

      for ( int i = 0; i < 5; i++ ) {
        Item item = new Item();
        item.setName( "battery" );
        fullTextSession.persist( item );

        CatalogItem catalogItem = new CatalogItem();
        catalogItem.setCatalog( catalog );
        catalogItem.setItem( item );
        fullTextSession.persist( catalogItem );

        item.getCatalogItems().add( catalogItem );
        fullTextSession.merge( item );

        catalog.getCatalogItems().add( catalogItem );
        fullTextSession.merge( catalog );
      }

      transaction.commit();
    }
    finally {
      fullTextSession.close();
    }
  }

  /**
   * Update a non-indexed collection of an entity contained in a collection. No indexing work should be created.
   */
  private void updateCatalogsCollection(FullTextSession fullTextSession, Catalog catalog) {
    final Transaction transaction = fullTextSession.beginTransaction();

    Consumer consumer = new Consumer();
    consumer.setName( "consumer" );
    consumer.getCatalogs().add( catalog );
    fullTextSession.persist( consumer );

    catalog.getConsumers().add( consumer );
    fullTextSession.merge( catalog );

    transaction.commit();
  }

}
TOP

Related Classes of org.hibernate.search.test.engine.optimizations.CollectionUpdateEventTest

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.