/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010-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.immutable.entitywithmutablecollection;
import java.util.Iterator;
import org.junit.Test;
import org.hibernate.MappingException;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Gail Badner
*/
public abstract class AbstractEntityWithManyToManyTest extends BaseCoreFunctionalTestCase {
private boolean isPlanContractsInverse;
private boolean isPlanContractsBidirectional;
private boolean isPlanVersioned;
private boolean isContractVersioned;
@Override
public void configure(Configuration cfg) {
cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
}
@Override
protected void prepareTest() throws Exception {
super.prepareTest();
isPlanContractsInverse = sessionFactory().getCollectionPersister( Plan.class.getName() + ".contracts" ).isInverse();
try {
sessionFactory().getCollectionPersister( Contract.class.getName() + ".plans" );
isPlanContractsBidirectional = true;
}
catch ( MappingException ex) {
isPlanContractsBidirectional = false;
}
isPlanVersioned = sessionFactory().getEntityPersister( Plan.class.getName() ).isVersioned();
isContractVersioned = sessionFactory().getEntityPersister( Contract.class.getName() ).isVersioned();
sessionFactory().getStatistics().clear();
}
@Test
public void testUpdateProperty() {
clearCounts();
Plan p = new Plan( "plan" );
p.addContract( new Contract( null, "gail", "phone") );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(p);
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = (Plan) s.createCriteria( Plan.class ).uniqueResult();
p.setDescription( "new plan" );
assertEquals( 1, p.getContracts().size() );
Contract c = ( Contract ) p.getContracts().iterator().next();
c.setCustomerName( "yogi" );
t.commit();
s.close();
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = (Plan) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertEquals( 1, c.getPlans().size() );
assertSame( p, c.getPlans().iterator().next() );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testCreateWithNonEmptyManyToManyCollectionOfNew() {
clearCounts();
Plan p = new Plan( "plan" );
p.addContract( new Contract( null, "gail", "phone") );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(p);
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
Contract c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertEquals( 1, c.getPlans().size() );
assertSame( p, c.getPlans().iterator().next() );
}
s.delete(p);
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testCreateWithNonEmptyManyToManyCollectionOfExisting() {
clearCounts();
Contract c = new Contract( null, "gail", "phone");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
Plan p = new Plan( "plan" );
p.addContract( c );
s = openSession();
t = s.beginTransaction();
s.save(p);
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isContractVersioned ? 1 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertEquals( 1, c.getPlans().size() );
assertSame( p, c.getPlans().iterator().next() );
}
s.delete(p);
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testAddNewManyToManyElementToPersistentEntity() {
clearCounts();
Plan p = new Plan( "plan" );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.get( Plan.class, p.getId() );
assertEquals( 0, p.getContracts().size() );
p.addContract( new Contract( null, "gail", "phone") );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isContractVersioned ? 1 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
Contract c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertEquals( 1, c.getPlans().size() );
assertSame( p, c.getPlans().iterator().next() );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testAddExistingManyToManyElementToPersistentEntity() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone" );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
s.persist( c );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.get( Plan.class, p.getId() );
assertEquals( 0, p.getContracts().size() );
c = ( Contract ) s.get( Contract.class, c.getId() );
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
p.addContract( c );
t.commit();
s.close();
assertInsertCount( 0 );
assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testCreateWithEmptyManyToManyCollectionUpdateWithExistingElement() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
s.persist( c );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.addContract( c );
s = openSession();
t = s.beginTransaction();
s.update( p );
t.commit();
s.close();
assertInsertCount( 0 );
assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testCreateWithNonEmptyManyToManyCollectionUpdateWithNewElement() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(p);
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
Contract newC = new Contract( null, "sherman", "telepathy" );
p.addContract( newC );
s = openSession();
t = s.beginTransaction();
s.update( p );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isContractVersioned ? 1 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 2, p.getContracts().size() );
for ( Iterator it=p.getContracts().iterator(); it.hasNext(); ) {
Contract aContract = ( Contract ) it.next();
if ( aContract.getId() == c.getId() ) {
assertEquals( "gail", aContract.getCustomerName() );
}
else if ( aContract.getId() == newC.getId() ) {
assertEquals( "sherman", aContract.getCustomerName() );
}
else {
fail( "unknown contract" );
}
if ( isPlanContractsBidirectional ) {
assertSame( p, aContract.getPlans().iterator().next() );
}
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 3 );
}
@Test
public void testCreateWithEmptyManyToManyCollectionMergeWithExistingElement() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
s.persist( c );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.addContract( c );
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.merge( p );
t.commit();
s.close();
assertInsertCount( 0 );
assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testCreateWithNonEmptyManyToManyCollectionMergeWithNewElement() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
Contract newC = new Contract( null, "yogi", "mail" );
p.addContract( newC );
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.merge( p );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 2, p.getContracts().size() );
for ( Iterator it=p.getContracts().iterator(); it.hasNext(); ) {
Contract aContract = ( Contract ) it.next();
if ( aContract.getId() == c.getId() ) {
assertEquals( "gail", aContract.getCustomerName() );
}
else if ( ! aContract.getCustomerName().equals( newC.getCustomerName() ) ) {
fail( "unknown contract:" + aContract.getCustomerName() );
}
if ( isPlanContractsBidirectional ) {
assertSame( p, aContract.getPlans().iterator().next() );
}
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 3 );
}
@Test
public void testRemoveManyToManyElementUsingUpdate() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.removeContract( c );
assertEquals( 0, p.getContracts().size() );
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s = openSession();
t = s.beginTransaction();
s.update( p );
t.commit();
s.close();
assertUpdateCount( isContractVersioned ? 1 : 0 );
assertDeleteCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
if ( isPlanContractsInverse ) {
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
assertSame( p, c.getPlans().iterator().next() );
}
else {
assertEquals( 0, p.getContracts().size() );
c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s.delete( c );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testRemoveManyToManyElementUsingUpdateBothSides() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.removeContract( c );
assertEquals( 0, p.getContracts().size() );
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s = openSession();
t = s.beginTransaction();
s.update( p );
s.update( c );
t.commit();
s.close();
assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
assertDeleteCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 0, p.getContracts().size() );
c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s.delete( c );
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testRemoveManyToManyElementUsingMerge() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.removeContract( c );
assertEquals( 0, p.getContracts().size() );
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.merge( p );
t.commit();
s.close();
assertUpdateCount( isContractVersioned ? 1 : 0 );
assertDeleteCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
if ( isPlanContractsInverse ) {
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
assertSame( p, c.getPlans().iterator().next() );
}
else {
assertEquals( 0, p.getContracts().size() );
c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s.delete( c );
}
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testRemoveManyToManyElementUsingMergeBothSides() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.removeContract( c );
assertEquals( 0, p.getContracts().size() );
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.merge( p );
c = ( Contract ) s.merge( c );
t.commit();
s.close();
assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
assertDeleteCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 0, p.getContracts().size() );
c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s.delete( c );
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testDeleteManyToManyElement() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
s.update( p );
p.removeContract( c );
s.delete( c );
t.commit();
s.close();
assertUpdateCount( isContractVersioned ? 1 : 0 );
assertDeleteCount( 1 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 0, p.getContracts().size() );
c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
assertNull( c );
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
public void testRemoveManyToManyElementByDelete() {
clearCounts();
Plan p = new Plan( "plan" );
Contract c = new Contract( null, "gail", "phone");
p.addContract( c );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
p.removeContract( c );
assertEquals( 0, p.getContracts().size() );
if ( isPlanContractsBidirectional ) {
assertEquals( 0, c.getPlans().size() );
}
s = openSession();
t = s.beginTransaction();
s.update( p );
s.delete( c );
t.commit();
s.close();
assertUpdateCount( isPlanVersioned ? 1 : 0 );
assertDeleteCount( 1 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 0, p.getContracts().size() );
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
public void testManyToManyCollectionOptimisticLockingWithMerge() {
clearCounts();
Plan pOrig = new Plan( "plan" );
Contract cOrig = new Contract( null, "gail", "phone");
pOrig.addContract( cOrig );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( pOrig );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
Plan p = ( Plan ) s.get( Plan.class, pOrig.getId() );
Contract newC = new Contract( null, "sherman", "note" );
p.addContract( newC );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isContractVersioned ? 1 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
pOrig.removeContract( cOrig );
try {
s.merge( pOrig );
assertFalse( isContractVersioned );
}
catch (StaleObjectStateException ex) {
assertTrue( isContractVersioned);
}
finally {
t.rollback();
}
s.close();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
s.delete( p );
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 3 );
}
@Test
public void testManyToManyCollectionOptimisticLockingWithUpdate() {
clearCounts();
Plan pOrig = new Plan( "plan" );
Contract cOrig = new Contract( null, "gail", "phone");
pOrig.addContract( cOrig );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(pOrig);
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
Plan p = ( Plan ) s.get( Plan.class, pOrig.getId() );
Contract newC = new Contract( null, "yogi", "pawprint" );
p.addContract( newC );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isContractVersioned ? 1 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
pOrig.removeContract( cOrig );
s.update( pOrig );
try {
t.commit();
assertFalse( isContractVersioned );
}
catch (StaleStateException ex) {
t.rollback();
assertTrue( isContractVersioned );
if ( ! sessionFactory().getSettings().isJdbcBatchVersionedData() ) {
assertTrue( StaleObjectStateException.class.isInstance( ex ) );
}
}
s.close();
s = openSession();
t = s.beginTransaction();
p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
s.delete( p );
s.createQuery( "delete from Contract" ).executeUpdate();
assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
}
@Test
public void testMoveManyToManyElementToNewEntityCollection() {
clearCounts();
Plan p = new Plan( "plan" );
p.addContract( new Contract( null, "gail", "phone" ) );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
t.commit();
s.close();
assertInsertCount( 2 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = (Plan) s.createCriteria( Plan.class ).uniqueResult();
assertEquals( 1, p.getContracts().size() );
Contract c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
p.removeContract( c );
Plan p2 = new Plan( "new plan" );
p2.addContract( c );
s.save( p2 );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( isPlanVersioned && isContractVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p.getId() ) )).uniqueResult();
p2 = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p2.getId() ) )).uniqueResult();
/*
if ( isPlanContractsInverse ) {
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
assertEquals( 0, p2.getContracts().size() );
}
else {
*/
assertEquals( 0, p.getContracts().size() );
assertEquals( 1, p2.getContracts().size() );
c = ( Contract ) p2.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p2, c.getPlans().iterator().next() );
}
//}
s.delete( p );
s.delete( p2 );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 3 );
}
@Test
public void testMoveManyToManyElementToExistingEntityCollection() {
clearCounts();
Plan p = new Plan( "plan" );
p.addContract( new Contract( null, "gail", "phone" ) );
Plan p2 = new Plan( "plan2" );
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist( p );
s.persist( p2 );
t.commit();
s.close();
assertInsertCount( 3 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p.getId() ) )).uniqueResult();
assertEquals( 1, p.getContracts().size() );
Contract c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
p.removeContract( c );
t.commit();
s.close();
assertInsertCount( 0 );
assertUpdateCount( isPlanVersioned && isContractVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p2 = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p2.getId() ) )).uniqueResult();
c = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c.getId() ) )).uniqueResult();
p2.addContract( c );
t.commit();
s.close();
assertInsertCount( 0 );
assertUpdateCount( isPlanVersioned && isContractVersioned ? 2 : 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
p = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p.getId() ) )).uniqueResult();
p2 = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p2.getId() ) )).uniqueResult();
/*
if ( isPlanContractsInverse ) {
assertEquals( 1, p.getContracts().size() );
c = ( Contract ) p.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p, c.getPlans().iterator().next() );
}
assertEquals( 0, p2.getContracts().size() );
}
else {
*/
assertEquals( 0, p.getContracts().size() );
assertEquals( 1, p2.getContracts().size() );
c = ( Contract ) p2.getContracts().iterator().next();
assertEquals( "gail", c.getCustomerName() );
if ( isPlanContractsBidirectional ) {
assertSame( p2, c.getPlans().iterator().next() );
}
//}
s.delete( p );
s.delete( p2 );
assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 3 );
}
protected void clearCounts() {
sessionFactory().getStatistics().clear();
}
protected void assertInsertCount(int expected) {
int inserts = ( int ) sessionFactory().getStatistics().getEntityInsertCount();
assertEquals( "unexpected insert count", expected, inserts );
}
protected void assertUpdateCount(int expected) {
int updates = ( int ) sessionFactory().getStatistics().getEntityUpdateCount();
assertEquals( "unexpected update counts", expected, updates );
}
protected void assertDeleteCount(int expected) {
int deletes = ( int ) sessionFactory().getStatistics().getEntityDeleteCount();
assertEquals( "unexpected delete counts", expected, deletes );
}
}