/*
* 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.associations.manytoone;
import static org.fest.assertions.Assertions.assertThat;
import static org.hibernate.ogm.utils.GridDialectType.NEO4J_EMBEDDED;
import static org.hibernate.ogm.utils.GridDialectType.NEO4J_REMOTE;
import static org.hibernate.ogm.utils.TestHelper.get;
import static org.hibernate.ogm.utils.TestHelper.getNumberOfAssociations;
import static org.hibernate.ogm.utils.TestHelper.getNumberOfEntities;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.EnumSet;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.ogm.utils.OgmTestCase;
import org.hibernate.ogm.utils.TestForIssue;
import org.hibernate.ogm.utils.TestHelper;
import org.junit.Test;
/**
* @author Emmanuel Bernard
*/
public class ManyToOneTest extends OgmTestCase {
@Test
public void testUnidirectionalManyToOne() throws Exception {
final Session session = openSession();
Transaction transaction = session.beginTransaction();
JUG jug = new JUG( "summer_camp" );
jug.setName( "JUG Summer Camp" );
session.persist( jug );
Member emmanuel = new Member( "emmanuel" );
emmanuel.setName( "Emmanuel Bernard" );
emmanuel.setMemberOf( jug );
Member jerome = new Member( "jerome" );
jerome.setName( "Jerome" );
jerome.setMemberOf( jug );
session.persist( emmanuel );
session.persist( jerome );
session.flush();
assertThat( getNumberOfEntities( session ) ).isEqualTo( 3 );
assertThat( getNumberOfAssociations( session ) ).isEqualTo( expectedAssociations() );
transaction.commit();
assertThat( getNumberOfEntities( sessionFactory ) ).isEqualTo( 3 );
assertThat( getNumberOfAssociations( sessionFactory ) ).isEqualTo( expectedAssociations() );
session.clear();
transaction = session.beginTransaction();
emmanuel = session.get( Member.class, emmanuel.getId() );
jug = emmanuel.getMemberOf();
session.delete( emmanuel );
jerome = session.get( Member.class, jerome.getId() );
session.delete( jerome );
session.delete( jug );
transaction.commit();
assertThat( getNumberOfEntities( sessionFactory ) ).isEqualTo( 0 );
assertThat( getNumberOfAssociations( sessionFactory ) ).isEqualTo( 0 );
session.close();
checkCleanCache();
}
@Test
@TestForIssue(jiraKey = "OGM-931")
public void canPersistAssociationToDetachedEntity() throws Exception {
Session session = openSession();
Transaction transaction = session.beginTransaction();
// Persist employer
Employer employer = new Employer();
employer.setId( "employer-1" );
employer.setName( "Hibernate" );
session.save( employer );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
// Create employee and associate it with detached employer
Employee employee = new Employee();
employee.setId( "employee-1" );
employee.setName( "DNadar" );
employee.setEmployer( employer );
session.save( employee );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
// Load association from main side
Employee loadedEmployee = session.get( Employee.class, "employee-1" );
assertThat( loadedEmployee.getEmployer().getName() ).isEqualTo( "Hibernate" );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
// Load association from inverse side
Employer loadedEmployer = session.get( Employer.class, "employer-1" );
assertThat( loadedEmployer.getEmployees() ).onProperty( "name" ).containsOnly( "DNadar" );
// Clean up
session.delete( loadedEmployer.getEmployees().iterator().next() );
session.delete( loadedEmployer );
transaction.commit();
session.close();
}
private Long expectedAssociations() {
if ( EnumSet.of( NEO4J_EMBEDDED, NEO4J_REMOTE ).contains( TestHelper.getCurrentDialectType() ) ) {
// *-to-one associations are mapped with a relationship in Neo4j that will result in the count
return 2L;
}
return 0L;
}
@Test
public void testBidirectionalManyToOneRegular() throws Exception {
final Session session = openSession();
Transaction transaction = session.beginTransaction();
SalesForce force = new SalesForce( "sales_force" );
force.setCorporation( "Red Hat" );
session.save( force );
SalesGuy eric = new SalesGuy( "eric" );
eric.setName( "Eric" );
eric.setSalesForce( force );
force.getSalesGuys().add( eric );
session.save( eric );
SalesGuy simon = new SalesGuy( "simon" );
simon.setName( "Simon" );
simon.setSalesForce( force );
force.getSalesGuys().add( simon );
session.save( simon );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
force = session.get( SalesForce.class, force.getId() );
assertNotNull( force.getSalesGuys() );
assertEquals( 2, force.getSalesGuys().size() );
simon = session.get( SalesGuy.class, simon.getId() );
// purposely faulty
// force.getSalesGuys().remove( simon );
session.delete( simon );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
force = session.get( SalesForce.class, force.getId() );
assertNotNull( force.getSalesGuys() );
assertEquals( 1, force.getSalesGuys().size() );
session.delete( force.getSalesGuys().iterator().next() );
session.delete( force );
transaction.commit();
session.close();
checkCleanCache();
}
@Test
public void testBidirectionalManyToOneRemoval() throws Exception {
final Session session = openSession();
Transaction transaction = session.beginTransaction();
SalesForce force = new SalesForce( "red_hat" );
force.setCorporation( "Red Hat" );
session.save( force );
SalesGuy eric = new SalesGuy( "eric" );
eric.setName( "Eric" );
eric.setSalesForce( force );
force.getSalesGuys().add( eric );
session.save( eric );
SalesGuy simon = new SalesGuy( "simon" );
simon.setName( "Simon" );
simon.setSalesForce( force );
force.getSalesGuys().add( simon );
session.save( simon );
transaction.commit();
session.clear();
// removing one sales guy, leaving the other in place
transaction = session.beginTransaction();
force = session.get( SalesForce.class, force.getId() );
assertEquals( 2, force.getSalesGuys().size() );
SalesGuy salesGuy = session.get( SalesGuy.class, eric.getId() );
salesGuy.setSalesForce( null );
force.getSalesGuys().remove( salesGuy );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
force = session.get( SalesForce.class, force.getId() );
assertEquals( 1, force.getSalesGuys().size() );
salesGuy = force.getSalesGuys().iterator().next();
assertThat( salesGuy.getName() ).isEqualTo( "Simon" );
session.delete( session.get( SalesGuy.class, eric.getId() ) );
session.delete( session.get( SalesGuy.class, simon.getId() ) );
session.delete( force );
transaction.commit();
session.close();
checkCleanCache();
}
@Test
public void testBiDirManyToOneInsertUpdateFalse() throws Exception {
final Session session = openSession();
Transaction tx = session.beginTransaction();
Beer hoegaarden = new Beer();
Brewery hoeBrewery = new Brewery();
hoeBrewery.getBeers().add( hoegaarden );
hoegaarden.setBrewery( hoeBrewery );
session.persist( hoeBrewery );
tx.commit();
session.clear();
tx = session.beginTransaction();
hoegaarden = get( session, Beer.class, hoegaarden.getId() );
assertThat( hoegaarden ).isNotNull();
assertThat( hoegaarden.getBrewery() ).isNotNull();
assertThat( hoegaarden.getBrewery().getBeers() )
.hasSize( 1 )
.containsOnly( hoegaarden );
Beer citron = new Beer();
hoeBrewery = hoegaarden.getBrewery();
hoeBrewery.getBeers().remove( hoegaarden );
hoeBrewery.getBeers().add( citron );
citron.setBrewery( hoeBrewery );
session.delete( hoegaarden );
tx.commit();
session.clear();
tx = session.beginTransaction();
citron = get( session, Beer.class, citron.getId() );
assertThat( citron.getBrewery().getBeers() )
.hasSize( 1 )
.containsOnly( citron );
hoeBrewery = citron.getBrewery();
citron.setBrewery( null );
hoeBrewery.getBeers().clear();
session.delete( citron );
session.delete( hoeBrewery );
tx.commit();
session.close();
checkCleanCache();
}
@Test
public void testRemovalOfTransientEntityWithAssociation() throws Exception {
final Session session = openSession();
Transaction transaction = session.beginTransaction();
SalesForce force = new SalesForce( "red_hat" );
force.setCorporation( "Red Hat" );
session.save( force );
SalesGuy eric = new SalesGuy( "eric" );
eric.setName( "Eric" );
eric.setSalesForce( force );
force.getSalesGuys().add( eric );
session.save( eric );
SalesGuy simon = new SalesGuy( "simon" );
simon.setName( "Simon" );
simon.setSalesForce( force );
force.getSalesGuys().add( simon );
session.save( simon );
transaction.commit();
session.clear();
transaction = session.beginTransaction();
// The classic API allows to delete transient instances;
// Intentionally not deleting the referencing sales guys
session.delete( force );
transaction.commit();
transaction = session.beginTransaction();
SalesGuy salesGuy = session.get( SalesGuy.class, "eric" );
assertThat( salesGuy.getSalesForce() ).describedAs( "Stale association should be exposed as null" ).isNull();
session.delete( salesGuy );
salesGuy = session.get( SalesGuy.class, "simon" );
assertThat( salesGuy.getSalesForce() ).describedAs( "Stale association should be exposed as null" ).isNull();
session.delete( salesGuy );
transaction.commit();
session.close();
checkCleanCache();
}
@Test
public void testDefaultBiDirManyToOneCompositeKeyTest() throws Exception {
Session session = openSession();
Transaction transaction = session.beginTransaction();
Court court = new Court();
court.setId( new Court.CourtId() );
court.getId().setCountryCode( "DE" );
court.getId().setSequenceNo( 123 );
court.setName( "Hamburg Court" );
session.persist( court );
Game game1 = new Game();
game1.setId( new Game.GameId() );
game1.getId().setCategory( "primary" );
game1.getId().setSequenceNo( 456 );
game1.setName( "The game" );
game1.setPlayedOn( court );
court.getGames().add( game1 );
Game game2 = new Game();
game2.setId( new Game.GameId() );
game2.getId().setCategory( "primary" );
game2.getId().setSequenceNo( 457 );
game2.setName( "The other game" );
game2.setPlayedOn( court );
session.persist( game1 );
session.persist( game2 );
session.flush();
transaction.commit();
session.clear();
transaction = session.beginTransaction();
Court localCourt = session.get( Court.class, new Court.CourtId( "DE", 123 ) );
assertThat( localCourt.getGames() ).hasSize( 2 );
for ( Game game : localCourt.getGames() ) {
session.delete( game );
}
localCourt.getGames().clear();
session.delete( localCourt );
transaction.commit();
session.close();
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
JUG.class,
Member.class,
SalesForce.class,
SalesGuy.class,
Beer.class,
Brewery.class,
Game.class,
Court.class,
Employee.class,
Employer.class
};
}
}