/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.test.collection.delayedOperation;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Tests delayed operations that are queued for a PersistentSet. remove( Object )
* requires extra lazy to queue the operations.
* @author Gail Badner
*/
public class ListDelayedOperationTest extends BaseCoreFunctionalTestCase {
private Long parentId;
private Long childId1;
private Long childId2;
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
Parent.class,
Child.class
};
}
@Before
public void setup() {
// start by cleaning up in case a test fails
if ( parentId != null ) {
cleanup();
}
Parent parent = new Parent();
Child child1 = new Child( "Sherman" );
Child child2 = new Child( "Yogi" );
parent.addChild( child1 );
parent.addChild( child2 );
Session s = openSession();
s.getTransaction().begin();
s.persist( parent );
s.getTransaction().commit();
s.close();
parentId = parent.getId();
childId1 = child1.getId();
childId2 = child2.getId();
}
@After
public void cleanup() {
Session s = openSession();
s.getTransaction().begin();
Parent parent = s.get( Parent.class, parentId );
parent.getChildren().clear();
s.delete( parent );
s.getTransaction().commit();
s.close();
parentId = null;
}
@Test
@TestForIssue( jiraKey = "HHH-5855")
public void testSimpleAddDetached() {
// Create 2 detached Child objects.
Session s = openSession();
s.getTransaction().begin();
Child c1 = new Child( "Darwin" );
s.persist( c1 );
Child c2 = new Child( "Comet" );
s.persist( c2 );
s.getTransaction().commit();
s.close();
// Now Child c is detached.
s = openSession();
s.getTransaction().begin();
Parent p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// add detached Child c
p.addChild( c1 );
// collection should still be uninitialized
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.getTransaction().commit();
s.close();
// Add a detached Child and commit
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 3, p.getChildren().size() );
s.getTransaction().commit();
s.close();
// Add another detached Child, merge, and commit
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
p.addChild( c2 );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.merge( p );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 4, p.getChildren().size() );
s.getTransaction().commit();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-5855")
public void testSimpleAddTransient() {
// Add a transient Child and commit.
Session s = openSession();
s.getTransaction().begin();
Parent p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// add transient Child
p.addChild( new Child( "Darwin" ) );
// collection should still be uninitialized
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 3, p.getChildren().size() );
s.getTransaction().commit();
s.close();
// Add another transient Child and commit again.
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// add transient Child
p.addChild( new Child( "Comet" ) );
// collection should still be uninitialized
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.merge( p );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 4, p.getChildren().size() );
s.getTransaction().commit();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-5855")
public void testSimpleAddManaged() {
// Add 2 Child entities
Session s = openSession();
s.getTransaction().begin();
Child c1 = new Child( "Darwin" );
s.persist( c1 );
Child c2 = new Child( "Comet" );
s.persist( c2 );
s.getTransaction().commit();
s.close();
// Add a managed Child and commit
s = openSession();
s.getTransaction().begin();
Parent p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// get the first Child so it is managed; add to collection
p.addChild( s.get( Child.class, c1.getId() ) );
// collection should still be uninitialized
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 3, p.getChildren().size() );
s.getTransaction().commit();
s.close();
// Add the other managed Child, merge and commit.
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// get the second Child so it is managed; add to collection
p.addChild( s.get( Child.class, c2.getId() ) );
// collection should still be uninitialized
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.merge( p );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 4, p.getChildren().size() );
s.getTransaction().commit();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-5855")
public void testSimpleRemoveDetached() {
// Get the 2 Child entities and detach.
Session s = openSession();
s.getTransaction().begin();
Child c1 = s.get( Child.class, childId1 );
Child c2 = s.get( Child.class, childId2 );
s.getTransaction().commit();
s.close();
// Remove a detached entity element and commit
s = openSession();
s.getTransaction().begin();
Parent p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// remove a detached element and commit
Hibernate.initialize( p.getChildren() );
p.removeChild( c1 );
for ( Child c : p.getChildren() ) {
if ( c.equals( c1 ) ) {
s.evict( c );
}
}
assertTrue( Hibernate.isInitialized( p.getChildren() ) );
//s.merge( p );
s.getTransaction().commit();
s.close();
// Remove a detached entity element, merge, and commit
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
Hibernate.initialize( p.getChildren() );
assertEquals( 1, p.getChildren().size() );
s.getTransaction().commit();
s.close();
// Remove a detached entity element, merge, and commit
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// remove a detached element and commit
p.removeChild( c2 );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
p = (Parent) s.merge( p );
Hibernate.initialize( p );
s.getTransaction().commit();
s.close();
// Remove a detached entity element, merge, and commit
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 0, p.getChildren().size() );
s.getTransaction().commit();
s.close();
}
/* STILL WORKING ON THIS ONE...
@Test
@TestForIssue( jiraKey = "HHH-5855")
public void testSimpleRemoveManaged() {
// Remove a managed entity element and commit
Session s = openSession();
s.getTransaction().begin();
Parent p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// get c1 so it is managed, then remove and commit
p.removeChild( s.get( Child.class, childId1 ) );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 1, p.getChildren().size() );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
// get c1 so it is managed, then remove, merge and commit
p.removeChild( s.get( Child.class, childId2 ) );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
s.merge( p );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
p = s.get( Parent.class, parentId );
assertFalse( Hibernate.isInitialized( p.getChildren() ) );
assertEquals( 0, p.getChildren().size() );
s.getTransaction().commit();
s.close();
}
*/
@Entity(name = "Parent")
public static class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
@LazyCollection(LazyCollectionOption.EXTRA )
@OrderColumn
private List<Child> children = new ArrayList<Child>();
public Parent() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Child> getChildren() {
return children;
}
public void addChild(Child child) {
children.add(child);
child.setParent(this);
}
public void addChild(Child child, int i) {
children.add(i, child );
child.setParent(this);
}
public void removeChild(Child child) {
children.remove(child);
child.setParent(null);
}
}
@Entity(name = "Child")
public static class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false)
private String name;
@ManyToOne
private Parent parent;
public Child() {
}
public Child(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
@Override
public String toString() {
return "Child{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Child child = (Child) o;
return name.equals( child.name );
}
@Override
public int hashCode() {
return name.hashCode();
}
}
}