/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * 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.ogm.datastore.mongodb.test.options.readpreference; import static org.fest.assertions.Assertions.assertThat; import static org.hibernate.ogm.datastore.mongodb.utils.MockMongoClientBuilder.mockClient; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.ogm.OgmSessionFactory; import org.hibernate.ogm.cfg.OgmProperties; import org.hibernate.ogm.datastore.document.cfg.DocumentStoreProperties; import org.hibernate.ogm.datastore.document.options.AssociationStorageType; import org.hibernate.ogm.datastore.mongodb.impl.MongoDBDatastoreProvider; import org.hibernate.ogm.datastore.mongodb.utils.MockMongoClientBuilder.MockMongoClient; import org.hibernate.ogm.utils.TestHelper; import org.junit.After; import org.junit.Test; import com.mongodb.ReadPreference; import org.bson.Document; /** * Tests that the configured read preference is applied when performing operations against MongoDB. * * @author Gunnar Morling */ public class ReadPreferencePropagationTest { private OgmSessionFactory sessions; @After public void closeSessionFactory() { sessions.close(); } @Test public void shouldApplyConfiguredReadPreferenceForGettingTuple() { // given an empty database MockMongoClient mockClient = mockClient().build(); setupSessionFactory( new MongoDBDatastoreProvider( mockClient.getClient() ) ); final Session session = sessions.openSession(); Transaction transaction = session.beginTransaction(); // when getting a golf player session.get( GolfPlayer.class, 1L ); transaction.commit(); session.close(); // then expect a findOne() call with the configured read preference verify( mockClient.getCollection( "GolfPlayer" ).withReadPreference( ReadPreference.secondaryPreferred() ) ).find( any( Document.class ) ); } @Test public void shouldApplyConfiguredReadPreferenceForGettingEmbeddedAssociation() { // given a persisted player with one associated golf course Document player = getPlayer(); player.put( "playedCourses", getPlayedCoursesAssociationEmbedded() ); MockMongoClient mockClient = mockClient() .insert( "GolfPlayer", player ) .insert( "GolfCourse", getGolfCourse() ) .build(); setupSessionFactory( new MongoDBDatastoreProvider( mockClient.getClient() ) ); Session session = sessions.openSession(); Transaction transaction = session.beginTransaction(); // when getting the golf player GolfPlayer ben = (GolfPlayer) session.get( GolfPlayer.class, 1L ); List<GolfCourse> playedCourses = ben.getPlayedCourses(); assertThat( playedCourses ).onProperty( "id" ).containsExactly( 1L ); transaction.commit(); session.close(); // then expect a findOne() call for the entity and the embedded association with the configured read preference verify( mockClient.getCollection( "GolfPlayer" ).withReadPreference( ReadPreference.secondaryPreferred() ) ).find( any( Document.class ) ); } @Test public void shouldApplyConfiguredReadPreferenceForGettingAssociationStoredAsAssociation() { // given a persisted player with one associated golf course MockMongoClient mockClient = mockClient() .insert( "GolfPlayer", getPlayer() ) .insert( "GolfCourse", getGolfCourse() ) .insert( "Associations", getPlayedCoursesAssociationAsDocument() ) .build(); setupSessionFactory( new MongoDBDatastoreProvider( mockClient.getClient() ), AssociationStorageType.ASSOCIATION_DOCUMENT ); Session session = sessions.openSession(); Transaction transaction = session.beginTransaction(); // when getting the golf player GolfPlayer ben = (GolfPlayer) session.get( GolfPlayer.class, 1L ); List<GolfCourse> playedCourses = ben.getPlayedCourses(); assertThat( playedCourses ).onProperty( "id" ).containsExactly( 1L ); transaction.commit(); session.close(); // then expect a findOne() call for the entity and one for the association with the configured read preference verify( mockClient.getCollection( "GolfPlayer" ).withReadPreference( ReadPreference.secondaryPreferred() ) ).find( any( Document.class ) ) ; verify( mockClient.getCollection( "Associations" ).withReadPreference( ReadPreference.primaryPreferred() ) ).find( any( Document.class ) ) ; verify( mockClient.getCollection( "GolfPlayer" ).withReadPreference( ReadPreference.secondaryPreferred() ).find( any( Document.class ) ).projection( any( Document.class ) ) ).first() ; verifyNoMoreInteractions( mockClient.getCollection( "GolfPlayer" ).withReadPreference( ReadPreference.secondaryPreferred() ).find( any( Document.class ) ).projection( any( Document.class ) ) ); } private Class<?>[] getAnnotatedClasses() { return new Class<?>[] { GolfPlayer.class, GolfCourse.class }; } private void setupSessionFactory(MongoDBDatastoreProvider provider) { setupSessionFactory( provider, null ); } private void setupSessionFactory(MongoDBDatastoreProvider provider, AssociationStorageType associationStorage) { Map<String, Object> settings = new HashMap<>(); settings.put( OgmProperties.DATASTORE_PROVIDER, provider ); if ( associationStorage != null ) { settings.put( DocumentStoreProperties.ASSOCIATIONS_STORE, associationStorage ); } sessions = TestHelper.getDefaultTestSessionFactory( settings, getAnnotatedClasses() ); } private Document getGolfCourse() { Document bepplePeach = new Document(); bepplePeach.put( "_id", 1L ); bepplePeach.put( "name", "Bepple Peach" ); return bepplePeach; } private Document getPlayer() { Document golfPlayer = new Document(); golfPlayer.put( "_id", 1L ); golfPlayer.put( "name", "Ben" ); golfPlayer.put( "handicap", 0.1 ); return golfPlayer; } private List<Document> getPlayedCoursesAssociationEmbedded() { Document bepplePeachRef = new Document(); bepplePeachRef.put( "playedCourses_id", 1L ); List<Document> playedCourses = new ArrayList<>(); playedCourses.add( bepplePeachRef ); return playedCourses; } private Document getPlayedCoursesAssociationAsDocument() { Document id = new Document(); id.put( "golfPlayer_id", 1L ); id.put( "table", "GolfPlayer_GolfCourse" ); Document row = new Document(); row.put( "playedCourses_id", 1L ); List<Document> rows = new ArrayList<>(); rows.add( row ); Document association = new Document(); association.put( "_id", id ); association.put( "rows", rows ); return association; } }