/*
* 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.backendtck.batchfetching;
import static org.fest.assertions.Assertions.assertThat;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.ogm.OgmSession;
import org.hibernate.ogm.dialect.multiget.spi.MultigetGridDialect;
import org.hibernate.ogm.dialect.spi.TupleContext;
import org.hibernate.ogm.model.impl.DefaultEntityKeyMetadata;
import org.hibernate.ogm.model.key.spi.EntityKey;
import org.hibernate.ogm.model.key.spi.EntityKeyMetadata;
import org.hibernate.ogm.model.spi.Tuple;
import org.hibernate.ogm.utils.GridDialectOperationContexts;
import org.hibernate.ogm.utils.GridDialectType;
import org.hibernate.ogm.utils.OgmTestCase;
import org.hibernate.ogm.utils.SkipByGridDialect;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for dialects implementing the {@link MultigetGridDialect} interface when the id of the entity is mapped on a
* single column.
*
* @author Davide D'Alto
*/
@SkipByGridDialect(value = { GridDialectType.INFINISPAN })
public class MultiGetSingleColumnIdTest extends OgmTestCase {
private static final EntityKeyMetadata METADATA = new DefaultEntityKeyMetadata( "BoardGame", new String[] { "id" } );
// A key that does not exists in the datastore
private static final EntityKey NOT_IN_THE_DB = new EntityKey( METADATA, new Object[]{ -666 } );
private static final BoardGame DOMINION = new BoardGame( 1, "Dominion" );
private static final BoardGame KING_OF_TOKYO = new BoardGame( 2, "King of Tokyo" );
private static final BoardGame SPLENDOR = new BoardGame( 3, "Splendor" );
@Test
public void testGetTuplesWithoutNulls() throws Exception {
try ( OgmSession session = openSession() ) {
Transaction tx = session.beginTransaction();
try {
MultigetGridDialect dialect = multiGetGridDialect();
EntityKey[] keys = new EntityKey[] { key( SPLENDOR ), key( DOMINION ), key( KING_OF_TOKYO ) };
List<Tuple> tuples = dialect.getTuples( keys, tupleContext( session ) );
assertThat( id( tuples.get( 0 ) ) ).isEqualTo( SPLENDOR.getId() );
assertThat( name( tuples.get( 0 ) ) ).isEqualTo( SPLENDOR.getName() );
assertThat( id( tuples.get( 1 ) ) ).isEqualTo( DOMINION.getId() );
assertThat( name( tuples.get( 1 ) ) ).isEqualTo( DOMINION.getName() );
assertThat( id( tuples.get( 2 ) ) ).isEqualTo( KING_OF_TOKYO.getId() );
assertThat( name( tuples.get( 2 ) ) ).isEqualTo( KING_OF_TOKYO.getName() );
tx.commit();
}
catch (Exception e) {
rollback( tx );
throw e;
}
}
}
@Test
public void testGetTuplesWithNulls() throws Exception {
try ( OgmSession session = openSession() ) {
Transaction tx = session.beginTransaction();
try {
MultigetGridDialect dialect = multiGetGridDialect();
EntityKey[] keys = new EntityKey[] { NOT_IN_THE_DB, key( KING_OF_TOKYO ), NOT_IN_THE_DB, NOT_IN_THE_DB };
List<Tuple> tuples = dialect.getTuples( keys, tupleContext( session ) );
assertThat( tuples.get( 0 ) ).isNull();
assertThat( id( tuples.get( 1 ) ) ).isEqualTo( KING_OF_TOKYO.getId() );
assertThat( name( tuples.get( 1 ) ) ).isEqualTo( KING_OF_TOKYO.getName() );
assertThat( tuples.get( 2 ) ).isNull();
assertThat( tuples.get( 3 ) ).isNull();
tx.commit();
}
catch (Exception e) {
rollback( tx );
throw e;
}
}
}
@Test
public void testGetTuplesWithAllNulls() throws Exception {
try ( OgmSession session = openSession() ) {
Transaction tx = session.beginTransaction();
try {
MultigetGridDialect dialect = multiGetGridDialect();
EntityKey[] keys = new EntityKey[] { NOT_IN_THE_DB, NOT_IN_THE_DB, NOT_IN_THE_DB, NOT_IN_THE_DB };
List<Tuple> tuples = dialect.getTuples( keys, tupleContext( session ) );
assertThat( tuples ).containsExactly( null, null, null, null );
tx.commit();
}
catch (Exception e) {
rollback( tx );
throw e;
}
}
}
private TupleContext tupleContext(Session session) {
return new GridDialectOperationContexts.TupleContextBuilder()
.tupleTypeContext(
new GridDialectOperationContexts.TupleTypeContextBuilder()
.selectableColumns( "name", "publisher" )
.buildTupleTypeContext() )
.transactionContext( session )
.buildTupleContext();
}
private EntityKey key(BoardGame boardGame) {
Object[] values = { boardGame.getId() };
return new EntityKey( METADATA, values );
}
@Before
public void prepareDataset() {
try ( OgmSession session = openSession() ) {
Transaction tx = session.beginTransaction();
try {
session.persist( DOMINION );
session.persist( KING_OF_TOKYO );
session.persist( SPLENDOR );
tx.commit();
}
catch (Exception e) {
rollback( tx );
throw e;
}
}
}
@After
public void deleteDataset() {
try ( OgmSession session = openSession() ) {
Transaction tx = session.beginTransaction();
delete( session, DOMINION );
delete( session, SPLENDOR );
delete( session, KING_OF_TOKYO );
tx.commit();
}
}
private void delete(OgmSession session, BoardGame boardGame) {
session.delete( session.load( BoardGame.class, boardGame.getId() ) );
}
private MultigetGridDialect multiGetGridDialect() {
MultigetGridDialect gridDialect = getSessionFactory().getServiceRegistry().getService( MultigetGridDialect.class );
return gridDialect;
}
private void rollback(Transaction tx) {
if ( tx != null ) {
tx.rollback();
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{ BoardGame.class };
}
// The conversion to the right type is done later and some datastore don't keep track of the exact type.
// For example Neo4j in remote mode, will return a Long instead of an Integer.
private Integer id(Tuple tuple) {
Object object = tuple.get( "id" );
Integer integer = Integer.valueOf( String.valueOf( object ) );
return integer;
}
private String name(Tuple tuple) {
Object object = tuple.get( "name" );
return String.valueOf( object );
}
@Entity
@Table(name = "BoardGame")
@SuppressWarnings("serial")
public static class BoardGame implements Serializable {
@Id
private Integer id;
private String name;
public BoardGame() {
super();
}
public BoardGame(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
return result;
}
@Override
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
BoardGame other = (BoardGame) obj;
if ( name == null ) {
if ( other.name != null ) {
return false;
}
}
else if ( !name.equals( other.name ) ) {
return false;
}
return true;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( "BoardGame [id=" );
builder.append( id );
builder.append( ", name=" );
builder.append( name );
builder.append( "]" );
return builder.toString();
}
}
}