Re-enabled additional tests
This commit is contained in:
parent
4806398ecc
commit
82de2b0a3f
|
@ -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 + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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
|
* @author Gail Badner
|
|
@ -10,7 +10,7 @@
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"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">
|
<class name="BagOwner">
|
||||||
<id name="name" column="NAME" type="string" />
|
<id name="name" column="NAME" type="string" />
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -15,7 +15,7 @@ import java.util.List;
|
||||||
public class Order {
|
public class Order {
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private List<Item> items = new ArrayList<Item>();
|
private List<Item> items = new ArrayList<>();
|
||||||
|
|
||||||
public Order() {
|
public Order() {
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -17,26 +17,26 @@ import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.junit.Test;
|
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.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests related to contains operations on a PersistentBag.
|
* Tests related to contains operations on a PersistentBag.
|
||||||
*
|
*
|
||||||
* @author Vlad Mihalcea
|
* @author Vlad Mihalcea
|
||||||
*/
|
*/
|
||||||
public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
@Override
|
PersistentBagContainsTest.Order.class,
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
PersistentBagContainsTest.Item.class
|
||||||
return new Class[] {
|
}
|
||||||
Order.class,
|
)
|
||||||
Item.class
|
@SessionFactory
|
||||||
};
|
public class PersistentBagContainsTest {
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test does not verify how equals is implemented for Bags,
|
* This test does not verify how equals is implemented for Bags,
|
||||||
|
@ -44,9 +44,9 @@ public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
|
||||||
* managed and detached entities.
|
* managed and detached entities.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-5409")
|
@TestForIssue(jiraKey = "HHH-5409")
|
||||||
public void testContains() {
|
public void testContains(SessionFactoryScope scope) {
|
||||||
Order _order = doInHibernate( this::sessionFactory, session -> {
|
Order _order = scope.fromTransaction( session -> {
|
||||||
Order order = new Order();
|
Order order = new Order();
|
||||||
session.persist( order );
|
session.persist( order );
|
||||||
|
|
||||||
|
@ -60,23 +60,23 @@ public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
|
||||||
return order;
|
return order;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
scope.inTransaction( session -> {
|
||||||
Item item1 = new Item();
|
Item item1 = new Item();
|
||||||
item1.setName( "i1" );
|
item1.setName( "i1" );
|
||||||
|
|
||||||
Item item2 = new Item();
|
Item item2 = new Item();
|
||||||
item2.setName( "i2" );
|
item2.setName( "i2" );
|
||||||
|
|
||||||
assertTrue(_order.getItems().contains( item1 ));
|
assertTrue( _order.getItems().contains( item1 ) );
|
||||||
assertTrue(_order.getItems().contains( item2 ));
|
assertTrue( _order.getItems().contains( item2 ) );
|
||||||
|
|
||||||
Order order = session.find( Order.class, _order.getId() );
|
Order order = session.find( Order.class, _order.getId() );
|
||||||
|
|
||||||
assertTrue(order.getItems().contains( item1 ));
|
assertTrue( order.getItems().contains( item1 ) );
|
||||||
assertTrue(order.getItems().contains( item2 ));
|
assertTrue( order.getItems().contains( item2 ) );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
scope.inTransaction( session -> {
|
||||||
Order order = session.find( Order.class, _order.getId() );
|
Order order = session.find( Order.class, _order.getId() );
|
||||||
session.delete( order );
|
session.delete( order );
|
||||||
} );
|
} );
|
||||||
|
@ -90,7 +90,7 @@ public class PersistentBagContainsTest extends BaseCoreFunctionalTestCase {
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
|
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
private List<Item> items = new ArrayList<Item>();
|
private List<Item> items = new ArrayList<>();
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,28 +21,26 @@ import org.hibernate.annotations.CollectionId;
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.Type;
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.junit.Test;
|
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.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
@DomainModel(
|
||||||
|
annotatedClasses = IdBagElementNullBasicTest.AnEntity.class
|
||||||
@Override
|
)
|
||||||
protected Class[] getAnnotatedClasses() {
|
@SessionFactory
|
||||||
return new Class[] {
|
public class IdBagElementNullBasicTest {
|
||||||
AnEntity.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPersistNullValue() {
|
public void testPersistNullValue(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
e.aCollection.add( null );
|
e.aCollection.add( null );
|
||||||
session.persist( e );
|
session.persist( e );
|
||||||
|
@ -50,49 +48,49 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addNullValue() {
|
public void addNullValue(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
session.persist( e );
|
session.persist( e );
|
||||||
return e.id;
|
return e.id;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
e.aCollection.add( null );
|
e.aCollection.add( null );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateNonNullValueToNull() {
|
public void testUpdateNonNullValueToNull(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
e.aCollection.add( "def" );
|
e.aCollection.add( "def" );
|
||||||
session.persist( e );
|
session.persist( e );
|
||||||
|
@ -100,29 +98,29 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 1, e.aCollection.size() );
|
assertEquals( 1, e.aCollection.size() );
|
||||||
assertEquals( 1, getCollectionElementRows( entityId ).size() );
|
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
|
||||||
e.aCollection.set( 0, null );
|
e.aCollection.set( 0, null );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateNonNullValueToNullWithExtraValue() {
|
public void testUpdateNonNullValueToNullWithExtraValue(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
e.aCollection.add( "def" );
|
e.aCollection.add( "def" );
|
||||||
e.aCollection.add( "ghi" );
|
e.aCollection.add( "ghi" );
|
||||||
|
@ -131,11 +129,11 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 2, e.aCollection.size() );
|
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 ) ) ) {
|
if ( "def".equals( e.aCollection.get( 0 ) ) ) {
|
||||||
e.aCollection.set( 0, null );
|
e.aCollection.set( 0, null );
|
||||||
}
|
}
|
||||||
|
@ -145,20 +143,20 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 1, e.aCollection.size() );
|
assertEquals( 1, e.aCollection.size() );
|
||||||
assertEquals( 1, getCollectionElementRows( e.id ).size() );
|
assertEquals( 1, getCollectionElementRows( e.id, scope ).size() );
|
||||||
assertEquals( "ghi", e.aCollection.get( 0 ) );
|
assertEquals( "ghi", e.aCollection.get( 0 ) );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List getCollectionElementRows(int id) {
|
private List getCollectionElementRows(int id, SessionFactoryScope scope) {
|
||||||
return doInHibernate(
|
return scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
return session.createNativeQuery(
|
return session.createNativeQuery(
|
||||||
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
|
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
|
||||||
).list();
|
).list();
|
||||||
|
@ -167,20 +165,20 @@ public class IdBagElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="AnEntity")
|
@Table(name = "AnEntity")
|
||||||
@GenericGenerator(name="increment", strategy = "increment")
|
@GenericGenerator(name = "increment", strategy = "increment")
|
||||||
public static class AnEntity {
|
public static class AnEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn( name = "AnEntity_id" ) })
|
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn(name = "AnEntity_id") })
|
||||||
@CollectionId(
|
@CollectionId(
|
||||||
columns = { @Column },
|
columns = { @Column },
|
||||||
type = @Type(type = "long"),
|
type = @Type(type = "long"),
|
||||||
generator = "increment"
|
generator = "increment"
|
||||||
)
|
)
|
||||||
private List<String> aCollection = new ArrayList<String>();
|
private List<String> aCollection = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"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">
|
<class name="IdbagOwner">
|
||||||
<id name="name" column="NAME" type="string" />
|
<id name="name" column="NAME" type="string" />
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -17,28 +17,26 @@ import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.OrderColumn;
|
import javax.persistence.OrderColumn;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.junit.Test;
|
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.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
@DomainModel(
|
||||||
|
annotatedClasses = ListElementNullBasicTest.AnEntity.class
|
||||||
@Override
|
)
|
||||||
protected Class[] getAnnotatedClasses() {
|
@SessionFactory
|
||||||
return new Class[] {
|
public class ListElementNullBasicTest {
|
||||||
AnEntity.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPersistNullValue() {
|
public void testPersistNullValue(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
e.aCollection.add( null );
|
e.aCollection.add( null );
|
||||||
session.persist( e );
|
session.persist( e );
|
||||||
|
@ -46,49 +44,49 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addNullValue() {
|
public void addNullValue(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
session.persist( e );
|
session.persist( e );
|
||||||
return e.id;
|
return e.id;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
e.aCollection.add( null );
|
e.aCollection.add( null );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateNonNullValueToNull() {
|
public void testUpdateNonNullValueToNull(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
e.aCollection.add( "def" );
|
e.aCollection.add( "def" );
|
||||||
session.persist( e );
|
session.persist( e );
|
||||||
|
@ -96,29 +94,29 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 1, e.aCollection.size() );
|
assertEquals( 1, e.aCollection.size() );
|
||||||
assertEquals( 1, getCollectionElementRows( entityId ).size() );
|
assertEquals( 1, getCollectionElementRows( entityId, scope ).size() );
|
||||||
e.aCollection.set( 0, null );
|
e.aCollection.set( 0, null );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 0, e.aCollection.size() );
|
assertEquals( 0, e.aCollection.size() );
|
||||||
assertEquals( 0, getCollectionElementRows( entityId ).size() );
|
assertEquals( 0, getCollectionElementRows( entityId, scope ).size() );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateNonNullValueToNullToNonNull() {
|
public void testUpdateNonNullValueToNullToNonNull(SessionFactoryScope scope) {
|
||||||
int entityId = doInHibernate(
|
int entityId = scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = new AnEntity();
|
AnEntity e = new AnEntity();
|
||||||
e.aCollection.add( "def" );
|
e.aCollection.add( "def" );
|
||||||
e.aCollection.add( "ghi" );
|
e.aCollection.add( "ghi" );
|
||||||
|
@ -127,29 +125,29 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 2, e.aCollection.size() );
|
assertEquals( 2, e.aCollection.size() );
|
||||||
assertEquals( 2, getCollectionElementRows( e.id ).size() );
|
assertEquals( 2, getCollectionElementRows( e.id, scope ).size() );
|
||||||
e.aCollection.set( 0, null );
|
e.aCollection.set( 0, null );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 2, e.aCollection.size() );
|
assertEquals( 2, e.aCollection.size() );
|
||||||
assertEquals( 1, getCollectionElementRows( e.id ).size() );
|
assertEquals( 1, getCollectionElementRows( e.id, scope ).size() );
|
||||||
e.aCollection.set( 0, "not null" );
|
e.aCollection.set( 0, "not null" );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
doInHibernate(
|
scope.inTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
AnEntity e = session.get( AnEntity.class, entityId );
|
AnEntity e = session.get( AnEntity.class, entityId );
|
||||||
assertEquals( 2, e.aCollection.size() );
|
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( "not null", e.aCollection.get( 0 ) );
|
||||||
assertEquals( "ghi", e.aCollection.get( 1 ) );
|
assertEquals( "ghi", e.aCollection.get( 1 ) );
|
||||||
session.delete( e );
|
session.delete( e );
|
||||||
|
@ -157,9 +155,9 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List getCollectionElementRows(int id) {
|
private List getCollectionElementRows(int id, SessionFactoryScope scope) {
|
||||||
return doInHibernate(
|
return scope.fromTransaction(
|
||||||
this::sessionFactory, session -> {
|
session -> {
|
||||||
return session.createNativeQuery(
|
return session.createNativeQuery(
|
||||||
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
|
"SELECT aCollection FROM AnEntity_aCollection where AnEntity_id = " + id
|
||||||
).list();
|
).list();
|
||||||
|
@ -168,15 +166,15 @@ public class ListElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="AnEntity")
|
@Table(name = "AnEntity")
|
||||||
public static class AnEntity {
|
public static class AnEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn( name = "AnEntity_id" ) })
|
@CollectionTable(name = "AnEntity_aCollection", joinColumns = { @JoinColumn(name = "AnEntity_id") })
|
||||||
@OrderColumn
|
@OrderColumn
|
||||||
private List<String> aCollection = new ArrayList<String>();
|
private List<String> aCollection = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"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">
|
<class name="ListOwner">
|
||||||
<id name="name" column="NAME" type="string" />
|
<id name="name" column="NAME" type="string" />
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -15,7 +15,7 @@ import java.util.List;
|
||||||
public class Order {
|
public class Order {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
private String code;
|
private String code;
|
||||||
private List<LineItem> lineItems = new ArrayList<LineItem>();
|
private List<LineItem> lineItems = new ArrayList<>();
|
||||||
|
|
||||||
public Order() {
|
public Order() {
|
||||||
}
|
}
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
|
@ -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() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.io.Serializable;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.io.Serializable;
|
||||||
|
|
|
@ -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 + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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>();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.testing.orm.junit;
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container class for different implementation of the {@link DialectFeatureCheck} interface.
|
* 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 static class SupportsResultSetPositioningOnForwardOnlyCursorCheck implements DialectFeatureCheck {
|
||||||
public boolean apply(Dialect dialect) {
|
public boolean apply(Dialect dialect) {
|
||||||
return dialect.supportsResultSetPositionQueryMethodsOnForwardOnlyCursor();
|
return dialect.supportsResultSetPositionQueryMethodsOnForwardOnlyCursor();
|
||||||
|
|
Loading…
Reference in New Issue