Re-enabled additional tests

This commit is contained in:
Andrea Boriero 2020-08-20 08:55:12 +01:00
parent 4806398ecc
commit 82de2b0a3f
40 changed files with 2325 additions and 2325 deletions

View File

@ -0,0 +1,169 @@
/*
* Copyright 2014 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.orm.test.collection.bag;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
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 org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* This template demonstrates how to develop a test case for Hibernate ORM, using its built-in unit test framework.
* Although ORMStandaloneTestCase is perfectly acceptable as a reproducer, usage of this class is much preferred.
* Since we nearly always include a regression test with bug fixes, providing your reproducer using this method
* simplifies the process.
* <p>
* What's even better? Fork hibernate-orm itself, add your test case directly to a module's unit tests, then
* submit it as a PR!
*/
@DomainModel(
annotatedClasses = {
BagDuplicatesTest.Parent.class,
BagDuplicatesTest.Child.class
}
)
@SessionFactory
public class BagDuplicatesTest {
@Test
public void HHH10385Test(SessionFactoryScope scope) {
Long parentId = scope.fromTransaction(
session -> {
Parent parent = new Parent();
session.persist( parent );
session.flush();
return parent.getId();
}
);
scope.inTransaction(
session -> {
Parent parent = session.get( Parent.class, parentId );
Child child1 = new Child();
child1.setName( "child1" );
child1.setParent( parent );
parent.addChild( child1 );
parent = (Parent) session.merge( parent );
session.flush();
}
);
scope.inTransaction(
session -> {
Parent parent = session.get( Parent.class, parentId );
assertEquals( 1, parent.getChildren().size() );
}
);
}
@Entity(name = "Parent")
public static class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
private List<Child> children = new ArrayList<>();
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 removeChild(Child child) {
children.remove( child );
child.setParent( null );
}
}
@Entity(name = "Child")
public static class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne
private Parent parent;
public Child() {
}
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 + '\'' +
'}';
}
}
}

View File

@ -0,0 +1,199 @@
/*
* 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.orm.test.collection.bag;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Gail Badner
*/
@DomainModel(annotatedClasses = {
BagElementNullBasicTest.AnEntity.class,
BagElementNullBasicTest.NullableElementsEntity.class
})
@SessionFactory
public class BagElementNullBasicTest {
@Test
public void testPersistNullValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( null );
session.persist( e );
return e.id;
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void addNullValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
session.persist( e );
return e.id;
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
e.aCollection.add( null );
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-13651")
public void addNullValueToNullableCollections(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
NullableElementsEntity e = new NullableElementsEntity();
e.list.add( null );
session.persist( e );
session.flush();
}
);
}
@Test
public void testUpdateNonNullValueToNull(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
session.persist( e );
return e.id;
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
e.aCollection.set( 0, null );
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void testUpdateNonNullValueToNullWithExtraValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
e.aCollection.add( "ghi" );
session.persist( e );
return e.id;
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 2, e.aCollection.size() );
assertEquals( 2, getCollectionElementRows( e.id, scope ).size() );
e.aCollection.set( 0, null );
}
);
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( e.id, scope ).size() );
assertEquals( "ghi", e.aCollection.get( 0 ) );
session.delete( e );
}
);
}
private List getCollectionElementRows(int id, SessionFactoryScope scope) {
return scope.fromTransaction(
session ->
session.createNativeQuery(
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
).list()
);
}
@Entity
@Table(name = "AnEntity")
public static class AnEntity {
@Id
@GeneratedValue
private int id;
@ElementCollection
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn(name = "AnEntity_id") })
@OrderBy
private List<String> aCollection = new ArrayList<>();
}
@Entity
@Table(name = "NullableElementsEntity")
public static class NullableElementsEntity {
@Id
@GeneratedValue
private int id;
@ElementCollection
@CollectionTable(name = "e_2_string", joinColumns = @JoinColumn(name = "e_id"))
@Column(name = "string_value", unique = false, nullable = true, insertable = true, updatable = true)
private List<String> list = new ArrayList<>();
}
}

View File

@ -4,7 +4,7 @@
* 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.bag;
package org.hibernate.orm.test.collection.bag;
import java.util.ArrayList;
import java.util.List;

View File

@ -4,7 +4,7 @@
* 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.bag;
package org.hibernate.orm.test.collection.bag;
/**
* @author Gail Badner

View File

@ -10,7 +10,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.collection.bag">
<hibernate-mapping package="org.hibernate.orm.test.collection.bag">
<class name="BagOwner">
<id name="name" column="NAME" type="string" />

View File

@ -4,7 +4,7 @@
* 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.bag;
package org.hibernate.orm.test.collection.bag;
import java.util.ArrayList;
import java.util.List;
@ -15,7 +15,7 @@ import java.util.List;
public class Order {
private Long id;
private List<Item> items = new ArrayList<Item>();
private List<Item> items = new ArrayList<>();
public Order() {
}

View File

@ -4,7 +4,7 @@
* 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.bag;
package org.hibernate.orm.test.collection.bag;
import java.util.ArrayList;
import java.util.List;
@ -17,26 +17,26 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests related to contains operations on a PersistentBag.
*
* @author Vlad Mihalcea
*/
public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {
Order.class,
Item.class
};
}
@DomainModel(
annotatedClasses = {
PersistentBagContainsTest.Order.class,
PersistentBagContainsTest.Item.class
}
)
@SessionFactory
public class PersistentBagContainsTest {
/**
* This test does not verify how equals is implemented for Bags,
@ -44,9 +44,9 @@ public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
* managed and detached entities.
*/
@Test
@TestForIssue( jiraKey = "HHH-5409")
public void testContains() {
Order _order = doInHibernate( this::sessionFactory, session -> {
@TestForIssue(jiraKey = "HHH-5409")
public void testContains(SessionFactoryScope scope) {
Order _order = scope.fromTransaction( session -> {
Order order = new Order();
session.persist( order );
@ -60,23 +60,23 @@ public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
return order;
} );
doInHibernate( this::sessionFactory, session -> {
scope.inTransaction( session -> {
Item item1 = new Item();
item1.setName( "i1" );
Item item2 = new Item();
item2.setName( "i2" );
assertTrue(_order.getItems().contains( item1 ));
assertTrue(_order.getItems().contains( item2 ));
assertTrue( _order.getItems().contains( item1 ) );
assertTrue( _order.getItems().contains( item2 ) );
Order order = session.find( Order.class, _order.getId() );
assertTrue(order.getItems().contains( item1 ));
assertTrue(order.getItems().contains( item2 ));
assertTrue( order.getItems().contains( item1 ) );
assertTrue( order.getItems().contains( item2 ) );
} );
doInHibernate( this::sessionFactory, session -> {
scope.inTransaction( session -> {
Order order = session.find( Order.class, _order.getId() );
session.delete( order );
} );
@ -90,7 +90,7 @@ public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
private Long id;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Item> items = new ArrayList<Item>();
private List<Item> items = new ArrayList<>();
public Long getId() {
return id;

View File

@ -0,0 +1,116 @@
/*
* 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.orm.test.collection.bag;
import java.util.ArrayList;
import org.hibernate.collection.internal.PersistentBag;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests related to operations on a PersistentBag.
*
* @author Steve Ebersole
*/
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsNoColumnInsert.class)
@DomainModel(
xmlMappings = "org/hibernate/orm/test/collection/bag/Mappings.hbm.xml"
)
@SessionFactory
public class PersistentBagTest {
@Test
public void testWriteMethodDirtying(SessionFactoryScope scope) {
BagOwner parent = new BagOwner( "root" );
BagOwner child = new BagOwner( "c1" );
parent.getChildren().add( child );
child.setParent( parent );
BagOwner otherChild = new BagOwner( "c2" );
scope.inTransaction(
session -> {
session.save( parent );
session.flush();
// at this point, the list on parent has now been replaced with a PersistentBag...
PersistentBag children = (PersistentBag) parent.getChildren();
assertFalse( children.remove( otherChild ) );
assertFalse( children.isDirty() );
ArrayList otherCollection = new ArrayList();
otherCollection.add( child );
assertFalse( children.retainAll( otherCollection ) );
assertFalse( children.isDirty() );
otherCollection = new ArrayList();
otherCollection.add( otherChild );
assertFalse( children.removeAll( otherCollection ) );
assertFalse( children.isDirty() );
children.clear();
session.delete( child );
assertTrue( children.isDirty() );
session.flush();
children.clear();
assertFalse( children.isDirty() );
session.delete( parent );
}
);
}
@Test
@SkipForDialect(dialectClass = AbstractHANADialect.class, reason = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMergePersistentEntityWithNewOneToManyElements(SessionFactoryScope scope) {
Long orderId = scope.fromTransaction(
session -> {
Order order = new Order();
session.persist( order );
session.flush();
return order.getId();
}
);
scope.inTransaction(
session -> {
Order order = session.get( Order.class, orderId );
Item item1 = new Item();
item1.setName( "i1" );
Item item2 = new Item();
item2.setName( "i2" );
order.addItem( item1 );
order.addItem( item2 );
order = (Order) session.merge( order );
}
);
scope.inTransaction(
session -> {
Order order = session.get( Order.class, orderId );
assertEquals( 2, order.getItems().size() );
session.delete( order );
}
);
}
}

View File

@ -4,7 +4,7 @@
* 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.idbag;
package org.hibernate.orm.test.collection.idbag;
import java.util.ArrayList;
import java.util.List;
@ -21,28 +21,26 @@ import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Gail Badner
*/
public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
AnEntity.class
};
}
@DomainModel(
annotatedClasses = IdBagElementNullBasicTest.AnEntity.class
)
@SessionFactory
public class IdBagElementNullBasicTest {
@Test
public void testPersistNullValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void testPersistNullValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( null );
session.persist( e );
@ -50,49 +48,49 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void addNullValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void addNullValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
session.persist( e );
return e.id;
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
e.aCollection.add( null );
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void testUpdateNonNullValueToNull() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void testUpdateNonNullValueToNull(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
session.persist( e );
@ -100,29 +98,29 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( entityId ).size() );
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
e.aCollection.set( 0, null );
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void testUpdateNonNullValueToNullWithExtraValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void testUpdateNonNullValueToNullWithExtraValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
e.aCollection.add( "ghi" );
@ -131,11 +129,11 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 2, e.aCollection.size() );
assertEquals( 2, getCollectionElementRows( e.id ).size() );
assertEquals( 2, getCollectionElementRows( e.id, scope ).size() );
if ( "def".equals( e.aCollection.get( 0 ) ) ) {
e.aCollection.set( 0, null );
}
@ -145,20 +143,20 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( e.id ).size() );
assertEquals( 1, getCollectionElementRows( e.id, scope ).size() );
assertEquals( "ghi", e.aCollection.get( 0 ) );
session.delete( e );
}
);
}
private List getCollectionElementRows(int id) {
return doInHibernate(
this::sessionFactory, session -> {
private List getCollectionElementRows(int id, SessionFactoryScope scope) {
return scope.fromTransaction(
session -> {
return session.createNativeQuery(
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
).list();
@ -167,20 +165,20 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
@Entity
@Table(name="AnEntity")
@GenericGenerator(name="increment", strategy = "increment")
@Table(name = "AnEntity")
@GenericGenerator(name = "increment", strategy = "increment")
public static class AnEntity {
@Id
@GeneratedValue
private int id;
@ElementCollection
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn( name = "AnEntity_id" ) })
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn(name = "AnEntity_id") })
@CollectionId(
columns = { @Column },
type = @Type(type = "long"),
generator = "increment"
)
private List<String> aCollection = new ArrayList<String>();
private List<String> aCollection = new ArrayList<>();
}
}

View File

@ -4,7 +4,7 @@
* 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.idbag;
package org.hibernate.orm.test.collection.idbag;
import java.util.ArrayList;
import java.util.List;

View File

@ -10,7 +10,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.collection.idbag">
<hibernate-mapping package="org.hibernate.orm.test.collection.idbag">
<class name="IdbagOwner">
<id name="name" column="NAME" type="string" />

View File

@ -0,0 +1,73 @@
/*
* 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.orm.test.collection.idbag;
import java.util.ArrayList;
import org.hibernate.collection.internal.PersistentIdentifierBag;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests related to operations on a PersistentIdentifierBag
*
* @author Steve Ebersole
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/collection/idbag/Mappings.hbm.xml"
)
@SessionFactory
public class PersistentIdBagTest {
@Test
public void testWriteMethodDirtying(SessionFactoryScope scope) {
IdbagOwner parent = new IdbagOwner( "root" );
IdbagOwner child = new IdbagOwner( "c1" );
parent.getChildren().add( child );
IdbagOwner otherChild = new IdbagOwner( "c2" );
scope.inTransaction(
session -> {
session.save( parent );
session.flush();
// at this point, the list on parent has now been replaced with a PersistentBag...
PersistentIdentifierBag children = (PersistentIdentifierBag) parent.getChildren();
assertFalse( children.remove( otherChild ) );
assertFalse( children.isDirty() );
ArrayList otherCollection = new ArrayList();
otherCollection.add( child );
assertFalse( children.retainAll( otherCollection ) );
assertFalse( children.isDirty() );
otherCollection = new ArrayList();
otherCollection.add( otherChild );
assertFalse( children.removeAll( otherCollection ) );
assertFalse( children.isDirty() );
children.clear();
session.delete( child );
assertTrue( children.isDirty() );
session.flush();
children.clear();
assertFalse( children.isDirty() );
session.delete( parent );
}
);
}
}

View File

@ -4,7 +4,7 @@
* 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.list;
package org.hibernate.orm.test.collection.list;
/**

View File

@ -4,7 +4,7 @@
* 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.list;
package org.hibernate.orm.test.collection.list;
import java.util.ArrayList;
import java.util.List;
@ -17,28 +17,26 @@ import javax.persistence.JoinColumn;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Gail Badner
*/
public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
AnEntity.class
};
}
@DomainModel(
annotatedClasses = ListElementNullBasicTest.AnEntity.class
)
@SessionFactory
public class ListElementNullBasicTest {
@Test
public void testPersistNullValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void testPersistNullValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( null );
session.persist( e );
@ -46,49 +44,49 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void addNullValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void addNullValue(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
session.persist( e );
return e.id;
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
e.aCollection.add( null );
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void testUpdateNonNullValueToNull() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void testUpdateNonNullValueToNull(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
session.persist( e );
@ -96,29 +94,29 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( entityId ).size() );
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
e.aCollection.set( 0, null );
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
session.delete( e );
}
);
}
@Test
public void testUpdateNonNullValueToNullToNonNull() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
public void testUpdateNonNullValueToNullToNonNull(SessionFactoryScope scope) {
int entityId = scope.fromTransaction(
session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
e.aCollection.add( "ghi" );
@ -127,29 +125,29 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 2, e.aCollection.size() );
assertEquals( 2, getCollectionElementRows( e.id ).size() );
assertEquals( 2, getCollectionElementRows( e.id, scope ).size() );
e.aCollection.set( 0, null );
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 2, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( e.id ).size() );
assertEquals( 1, getCollectionElementRows( e.id, scope ).size() );
e.aCollection.set( 0, "not null" );
}
);
doInHibernate(
this::sessionFactory, session -> {
scope.inTransaction(
session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 2, e.aCollection.size() );
assertEquals( 2, getCollectionElementRows( e.id ).size() );
assertEquals( 2, getCollectionElementRows( e.id, scope ).size() );
assertEquals( "not null", e.aCollection.get( 0 ) );
assertEquals( "ghi", e.aCollection.get( 1 ) );
session.delete( e );
@ -157,9 +155,9 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
);
}
private List getCollectionElementRows(int id) {
return doInHibernate(
this::sessionFactory, session -> {
private List getCollectionElementRows(int id, SessionFactoryScope scope) {
return scope.fromTransaction(
session -> {
return session.createNativeQuery(
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
).list();
@ -168,15 +166,15 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
}
@Entity
@Table(name="AnEntity")
@Table(name = "AnEntity")
public static class AnEntity {
@Id
@GeneratedValue
private int id;
@ElementCollection
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn( name = "AnEntity_id" ) })
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn(name = "AnEntity_id") })
@OrderColumn
private List<String> aCollection = new ArrayList<String>();
private List<String> aCollection = new ArrayList<>();
}
}

View File

@ -0,0 +1,139 @@
/*
* 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.orm.test.collection.list;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Test initially developed for HHH-9195
*
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
ListIndexReferenceFromListElementTest.LocalOrder.class,
ListIndexReferenceFromListElementTest.LocalLineItem.class
}
)
@SessionFactory
public class ListIndexReferenceFromListElementTest {
@BeforeEach
public void before(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
LocalOrder localOrder = new LocalOrder();
localOrder.makeLineItem( "Shoes" );
localOrder.makeLineItem( "Socks" );
session.save( localOrder );
}
);
}
@AfterEach
public void after(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete LocalLineItem" ).executeUpdate();
session.createQuery( "delete LocalOrder" ).executeUpdate();
}
);
}
@Test
public void testIt(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
LocalOrder order = session.byId( LocalOrder.class ).load( 1 );
assertEquals( 2, order.lineItems.size() );
LocalLineItem shoes = order.lineItems.get( 0 );
LocalLineItem socks = order.lineItems.get( 1 );
assertEquals( "Shoes", shoes.name );
assertEquals( 0, shoes.position );
assertEquals( 1, socks.position );
order.lineItems.remove( socks );
order.lineItems.add( 0, socks );
}
);
scope.inTransaction(
session -> {
LocalOrder order = session.byId( LocalOrder.class ).load( 1 );
assertEquals( 2, order.lineItems.size() );
LocalLineItem socks = order.lineItems.get( 0 );
LocalLineItem shoes = order.lineItems.get( 1 );
assertEquals( "Shoes", shoes.name );
assertEquals( 0, socks.position );
assertEquals( 1, shoes.position );
}
);
}
@Entity(name = "LocalOrder")
@Table(name = "LocalOrder")
public static class LocalOrder {
@Id
@GeneratedValue
public Integer id;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OrderColumn(name = "position")
public List<LocalLineItem> lineItems = new ArrayList<>();
public LocalOrder() {
}
public LocalLineItem makeLineItem(String name) {
LocalLineItem lineItem = new LocalLineItem( name, this );
lineItems.add( lineItem );
return lineItem;
}
}
@Entity(name = "LocalLineItem")
@Table(name = "LocalLineItem")
public static class LocalLineItem {
@Id
@GeneratedValue
public Integer id;
public String name;
@ManyToOne
@JoinColumn
public LocalOrder order;
@Column(insertable = false, updatable = false)
public int position;
public LocalLineItem() {
}
public LocalLineItem(String name, LocalOrder order) {
this.name = name;
this.order = order;
}
}
}

View File

@ -4,7 +4,7 @@
* 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.list;
package org.hibernate.orm.test.collection.list;
import java.util.ArrayList;
import java.util.List;

View File

@ -10,7 +10,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.collection.list">
<hibernate-mapping package="org.hibernate.orm.test.collection.list">
<class name="ListOwner">
<id name="name" column="NAME" type="string" />

View File

@ -4,7 +4,7 @@
* 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.list;
package org.hibernate.orm.test.collection.list;
import java.util.ArrayList;
import java.util.List;
@ -15,7 +15,7 @@ import java.util.List;
public class Order {
private Integer id;
private String code;
private List<LineItem> lineItems = new ArrayList<LineItem>();
private List<LineItem> lineItems = new ArrayList<>();
public Order() {
}

View File

@ -0,0 +1,207 @@
/*
* 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.orm.test.collection.list;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.collection.internal.PersistentList;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Tests related to operations on a PersistentList
*
* @author Steve Ebersole
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/collection/list/Mappings.hbm.xml"
)
@SessionFactory
public class PersistentListTest {
@Test
@TestForIssue(jiraKey = "HHH-5732")
public void testInverseListIndex(SessionFactoryScope scope) {
// make sure no one changes the mapping
SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
final CollectionPersister collectionPersister = sessionFactory
.getCollectionPersister( ListOwner.class.getName() + ".children" );
assertTrue( collectionPersister.isInverse() );
// do some creations...
ListOwner root = new ListOwner( "root" );
scope.inTransaction(
session -> {
ListOwner child1 = new ListOwner( "c1" );
root.getChildren().add( child1 );
child1.setParent( root );
ListOwner child2 = new ListOwner( "c2" );
root.getChildren().add( child2 );
child2.setParent( root );
session.save( root );
}
);
// now, make sure the list-index column gotten written...
scope.inTransaction(
session2 -> {
session2.doWork(
connection -> {
final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
SimpleSelect select = new SimpleSelect( sessionFactory.getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "NAME" )
.addColumn( "LIST_INDEX" )
.addCondition( "NAME", "<>", "?" );
PreparedStatement preparedStatement = ( (SessionImplementor) session2 ).getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( select.toStatementString() );
preparedStatement.setString( 1, "root" );
ResultSet resultSet = ( (SessionImplementor) session2 ).getJdbcCoordinator()
.getResultSetReturn()
.extract( preparedStatement );
Map<String, Integer> valueMap = new HashMap<String, Integer>();
while ( resultSet.next() ) {
final String name = resultSet.getString( 1 );
assertFalse( "NAME column was null", resultSet.wasNull() );
final int position = resultSet.getInt( 2 );
assertFalse( "LIST_INDEX column was null", resultSet.wasNull() );
valueMap.put( name, position );
}
assertEquals( 2, valueMap.size() );
// c1 should be list index 0
assertEquals( Integer.valueOf( 0 ), valueMap.get( "c1" ) );
// c2 should be list index 1
assertEquals( Integer.valueOf( 1 ), valueMap.get( "c2" ) );
}
);
session2.delete( root );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-5732")
public void testInverseListIndex2(SessionFactoryScope scope) {
// make sure no one changes the mapping
SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
final CollectionPersister collectionPersister = sessionFactory
.getCollectionPersister( Order.class.getName() + ".lineItems" );
assertTrue( collectionPersister.isInverse() );
// do some creations...
Order order = new Order( "acme-1" );
scope.inTransaction(
session -> {
order.addLineItem( "abc", 2 );
order.addLineItem( "def", 200 );
order.addLineItem( "ghi", 13 );
session.save( order );
}
);
// now, make sure the list-index column gotten written...
scope.inTransaction(
session2 -> {
session2.doWork(
connection -> {
final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
SimpleSelect select = new SimpleSelect( sessionFactory.getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "ORDER_ID" )
.addColumn( "INDX" )
.addColumn( "PRD_CODE" );
PreparedStatement preparedStatement = ( (SessionImplementor) session2 ).getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( select.toStatementString() );
ResultSet resultSet = ( (SessionImplementor) session2 ).getJdbcCoordinator()
.getResultSetReturn()
.extract( preparedStatement );
Map<String, Integer> valueMap = new HashMap<String, Integer>();
while ( resultSet.next() ) {
final int fk = resultSet.getInt( 1 );
assertFalse( "Collection key (FK) column was null", resultSet.wasNull() );
final int indx = resultSet.getInt( 2 );
assertFalse( "List index column was null", resultSet.wasNull() );
final String prodCode = resultSet.getString( 3 );
assertFalse( "Prod code column was null", resultSet.wasNull() );
valueMap.put( prodCode, indx );
}
assertEquals( 3, valueMap.size() );
assertEquals( Integer.valueOf( 0 ), valueMap.get( "abc" ) );
assertEquals( Integer.valueOf( 1 ), valueMap.get( "def" ) );
assertEquals( Integer.valueOf( 2 ), valueMap.get( "ghi" ) );
}
);
session2.delete( order );
}
);
}
@Test
public void testWriteMethodDirtying(SessionFactoryScope scope) {
ListOwner parent = new ListOwner( "root" );
ListOwner child = new ListOwner( "c1" );
parent.getChildren().add( child );
child.setParent( parent );
ListOwner otherChild = new ListOwner( "c2" );
scope.inTransaction(
session -> {
session.save( parent );
session.flush();
// at this point, the list on parent has now been replaced with a PersistentList...
PersistentList children = (PersistentList) parent.getChildren();
assertFalse( children.remove( otherChild ) );
assertFalse( children.isDirty() );
ArrayList otherCollection = new ArrayList();
otherCollection.add( child );
assertFalse( children.retainAll( otherCollection ) );
assertFalse( children.isDirty() );
otherCollection = new ArrayList();
otherCollection.add( otherChild );
assertFalse( children.removeAll( otherCollection ) );
assertFalse( children.isDirty() );
children.clear();
session.delete( child );
assertTrue( children.isDirty() );
session.flush();
children.clear();
assertFalse( children.isDirty() );
session.delete( parent );
}
);
}
}

View File

@ -0,0 +1,676 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.orm.test.collection.multisession;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.collection.internal.AbstractPersistentCollection;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Gail Badner
*/
@DomainModel(
annotatedClasses = {
MultipleSessionCollectionTest.Parent.class,
MultipleSessionCollectionTest.Child.class
}
)
@SessionFactory
public class MultipleSessionCollectionTest {
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testSaveOrUpdateOwnerWithCollectionInNewSessionBeforeFlush(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inTransaction(
s1 -> {
s1.saveOrUpdate( p );
// try to save the same entity in a new session before flushing the first session
scope.inSession(
s2 -> {
try {
s2.getTransaction().begin();
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
//expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testSaveOrUpdateOwnerWithCollectionInNewSessionAfterFlush(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inTransaction(
s1 -> {
s1.saveOrUpdate( p );
s1.flush();
// try to save the same entity in a new session after flushing the first session
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
//expected
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testSaveOrUpdateOwnerWithUninitializedCollectionInNewSession(SessionFactoryScope scope) {
Parent parent = new Parent();
scope.inTransaction(
session -> {
Child c = new Child();
parent.children.add( c );
session.persist( parent );
}
);
scope.inTransaction(
s1 -> {
Parent p = s1.get( Parent.class, parent.id );
assertFalse( Hibernate.isInitialized( p.children ) );
// try to save the same entity (with an uninitialized collection) in a new session
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
//expected
s2.getTransaction().rollback();
}
}
);
// should still be able to initialize collection, modify and commit in first session
assertFalse( Hibernate.isInitialized( p.children ) );
Hibernate.initialize( p.children );
p.children.add( new Child() );
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, parent.id );
assertEquals( 2, pGet.children.size() );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testSaveOrUpdateOwnerWithInitializedCollectionInNewSession(SessionFactoryScope scope) {
Parent parent = new Parent();
Child c = new Child();
parent.children.add( c );
scope.inTransaction(
session -> session.persist( parent )
);
scope.inTransaction(
s1 -> {
Parent p = s1.get( Parent.class, parent.id );
Hibernate.initialize( p.children );
// try to save the same entity (with an initialized collection) in a new session
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, parent.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testCopyPersistentCollectionReferenceBeforeFlush(SessionFactoryScope scope) {
Parent parent = new Parent();
Child c = new Child();
parent.children.add( c );
scope.inTransaction(
s1 -> {
s1.persist( parent );
// Copy p.children into a different Parent before flush and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = parent.children;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, parent.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testCopyPersistentCollectionReferenceAfterFlush(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inTransaction(
s1 -> {
s1.persist( p );
s1.flush();
// Copy p.children into a different Parent after flush and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testCopyUninitializedCollectionReferenceAfterGet(SessionFactoryScope scope) {
Parent parent = new Parent();
Child c = new Child();
parent.children.add( c );
scope.inTransaction(
session -> session.persist( parent )
);
scope.inTransaction(
s1 -> {
Parent p = s1.get( Parent.class, parent.id );
assertFalse( Hibernate.isInitialized( p.children ) );
// Copy p.children (uninitialized) into a different Parent and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, parent.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testCopyInitializedCollectionReferenceAfterGet(SessionFactoryScope scope) {
Parent parent = new Parent();
Child c = new Child();
parent.children.add( c );
scope.inTransaction(
session -> session.persist( parent )
);
scope.inTransaction(
s1 -> {
Parent p = s1.get( Parent.class, parent.id );
Hibernate.initialize( p.children );
// Copy p.children (initialized) into a different Parent.children and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, parent.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testCopyInitializedCollectionReferenceToNewEntityCollectionRoleAfterGet(SessionFactoryScope scope) {
Parent parent = new Parent();
Child c = new Child();
parent.children.add( c );
scope.inTransaction(
session -> session.persist( parent )
);
scope.inTransaction(
s1 -> {
Parent p = s1.get( Parent.class, parent.id );
Hibernate.initialize( p.children );
// Copy p.children (initialized) into a different Parent.oldChildren (note different collection role)
// and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.oldChildren = p.children;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
scope.inTransaction(
session -> {
Parent pGet = session.get( Parent.class, parent.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testDeleteCommitCopyToNewOwnerInNewSession(SessionFactoryScope scope) {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
scope.inTransaction(
session -> {
session.save( p1 );
session.save( p2 );
}
);
scope.inSession(
s1 -> {
s1.getTransaction().begin();
s1.delete( p1 );
s1.flush();
s1.getTransaction().commit();
// need to commit after flushing; otherwise, will get lock failure when try to move the collection below
assertNull( s1.getPersistenceContext().getEntry( p1 ) );
CollectionEntry ceChildren = s1.getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p1.children );
CollectionEntry ceNickNames = s1.getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p1.nickNames );
assertNull( ceChildren );
assertNull( ceNickNames );
assertNull( ( (AbstractPersistentCollection) p1.children ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.oldChildren ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.nickNames ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.oldNickNames ).getSession() );
// Assign the deleted collection to a different entity with same collection role (p2.nickNames)
p2.nickNames = p1.nickNames;
scope.inTransaction(
s2 -> s2.saveOrUpdate( p2 )
);
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testDeleteCommitCopyToNewOwnerNewCollectionRoleInNewSession(SessionFactoryScope scope) {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
scope.inTransaction(
session -> {
session.save( p1 );
session.save( p2 );
}
);
scope.inSession(
s1 -> {
s1.getTransaction().begin();
s1.delete( p1 );
s1.flush();
s1.getTransaction().commit();
// need to commit after flushing; otherwise, will get lock failure when try to move the collection below
assertNull( s1.getPersistenceContext().getEntry( p1 ) );
CollectionEntry ceChildren = s1.getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p1.children );
CollectionEntry ceNickNames = s1.getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p1.nickNames );
assertNull( ceChildren );
assertNull( ceNickNames );
assertNull( ( (AbstractPersistentCollection) p1.children ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.oldChildren ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.nickNames ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.oldNickNames ).getSession() );
// Assign the deleted collection to a different entity with different collection role (p2.oldNickNames)
p2.oldNickNames = p1.nickNames;
scope.inTransaction(
s2 -> s2.saveOrUpdate( p2 )
);
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testDeleteCopyToNewOwnerInNewSessionBeforeFlush(SessionFactoryScope scope) {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
scope.inTransaction(
session -> {
session.save( p1 );
session.save( p2 );
}
);
scope.inTransaction(
s1 -> {
s1.delete( p1 );
// Assign the deleted collection to a different entity with same collection role (p2.nickNames)
// before committing delete.
p2.nickNames = p1.nickNames;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p2 );
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testDeleteCopyToNewOwnerNewCollectionRoleInNewSessionBeforeFlush(SessionFactoryScope scope) {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
scope.inTransaction(
session -> {
session.save( p1 );
session.save( p2 );
}
);
scope.inTransaction(
s1 -> {
s1.delete( p1 );
// Assign the deleted collection to a different entity with different collection role (p2.oldNickNames)
// before committing delete.
p2.oldNickNames = p1.nickNames;
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p2 );
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
// expected
s2.getTransaction().rollback();
}
}
);
}
);
}
@Entity
@Table(name = "Parent")
public static class Parent {
@Id
@GeneratedValue
private Long id;
@ElementCollection
private Set<String> nickNames = new HashSet<String>();
@ElementCollection
private Set<String> oldNickNames = new HashSet<String>();
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Set<Child> children = new HashSet<Child>();
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Set<Child> oldChildren = new HashSet<Child>();
}
@Entity
@Table(name = "Child")
public static class Child {
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -0,0 +1,374 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.orm.test.collection.multisession;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.collection.internal.AbstractPersistentCollection;
import org.hibernate.collection.internal.PersistentSet;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.logger.LoggerInspectionRule;
import org.hibernate.testing.logger.Triggerable;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.Rule;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gail Badner
*/
@DomainModel(
annotatedClasses = {
MultipleSessionCollectionWarningTest.Parent.class,
MultipleSessionCollectionWarningTest.Child.class
}
)
@SessionFactory
public class MultipleSessionCollectionWarningTest {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractPersistentCollection.class );
@Rule
public LoggerInspectionRule logInspection = new LoggerInspectionRule( LOG );
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testSetCurrentSessionOverwritesNonConnectedSesssion(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inSession(
s1 -> {
s1.getTransaction().begin();
try {
s1.saveOrUpdate( p );
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = s1.getPersistenceContext()
.removeCollectionEntry( (PersistentSet) p.children );
assertNotNull( ce );
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000470:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're setting a new session when the collection already
// has a non-null session (and the collection is not "connected" to that session);
// Since s1 was not flushed, the collection role will not be known (no way to test that other than inspection).
s2.saveOrUpdate( p );
assertTrue( triggerable.wasTriggered() );
// collection's session should be overwritten with s2
assertSame( s2, ( (AbstractPersistentCollection) p.children ).getSession() );
}
finally {
s2.getTransaction().rollback();
}
}
);
}
finally {
s1.getTransaction().rollback();
}
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testSetCurrentSessionOverwritesNonConnectedSesssionFlushed(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inSession(
s1 -> {
s1.getTransaction().begin();
try {
s1.saveOrUpdate( p );
// flush the session so that p.children will contain its role
s1.flush();
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = s1.getPersistenceContext()
.removeCollectionEntry( (PersistentSet) p.children );
assertNotNull( ce );
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000470:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're setting a new session when the collection already
// has a non-null session (and the collection is not "connected" to that session);
// The collection role and key should be included in the message (no way to test that other than inspection).
s2.saveOrUpdate( p );
assertTrue( triggerable.wasTriggered() );
// collection's session should be overwritten with s2
assertSame( s2, ( (AbstractPersistentCollection) p.children ).getSession() );
}
finally {
s2.getTransaction().rollback();
}
}
);
}
finally {
s1.getTransaction().rollback();
}
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testUnsetSessionCannotOverwriteNonConnectedSesssion(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inSession(
s1 -> {
s1.getTransaction().begin();
try {
s1.saveOrUpdate( p );
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = s1.getPersistenceContext()
.removeCollectionEntry( (PersistentSet) p.children );
assertNotNull( ce );
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000471:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're unsetting a different session.
// We should not do this in practice; it is done here only to force the warning.
// Since s1 was not flushed, the collection role will not be known (no way to test that).
assertFalse( ( (PersistentCollection) p.children ).unsetSession( s2 ) );
assertTrue( triggerable.wasTriggered() );
// collection's session should still be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
}
finally {
s2.getTransaction().rollback();
}
}
);
}
finally {
s1.getTransaction().rollback();
}
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testUnsetSessionCannotOverwriteConnectedSesssion(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inSession(
s1 -> {
s1.getTransaction().begin();
try {
s1.saveOrUpdate( p );
// The collection is "connected" to s1 because it contains the CollectionEntry
CollectionEntry ce = s1.getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p.children );
assertNotNull( ce );
// the collection session should be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000471:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're unsetting a different session
// We should not do this in practice; it is done here only to force the warning.
// Since s1 was not flushed, the collection role will not be known (no way to test that).
assertFalse( ( (PersistentCollection) p.children ).unsetSession( s2 ) );
assertTrue( triggerable.wasTriggered() );
// collection's session should still be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
}
finally {
s2.getTransaction().rollback();
}
}
);
}
finally {
s1.getTransaction().rollback();
}
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testUnsetSessionCannotOverwriteConnectedSesssionFlushed(SessionFactoryScope scope) {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
scope.inSession(
s1 -> {
s1.getTransaction().begin();
try {
s1.saveOrUpdate( p );
// flush the session so that p.children will contain its role
s1.flush();
// The collection is "connected" to s1 because it contains the CollectionEntry
CollectionEntry ce = s1.getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p.children );
assertNotNull( ce );
// the collection session should be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
scope.inSession(
s2 -> {
s2.getTransaction().begin();
try {
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000471:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're unsetting a different session
// We should not do this in practice; it is done here only to force the warning.
// The collection role and key should be included in the message (no way to test that other than inspection).
assertFalse( ( (PersistentCollection) p.children ).unsetSession( s2 ) );
assertTrue( triggerable.wasTriggered() );
// collection's session should still be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
}
finally {
s2.getTransaction().rollback();
}
}
);
}
finally {
s1.getTransaction().rollback();
}
}
);
}
@Entity(name = "Parent")
@Table(name = "Parent")
public static class Parent {
@Id
@GeneratedValue
private Long id;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Set<Child> children = new HashSet<>();
}
@Entity(name = "Child")
@Table(name = "Child")
public static class Child {
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -0,0 +1,90 @@
package org.hibernate.orm.test.collection.nonInsertable;
import java.util.Arrays;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
@TestForIssue(jiraKey = "HHH-13236")
@DomainModel(
annotatedClasses = {
NonInsertableColumnTest.Parent.class,
NonInsertableColumnTest.Child.class
}
)
@SessionFactory
public class NonInsertableColumnTest {
@Test
public void test(SessionFactoryScope scope) {
Long parentId = scope.fromTransaction(
session -> {
Child child = new Child();
child.field = "Test";
child.nonInsertable = "nonInsertable";
child.nonUpdatable = "nonUpdatable";
Parent parent = new Parent();
parent.children = Arrays.asList( child );
session.persist( parent );
session.flush();
return parent.id;
}
);
scope.inSession(
session -> {
Parent loaded = session.get( Parent.class, parentId );
assertEquals( "nonUpdatable", loaded.children.get( 0 ).nonUpdatable );
assertNull( loaded.children.get( 0 ).nonInsertable );
assertEquals( "Test", loaded.children.get( 0 ).field );
assertEquals( "Test", loaded.children.get( 0 ).shadowField );
}
);
}
@Entity(name = "Parent")
public static class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
@ElementCollection
public List<Child> children;
}
@Embeddable
public static class Child {
@Column(name = "field")
public String field;
@Column(insertable = false)
public String nonInsertable;
@Column(updatable = false)
public String nonUpdatable;
@Column(name = "field", insertable = false, updatable = false)
public String shadowField;
}
}

View File

@ -4,7 +4,7 @@
* 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.collectionalias;
package org.hibernate.orm.test.collectionalias;
import java.io.Serializable;
import java.util.ArrayList;

View File

@ -0,0 +1,65 @@
/*
* 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.orm.test.collectionalias;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* @author Dave Stephan
* @author Gail Badner
*/
@DomainModel(
annotatedClasses = {
TableBId.class,
TableB.class,
TableA.class,
ATable.class
}
)
@SessionFactory
public class CollectionAliasTest {
@TestForIssue(jiraKey = "HHH-7545")
@Test
public void test(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
ATable aTable = new ATable( 1 );
TableB tableB = new TableB(
new TableBId( 1, "a", "b" )
);
aTable.getTablebs().add( tableB );
tableB.setTablea( aTable );
session.save( aTable );
}
);
scope.inSession(
session -> {
ATable aTable = (ATable) session.createQuery(
"select distinct tablea from ATable tablea LEFT JOIN FETCH tablea.tablebs " )
.uniqueResult();
assertEquals( new Integer( 1 ), aTable.getFirstId() );
assertEquals( 1, aTable.getTablebs().size() );
TableB tableB = aTable.getTablebs().get( 0 );
assertSame( aTable, tableB.getTablea() );
assertEquals( new Integer( 1 ), tableB.getId().getFirstId() );
assertEquals( "a", tableB.getId().getSecondId() );
assertEquals( "b", tableB.getId().getThirdId() );
}
);
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.orm.test.collectionalias;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* The bug fixed by HHH-7545 showed showed different results depending on the order
* in which entity mappings were processed.
*
* This mappings are in the opposite order here than in CollectionAliasTest.
*
* @Author Gail Badner
*/
@DomainModel(
annotatedClasses = {
ATable.class,
TableA.class,
TableB.class,
TableBId.class,
}
)
@SessionFactory
public class ReorderedMappingsCollectionAliasTest {
@TestForIssue(jiraKey = "HHH-7545")
@Test
public void test(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
ATable aTable = new ATable( 1 );
TableB tableB = new TableB(
new TableBId( 1, "a", "b" )
);
aTable.getTablebs().add( tableB );
tableB.setTablea( aTable );
session.save( aTable );
}
);
scope.inSession(
session -> {
ATable aTable = (ATable) session.createQuery(
"select distinct tablea from ATable tablea LEFT JOIN FETCH tablea.tablebs " )
.uniqueResult();
assertEquals( new Integer( 1 ), aTable.getFirstId() );
assertEquals( 1, aTable.getTablebs().size() );
TableB tableB = aTable.getTablebs().get( 0 );
assertSame( aTable, tableB.getTablea() );
assertEquals( new Integer( 1 ), tableB.getId().getFirstId() );
assertEquals( "a", tableB.getId().getSecondId() );
assertEquals( "b", tableB.getId().getThirdId() );
}
);
}
}

View File

@ -4,7 +4,7 @@
* 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.collectionalias;
package org.hibernate.orm.test.collectionalias;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@ -4,7 +4,7 @@
* 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.collectionalias;
package org.hibernate.orm.test.collectionalias;
import java.io.Serializable;

View File

@ -4,7 +4,7 @@
* 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.collectionalias;
package org.hibernate.orm.test.collectionalias;
import java.io.Serializable;

View File

@ -1,230 +0,0 @@
/*
* Copyright 2014 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.collection.bag;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* This template demonstrates how to develop a test case for Hibernate ORM, using its built-in unit test framework.
* Although ORMStandaloneTestCase is perfectly acceptable as a reproducer, usage of this class is much preferred.
* Since we nearly always include a regression test with bug fixes, providing your reproducer using this method
* simplifies the process.
*
* What's even better? Fork hibernate-orm itself, add your test case directly to a module's unit tests, then
* submit it as a PR!
*/
public class BagDuplicatesTest extends BaseCoreFunctionalTestCase {
// Add your entities here.
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
Parent.class,
Child.class
};
}
// If you use *.hbm.xml mappings, instead of annotations, add the mappings here.
@Override
protected String[] getMappings() {
return new String[] {
// "Foo.hbm.xml",
// "Bar.hbm.xml"
};
}
// If those mappings reside somewhere other than resources/org/hibernate/test, change this.
@Override
protected String getBaseForMappings() {
return "org/hibernate/test/";
}
// Add in any settings that are specific to your test. See resources/hibernate.properties for the defaults.
@Override
protected void configure(Configuration configuration) {
super.configure( configuration );
configuration.setProperty( AvailableSettings.SHOW_SQL, "true" );
}
// Add your tests, using standard JUnit.
@Test
public void HHH10385Test() throws Exception {
// BaseCoreFunctionalTestCase automatically creates the SessionFactory and provides the Session.
Session session = null;
Transaction transaction = null;
Long parentId = null;
try {
session = openSession();
transaction = session.beginTransaction();
Parent parent = new Parent();
session.persist(parent);
session.flush();
parentId = parent.getId();
transaction.commit();
} catch (HibernateException e) {
if (transaction != null) {
transaction.rollback();
}
fail(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
try {
session = openSession();
transaction = session.beginTransaction();
Parent parent = session.get(Parent.class, parentId);
Child child1 = new Child();
child1.setName("child1");
child1.setParent(parent);
parent.addChild(child1);
parent = (Parent) session.merge(parent);
session.flush();
//assertEquals(1, parent.getChildren().size());
transaction.commit();
} catch (HibernateException e) {
if (transaction != null) {
transaction.rollback();
}
fail(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
try {
session = openSession();
transaction = session.beginTransaction();
Parent parent = session.get(Parent.class, parentId);
assertEquals(1, parent.getChildren().size());
transaction.commit();
} catch (HibernateException e) {
if (transaction != null) {
transaction.rollback();
}
fail(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
}
@Entity(name = "Parent")
public static class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
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 removeChild(Child child) {
children.remove(child);
child.setParent(null);
}
}
@Entity(name = "Child")
public static class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne
private Parent parent;
public Child() {
}
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 + '\'' +
'}';
}
}
}

View File

@ -1,203 +0,0 @@
/*
* 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.bag;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
/**
* @author Gail Badner
*/
public class BagElementNullBasicTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
AnEntity.class,
NullableElementsEntity.class
};
}
@Test
public void testPersistNullValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
AnEntity e = new AnEntity();
e.aCollection.add( null );
session.persist( e );
return e.id;
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
session.delete( e );
}
);
}
@Test
public void addNullValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
AnEntity e = new AnEntity();
session.persist( e );
return e.id;
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
e.aCollection.add( null );
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
session.delete( e );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-13651")
public void addNullValueToNullableCollections() {
try (final Session s = sessionFactory().openSession()) {
final Transaction tx = s.beginTransaction();
NullableElementsEntity e = new NullableElementsEntity();
e.list.add( null );
s.persist( e );
s.flush();
tx.commit();
}
}
@Test
public void testUpdateNonNullValueToNull() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
session.persist( e );
return e.id;
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( entityId ).size() );
e.aCollection.set( 0, null );
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 0, e.aCollection.size() );
assertEquals( 0, getCollectionElementRows( entityId ).size() );
session.delete( e );
}
);
}
@Test
public void testUpdateNonNullValueToNullWithExtraValue() {
int entityId = doInHibernate(
this::sessionFactory, session -> {
AnEntity e = new AnEntity();
e.aCollection.add( "def" );
e.aCollection.add( "ghi" );
session.persist( e );
return e.id;
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 2, e.aCollection.size() );
assertEquals( 2, getCollectionElementRows( e.id ).size() );
e.aCollection.set( 0, null );
}
);
doInHibernate(
this::sessionFactory, session -> {
AnEntity e = session.get( AnEntity.class, entityId );
assertEquals( 1, e.aCollection.size() );
assertEquals( 1, getCollectionElementRows( e.id ).size() );
assertEquals( "ghi", e.aCollection.get( 0 ) );
session.delete( e );
}
);
}
private List getCollectionElementRows(int id) {
return doInHibernate(
this::sessionFactory, session -> {
return session.createNativeQuery(
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
).list();
}
);
}
@Entity
@Table(name="AnEntity")
public static class AnEntity {
@Id
@GeneratedValue
private int id;
@ElementCollection
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn( name = "AnEntity_id" ) })
@OrderBy
private List<String> aCollection = new ArrayList<String>();
}
@Entity
@Table(name="NullableElementsEntity")
public static class NullableElementsEntity {
@Id
@GeneratedValue
private int id;
@ElementCollection
@CollectionTable(name="e_2_string", joinColumns=@JoinColumn(name="e_id"))
@Column(name="string_value", unique = false, nullable = true, insertable = true, updatable = true)
private List<String> list = new ArrayList<String>();
}
}

View File

@ -1,112 +0,0 @@
/*
* 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.bag;
import java.util.ArrayList;
import org.hibernate.Session;
import org.hibernate.collection.internal.PersistentBag;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Tests related to operations on a PersistentBag.
*
* @author Steve Ebersole
*/
@RequiresDialectFeature(DialectChecks.SupportsNoColumnInsert.class)
public class PersistentBagTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "collection/bag/Mappings.hbm.xml" };
}
@Test
public void testWriteMethodDirtying() {
BagOwner parent = new BagOwner( "root" );
BagOwner child = new BagOwner( "c1" );
parent.getChildren().add( child );
child.setParent( parent );
BagOwner otherChild = new BagOwner( "c2" );
Session session = openSession();
session.beginTransaction();
session.save( parent );
session.flush();
// at this point, the list on parent has now been replaced with a PersistentBag...
PersistentBag children = ( PersistentBag ) parent.getChildren();
assertFalse( children.remove( otherChild ) );
assertFalse( children.isDirty() );
ArrayList otherCollection = new ArrayList();
otherCollection.add( child );
assertFalse( children.retainAll( otherCollection ) );
assertFalse( children.isDirty() );
otherCollection = new ArrayList();
otherCollection.add( otherChild );
assertFalse( children.removeAll( otherCollection ) );
assertFalse( children.isDirty() );
children.clear();
session.delete( child );
assertTrue( children.isDirty() );
session.flush();
children.clear();
assertFalse( children.isDirty() );
session.delete( parent );
session.getTransaction().commit();
session.close();
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMergePersistentEntityWithNewOneToManyElements() {
Order order = new Order();
Session s = openSession();
s.getTransaction().begin();
s.persist( order );
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
order = s.get( Order.class, order.getId() );
Item item1 = new Item();
item1.setName( "i1" );
Item item2 = new Item();
item2.setName( "i2" );
order.addItem( item1 );
order.addItem( item2 );
order = (Order) s.merge( order );
//s.flush();
s.getTransaction().commit();
s.close();
s = openSession();
s.getTransaction().begin();
order = s.get( Order.class, order.getId() );
assertEquals( 2, order.getItems().size() );
s.delete( order );
s.getTransaction().commit();
s.close();
}
}

View File

@ -1,71 +0,0 @@
/*
* 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.idbag;
import java.util.ArrayList;
import org.hibernate.Session;
import org.hibernate.collection.internal.PersistentIdentifierBag;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Tests related to operations on a PersistentIdentifierBag
*
* @author Steve Ebersole
*/
public class PersistentIdBagTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "collection/idbag/Mappings.hbm.xml" };
}
@Test
public void testWriteMethodDirtying() {
IdbagOwner parent = new IdbagOwner( "root" );
IdbagOwner child = new IdbagOwner( "c1" );
parent.getChildren().add( child );
IdbagOwner otherChild = new IdbagOwner( "c2" );
Session session = openSession();
session.beginTransaction();
session.save( parent );
session.flush();
// at this point, the list on parent has now been replaced with a PersistentBag...
PersistentIdentifierBag children = ( PersistentIdentifierBag ) parent.getChildren();
assertFalse( children.remove( otherChild ) );
assertFalse( children.isDirty() );
ArrayList otherCollection = new ArrayList();
otherCollection.add( child );
assertFalse( children.retainAll( otherCollection ) );
assertFalse( children.isDirty() );
otherCollection = new ArrayList();
otherCollection.add( otherChild );
assertFalse( children.removeAll( otherCollection ) );
assertFalse( children.isDirty() );
children.clear();
session.delete( child );
assertTrue( children.isDirty() );
session.flush();
children.clear();
assertFalse( children.isDirty() );
session.delete( parent );
session.getTransaction().commit();
session.close();
}
}

View File

@ -1,139 +0,0 @@
/*
* 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.list;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
/**
* Test initially developed for HHH-9195
* @author Steve Ebersole
*/
public class ListIndexReferenceFromListElementTest extends BaseNonConfigCoreFunctionalTestCase {
@Entity( name = "LocalOrder" )
@Table( name = "LocalOrder" )
public static class LocalOrder {
@Id
@GeneratedValue
public Integer id;
@OneToMany( mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
@OrderColumn( name = "position" )
public List<LocalLineItem> lineItems = new ArrayList<LocalLineItem>();
public LocalOrder() {
}
public LocalLineItem makeLineItem(String name) {
LocalLineItem lineItem = new LocalLineItem( name, this );
lineItems.add( lineItem );
return lineItem;
}
}
@Entity( name = "LocalLineItem" )
@Table( name = "LocalLineItem" )
public static class LocalLineItem {
@Id
@GeneratedValue
public Integer id;
public String name;
@ManyToOne
@JoinColumn
public LocalOrder order;
@Column( insertable = false, updatable = false )
public int position;
public LocalLineItem() {
}
public LocalLineItem(String name, LocalOrder order) {
this.name = name;
this.order = order;
}
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { LocalOrder.class, LocalLineItem.class };
}
@Before
public void before() {
Session s = sessionFactory().openSession();
s.beginTransaction();
LocalOrder localOrder = new LocalOrder();
localOrder.makeLineItem( "Shoes" );
localOrder.makeLineItem( "Socks" );
s.save( localOrder );
s.getTransaction().commit();
s.close();
}
@After
public void after() {
Session s = sessionFactory().openSession();
s.beginTransaction();
s.createQuery( "delete LocalLineItem" ).executeUpdate();
s.createQuery( "delete LocalOrder" ).executeUpdate();
s.getTransaction().commit();
s.close();
}
@Test
public void testIt() {
{
Session s = openSession();
s.beginTransaction();
LocalOrder order = s.byId( LocalOrder.class ).load( 1 );
assertEquals( 2, order.lineItems.size() );
LocalLineItem shoes = order.lineItems.get( 0 );
LocalLineItem socks = order.lineItems.get( 1 );
assertEquals( "Shoes", shoes.name );
assertEquals( 0, shoes.position );
assertEquals( 1, socks.position );
order.lineItems.remove( socks );
order.lineItems.add( 0, socks );
s.getTransaction().commit();
s.close();
}
{
Session s = openSession();
s.beginTransaction();
LocalOrder order = s.byId( LocalOrder.class ).load( 1 );
assertEquals( 2, order.lineItems.size() );
LocalLineItem socks = order.lineItems.get( 0 );
LocalLineItem shoes = order.lineItems.get( 1 );
assertEquals( "Shoes", shoes.name );
assertEquals( 0, socks.position );
assertEquals( 1, shoes.position );
s.getTransaction().commit();
s.close();
}
}
}

View File

@ -1,202 +0,0 @@
/*
* 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.list;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.collection.internal.PersistentList;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
/**
* Tests related to operations on a PersistentList
*
* @author Steve Ebersole
*/
public class PersistentListTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "collection/list/Mappings.hbm.xml" };
}
@Test
@TestForIssue( jiraKey = "HHH-5732" )
public void testInverseListIndex() {
// make sure no one changes the mapping
final CollectionPersister collectionPersister = sessionFactory().getCollectionPersister( ListOwner.class.getName() + ".children" );
assertTrue( collectionPersister.isInverse() );
// do some creations...
Session session = openSession();
session.beginTransaction();
ListOwner root = new ListOwner( "root" );
ListOwner child1 = new ListOwner( "c1" );
root.getChildren().add( child1 );
child1.setParent( root );
ListOwner child2 = new ListOwner( "c2" );
root.getChildren().add( child2 );
child2.setParent( root );
session.save( root );
session.getTransaction().commit();
session.close();
// now, make sure the list-index column gotten written...
final Session session2 = openSession();
session2.beginTransaction();
session2.doWork(
new Work() {
@Override
public void execute(Connection connection) throws SQLException {
final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
SimpleSelect select = new SimpleSelect( getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "NAME" )
.addColumn( "LIST_INDEX" )
.addCondition( "NAME", "<>", "?" );
PreparedStatement preparedStatement = ((SessionImplementor)session2).getJdbcCoordinator().getStatementPreparer().prepareStatement( select.toStatementString() );
preparedStatement.setString( 1, "root" );
ResultSet resultSet = ((SessionImplementor)session2).getJdbcCoordinator().getResultSetReturn().extract( preparedStatement );
Map<String, Integer> valueMap = new HashMap<String, Integer>();
while ( resultSet.next() ) {
final String name = resultSet.getString( 1 );
assertFalse( "NAME column was null", resultSet.wasNull() );
final int position = resultSet.getInt( 2 );
assertFalse( "LIST_INDEX column was null", resultSet.wasNull() );
valueMap.put( name, position );
}
assertEquals( 2, valueMap.size() );
// c1 should be list index 0
assertEquals( Integer.valueOf( 0 ), valueMap.get( "c1" ) );
// c2 should be list index 1
assertEquals( Integer.valueOf( 1 ), valueMap.get( "c2" ) );
}
}
);
session2.delete( root );
session2.getTransaction().commit();
session2.close();
}
@Test
@TestForIssue( jiraKey = "HHH-5732" )
public void testInverseListIndex2() {
// make sure no one changes the mapping
final CollectionPersister collectionPersister = sessionFactory().getCollectionPersister( Order.class.getName() + ".lineItems" );
assertTrue( collectionPersister.isInverse() );
// do some creations...
Session session = openSession();
session.beginTransaction();
Order order = new Order( "acme-1" );
order.addLineItem( "abc", 2 );
order.addLineItem( "def", 200 );
order.addLineItem( "ghi", 13 );
session.save( order );
session.getTransaction().commit();
session.close();
// now, make sure the list-index column gotten written...
final Session session2 = openSession();
session2.beginTransaction();
session2.doWork(
new Work() {
@Override
public void execute(Connection connection) throws SQLException {
final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
SimpleSelect select = new SimpleSelect( getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "ORDER_ID" )
.addColumn( "INDX" )
.addColumn( "PRD_CODE" );
PreparedStatement preparedStatement = ((SessionImplementor)session2).getJdbcCoordinator().getStatementPreparer().prepareStatement( select.toStatementString() );
ResultSet resultSet = ((SessionImplementor)session2).getJdbcCoordinator().getResultSetReturn().extract( preparedStatement );
Map<String, Integer> valueMap = new HashMap<String, Integer>();
while ( resultSet.next() ) {
final int fk = resultSet.getInt( 1 );
assertFalse( "Collection key (FK) column was null", resultSet.wasNull() );
final int indx = resultSet.getInt( 2 );
assertFalse( "List index column was null", resultSet.wasNull() );
final String prodCode = resultSet.getString( 3 );
assertFalse( "Prod code column was null", resultSet.wasNull() );
valueMap.put( prodCode, indx );
}
assertEquals( 3, valueMap.size() );
assertEquals( Integer.valueOf( 0 ), valueMap.get( "abc" ) );
assertEquals( Integer.valueOf( 1 ), valueMap.get( "def" ) );
assertEquals( Integer.valueOf( 2 ), valueMap.get( "ghi" ) );
}
}
);
session2.delete( order );
session2.getTransaction().commit();
session2.close();
}
@Test
public void testWriteMethodDirtying() {
ListOwner parent = new ListOwner( "root" );
ListOwner child = new ListOwner( "c1" );
parent.getChildren().add( child );
child.setParent( parent );
ListOwner otherChild = new ListOwner( "c2" );
Session session = openSession();
session.beginTransaction();
session.save( parent );
session.flush();
// at this point, the list on parent has now been replaced with a PersistentList...
PersistentList children = (PersistentList) parent.getChildren();
assertFalse( children.remove( otherChild ) );
assertFalse( children.isDirty() );
ArrayList otherCollection = new ArrayList();
otherCollection.add( child );
assertFalse( children.retainAll( otherCollection ) );
assertFalse( children.isDirty() );
otherCollection = new ArrayList();
otherCollection.add( otherChild );
assertFalse( children.removeAll( otherCollection ) );
assertFalse( children.isDirty() );
children.clear();
session.delete( child );
assertTrue( children.isDirty() );
session.flush();
children.clear();
assertFalse( children.isDirty() );
session.delete( parent );
session.getTransaction().commit();
session.close();
}
}

View File

@ -1,694 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.collection.multisession;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.collection.internal.AbstractPersistentCollection;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/**
* @author Gail Badner
*/
public class MultipleSessionCollectionTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testSaveOrUpdateOwnerWithCollectionInNewSessionBeforeFlush() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
// try to save the same entity in a new session before flushing the first session
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testSaveOrUpdateOwnerWithCollectionInNewSessionAfterFlush() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
s1.flush();
// try to save the same entity in a new session after flushing the first session
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testSaveOrUpdateOwnerWithUninitializedCollectionInNewSession() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s = openSession();
s.getTransaction().begin();
s.persist( p );
s.getTransaction().commit();
s.close();
Session s1 = openSession();
s1.getTransaction().begin();
p = s1.get( Parent.class, p.id );
assertFalse( Hibernate.isInitialized( p.children ) );
// try to save the same entity (with an uninitialized collection) in a new session
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to initialize collection, modify and commit in first session
assertFalse( Hibernate.isInitialized( p.children ) );
Hibernate.initialize( p.children );
p.children.add( new Child() );
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( 2, pGet.children.size());
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testSaveOrUpdateOwnerWithInitializedCollectionInNewSession() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s = openSession();
s.getTransaction().begin();
s.persist( p );
s.getTransaction().commit();
s.close();
Session s1 = openSession();
s1.getTransaction().begin();
p = s1.get( Parent.class, p.id );
Hibernate.initialize( p.children );
// try to save the same entity (with an initialized collection) in a new session
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
//
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testCopyPersistentCollectionReferenceBeforeFlush() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.persist( p );
// Copy p.children into a different Parent before flush and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testCopyPersistentCollectionReferenceAfterFlush() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.persist( p );
s1.flush();
// Copy p.children into a different Parent after flush and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testCopyUninitializedCollectionReferenceAfterGet() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s = openSession();
s.getTransaction().begin();
s.persist( p );
s.getTransaction().commit();
s.close();
Session s1 = openSession();
s1.getTransaction().begin();
p = s1.get( Parent.class, p.id );
assertFalse( Hibernate.isInitialized( p.children ) );
// Copy p.children (uninitialized) into a different Parent and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testCopyInitializedCollectionReferenceAfterGet() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s = openSession();
s.getTransaction().begin();
s.persist( p );
s.getTransaction().commit();
s.close();
Session s1 = openSession();
s1.getTransaction().begin();
p = s1.get( Parent.class, p.id );
Hibernate.initialize( p.children );
// Copy p.children (initialized) into a different Parent.children and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.children = p.children;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testCopyInitializedCollectionReferenceToNewEntityCollectionRoleAfterGet() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s = openSession();
s.getTransaction().begin();
s.persist( p );
s.getTransaction().commit();
s.close();
Session s1 = openSession();
s1.getTransaction().begin();
p = s1.get( Parent.class, p.id );
Hibernate.initialize( p.children );
// Copy p.children (initialized) into a different Parent.oldChildren (note different collection role)
// and try to save in new session.
Parent pWithSameChildren = new Parent();
pWithSameChildren.oldChildren = p.children;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( pWithSameChildren );
s2.getTransaction().commit();
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit in first session
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
Parent pGet = s1.get( Parent.class, p.id );
assertEquals( c.id, pGet.children.iterator().next().id );
session.delete( pGet );
s1.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testDeleteCommitCopyToNewOwnerInNewSession() {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
Session s1 = openSession();
s1.getTransaction().begin();
s1.save( p1 );
s1.save( p2 );
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
s1.delete( p1 );
s1.flush();
s1.getTransaction().commit();
// need to commit after flushing; otherwise, will get lock failure when try to move the collection below
assertNull( ( (SessionImplementor) s1 ).getPersistenceContext().getEntry( p1 ) );
CollectionEntry ceChildren = ( (SessionImplementor) s1 ).getPersistenceContext().getCollectionEntry( (PersistentCollection) p1.children );
CollectionEntry ceNickNames = ( (SessionImplementor) s1 ).getPersistenceContext().getCollectionEntry( (PersistentCollection) p1.nickNames );
assertNull( ceChildren );
assertNull( ceNickNames );
assertNull( ( ( AbstractPersistentCollection) p1.children ).getSession() );
assertNull( ( ( AbstractPersistentCollection) p1.oldChildren ).getSession() );
assertNull( ( ( AbstractPersistentCollection) p1.nickNames ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.oldNickNames ).getSession() );
// Assign the deleted collection to a different entity with same collection role (p2.nickNames)
p2.nickNames = p1.nickNames;
Session s2 = openSession();
s2.getTransaction().begin();
s2.saveOrUpdate( p2 );
s2.getTransaction().commit();
s2.close();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testDeleteCommitCopyToNewOwnerNewCollectionRoleInNewSession() {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
Session s1 = openSession();
s1.getTransaction().begin();
s1.save( p1 );
s1.save( p2 );
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
s1.delete( p1 );
s1.flush();
s1.getTransaction().commit();
// need to commit after flushing; otherwise, will get lock failure when try to move the collection below
assertNull( ( (SessionImplementor) s1 ).getPersistenceContext().getEntry( p1 ) );
CollectionEntry ceChildren = ( (SessionImplementor) s1 ).getPersistenceContext().getCollectionEntry( (PersistentCollection) p1.children );
CollectionEntry ceNickNames = ( (SessionImplementor) s1 ).getPersistenceContext().getCollectionEntry( (PersistentCollection) p1.nickNames );
assertNull( ceChildren );
assertNull( ceNickNames );
assertNull( ( ( AbstractPersistentCollection) p1.children ).getSession() );
assertNull( ( ( AbstractPersistentCollection) p1.oldChildren ).getSession() );
assertNull( ( ( AbstractPersistentCollection) p1.nickNames ).getSession() );
assertNull( ( (AbstractPersistentCollection) p1.oldNickNames ).getSession() );
// Assign the deleted collection to a different entity with different collection role (p2.oldNickNames)
p2.oldNickNames = p1.nickNames;
Session s2 = openSession();
s2.getTransaction().begin();
s2.saveOrUpdate( p2 );
s2.getTransaction().commit();
s2.close();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testDeleteCopyToNewOwnerInNewSessionBeforeFlush() {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
Session s1 = openSession();
s1.getTransaction().begin();
s1.save( p1 );
s1.save( p2 );
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
s1.delete( p1 );
// Assign the deleted collection to a different entity with same collection role (p2.nickNames)
// before committing delete.
p2.nickNames = p1.nickNames;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p2 );
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit the original delete
s1.getTransaction().commit();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testDeleteCopyToNewOwnerNewCollectionRoleInNewSessionBeforeFlush() {
Parent p1 = new Parent();
p1.nickNames.add( "nick" );
Parent p2 = new Parent();
Session s1 = openSession();
s1.getTransaction().begin();
s1.save( p1 );
s1.save( p2 );
s1.getTransaction().commit();
s1.close();
s1 = openSession();
s1.getTransaction().begin();
s1.delete( p1 );
// Assign the deleted collection to a different entity with different collection role (p2.oldNickNames)
// before committing delete.
p2.oldNickNames = p1.nickNames;
Session s2 = openSession();
s2.getTransaction().begin();
try {
s2.saveOrUpdate( p2 );
fail( "should have thrown HibernateException" );
}
catch (HibernateException ex) {
log.error( ex );
s2.getTransaction().rollback();
}
finally {
s2.close();
}
// should still be able to commit the original delete
s1.getTransaction().commit();
s1.close();
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[] {
Parent.class,
Child.class
};
}
@Entity
@Table(name="Parent")
public static class Parent {
@Id
@GeneratedValue
private Long id;
@ElementCollection
private Set<String> nickNames = new HashSet<String>();
@ElementCollection
private Set<String> oldNickNames = new HashSet<String>();
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Set<Child> children = new HashSet<Child>();
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Set<Child> oldChildren = new HashSet<Child>();
}
@Entity
@Table(name="Child")
public static class Child {
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -1,328 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.collection.multisession;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.junit.Rule;
import org.junit.Test;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.collection.internal.AbstractPersistentCollection;
import org.hibernate.collection.internal.PersistentSet;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.logger.LoggerInspectionRule;
import org.hibernate.testing.logger.Triggerable;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
public class MultipleSessionCollectionWarningTest extends BaseCoreFunctionalTestCase {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractPersistentCollection.class );
@Rule
public LoggerInspectionRule logInspection = new LoggerInspectionRule( LOG );
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testSetCurrentSessionOverwritesNonConnectedSesssion() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = ( (SessionImplementor) s1 ).getPersistenceContext()
.removeCollectionEntry( (PersistentSet) p.children );
assertNotNull( ce );
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000470:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're setting a new session when the collection already
// has a non-null session (and the collection is not "connected" to that session);
// Since s1 was not flushed, the collection role will not be known (no way to test that other than inspection).
s2.saveOrUpdate( p );
assertTrue( triggerable.wasTriggered() );
// collection's session should be overwritten with s2
assertSame( s2, ( (AbstractPersistentCollection) p.children ).getSession() );
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testSetCurrentSessionOverwritesNonConnectedSesssionFlushed() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
// flush the session so that p.children will contain its role
s1.flush();
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = ( (SessionImplementor) s1 ).getPersistenceContext()
.removeCollectionEntry( (PersistentSet) p.children );
assertNotNull( ce );
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000470:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're setting a new session when the collection already
// has a non-null session (and the collection is not "connected" to that session);
// The collection role and key should be included in the message (no way to test that other than inspection).
s2.saveOrUpdate( p );
assertTrue( triggerable.wasTriggered() );
// collection's session should be overwritten with s2
assertSame( s2, ( (AbstractPersistentCollection) p.children ).getSession() );
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testUnsetSessionCannotOverwriteNonConnectedSesssion() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = ( (SessionImplementor) s1 ).getPersistenceContext()
.removeCollectionEntry( (PersistentSet) p.children );
assertNotNull( ce );
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000471:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're unsetting a different session.
// We should not do this in practice; it is done here only to force the warning.
// Since s1 was not flushed, the collection role will not be known (no way to test that).
assertFalse( ( (PersistentCollection) p.children ).unsetSession( (SessionImplementor) s2 ) );
assertTrue( triggerable.wasTriggered() );
// collection's session should still be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testUnsetSessionCannotOverwriteConnectedSesssion() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
// The collection is "connected" to s1 because it contains the CollectionEntry
CollectionEntry ce = ( (SessionImplementor) s1 ).getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p.children );
assertNotNull( ce );
// the collection session should be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000471:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're unsetting a different session
// We should not do this in practice; it is done here only to force the warning.
// Since s1 was not flushed, the collection role will not be known (no way to test that).
assertFalse( ( (PersistentCollection) p.children ).unsetSession( (SessionImplementor) s2 ) );
assertTrue( triggerable.wasTriggered() );
// collection's session should still be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
@Test
@TestForIssue( jiraKey = "HHH-9518" )
public void testUnsetSessionCannotOverwriteConnectedSesssionFlushed() {
Parent p = new Parent();
Child c = new Child();
p.children.add( c );
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate( p );
// flush the session so that p.children will contain its role
s1.flush();
// The collection is "connected" to s1 because it contains the CollectionEntry
CollectionEntry ce = ( (SessionImplementor) s1 ).getPersistenceContext()
.getCollectionEntry( (PersistentCollection) p.children );
assertNotNull( ce );
// the collection session should be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages( "HHH000471:" );
assertFalse( triggerable.wasTriggered() );
// The following should trigger warning because we're unsetting a different session
// We should not do this in practice; it is done here only to force the warning.
// The collection role and key should be included in the message (no way to test that other than inspection).
assertFalse( ( (PersistentCollection) p.children ).unsetSession( (SessionImplementor) s2 ) );
assertTrue( triggerable.wasTriggered() );
// collection's session should still be s1
assertSame( s1, ( (AbstractPersistentCollection) p.children ).getSession() );
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[] {
Parent.class,
Child.class
};
}
@Entity
@Table(name="Parent")
public static class Parent {
@Id
@GeneratedValue
private Long id;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Set<Child> children = new HashSet<Child>();
}
@Entity
@Table(name="Child")
public static class Child {
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -1,108 +0,0 @@
package org.hibernate.test.collection.nonInsertable;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import javax.persistence.*;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
@TestForIssue(jiraKey = "HHH-13236")
public class NonInsertableColumnTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
Parent.class,
Child.class
};
}
@Override
protected void configure(Configuration configuration) {
super.configure( configuration );
configuration.setProperty( AvailableSettings.SHOW_SQL, "true" );
}
@Test
public void test() {
Session session = null;
Transaction transaction = null;
try {
session = openSession();
transaction = session.beginTransaction();
Child child = new Child();
child.field = "Test";
child.nonInsertable = "nonInsertable";
child.nonUpdatable = "nonUpdatable";
Parent parent = new Parent();
parent.children = Arrays.asList(child);
session.persist(parent);
session.flush();
transaction.commit();
session.clear();
Parent loaded = session.get(Parent.class, parent.id);
assertEquals("nonUpdatable", loaded.children.get(0).nonUpdatable);
assertNull(loaded.children.get(0).nonInsertable);
assertEquals("Test", loaded.children.get(0).field);
assertEquals("Test", loaded.children.get(0).shadowField);
} catch (HibernateException e) {
if (transaction != null) {
transaction.rollback();
}
fail(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
}
@Entity(name="Parent")
public static class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
@ElementCollection
public List<Child> children;
}
@Embeddable
public static class Child {
@Column(name="field")
public String field;
@Column(insertable = false)
public String nonInsertable;
@Column(updatable = false)
public String nonUpdatable;
@Column(name="field", insertable = false, updatable = false)
public String shadowField;
}
}

View File

@ -1,61 +0,0 @@
/*
* 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.collectionalias;
import org.hibernate.Session;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
/**
* @author Dave Stephan
* @author Gail Badner
*/
public class CollectionAliasTest extends BaseCoreFunctionalTestCase {
@TestForIssue( jiraKey = "HHH-7545" )
@Test
public void test() {
Session s = openSession();
s.getTransaction().begin();
ATable aTable = new ATable( 1 );
TableB tableB = new TableB(
new TableBId( 1, "a", "b" )
);
aTable.getTablebs().add( tableB );
tableB.setTablea( aTable );
s.save( aTable );
s.getTransaction().commit();
s.close();
s = openSession();
aTable = (ATable) s.createQuery( "select distinct tablea from ATable tablea LEFT JOIN FETCH tablea.tablebs " ).uniqueResult();
assertEquals( new Integer( 1 ), aTable.getFirstId() );
assertEquals( 1, aTable.getTablebs().size() );
tableB = aTable.getTablebs().get( 0 );
assertSame( aTable, tableB.getTablea() );
assertEquals( new Integer( 1 ), tableB.getId().getFirstId() );
assertEquals( "a", tableB.getId().getSecondId() );
assertEquals( "b", tableB.getId().getThirdId() );
s.close();
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
TableBId.class,
TableB.class,
TableA.class,
ATable.class
};
}
}

View File

@ -1,28 +0,0 @@
/*
* 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.collectionalias;
/**
* The bug fixed by HHH-7545 showed showed different results depending on the order
* in which entity mappings were processed.
*
* This mappings are in the opposite order here than in CollectionAliasTest.
*
* @Author Gail Badner
*/
public class ReorderedMappingsCollectionAliasTest extends CollectionAliasTest {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
ATable.class,
TableA.class,
TableB.class,
TableBId.class,
};
}
}

View File

@ -8,7 +8,6 @@ package org.hibernate.testing.orm.junit;
import org.hibernate.dialect.Dialect;
/**
* Container class for different implementation of the {@link DialectFeatureCheck} interface.
*
@ -58,6 +57,12 @@ abstract public class DialectFeatureChecks {
}
}
public static class SupportsNoColumnInsert implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsNoColumnsInsert();
}
}
public static class SupportsResultSetPositioningOnForwardOnlyCursorCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsResultSetPositionQueryMethodsOnForwardOnlyCursor();