From 4b672a214f84627fe872e015a87f0a4963c1947d Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Wed, 5 Jul 2017 16:24:09 +0300 Subject: [PATCH] HHH-9864 - foreign key violation with order_inserts=true and batches with mixed subclass entities Add test for @ManyToOne association --- .../InsertOrderingWithManyToOne.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingWithManyToOne.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingWithManyToOne.java b/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingWithManyToOne.java new file mode 100644 index 0000000000..bcfa2e2588 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingWithManyToOne.java @@ -0,0 +1,120 @@ +/* + * 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 . + */ +package org.hibernate.test.insertordering; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.SequenceGenerator; + +import org.hibernate.cfg.Environment; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; +import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-9864") +public class InsertOrderingWithManyToOne + extends BaseNonConfigCoreFunctionalTestCase { + + private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Address.class, Person.class }; + } + + @Override + protected void addSettings(Map settings) { + settings.put( Environment.ORDER_INSERTS, "true" ); + settings.put( Environment.STATEMENT_BATCH_SIZE, "10" ); + settings.put( + org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, + connectionProvider + ); + } + + @Override + public void releaseResources() { + super.releaseResources(); + connectionProvider.stop(); + } + + @Test + public void testBatching() throws SQLException { + doInHibernate( this::sessionFactory, session -> { + Person father = new Person(); + Person mother = new Person(); + Person son = new Person(); + Person daughter = new Person(); + + Address home = new Address(); + Address office = new Address(); + + father.address = home; + son.address = home; + mother.address = office; + daughter.address = office; + + session.persist( home ); + session.persist( office ); + + session.persist( father ); + session.persist( mother ); + session.persist( son ); + session.persist( daughter ); + + connectionProvider.clear(); + } ); + + PreparedStatement addressPreparedStatement = connectionProvider.getPreparedStatement( + "insert into Address (ID) values (?)" ); + verify( addressPreparedStatement, times( 2 ) ).addBatch(); + PreparedStatement personPreparedStatement = connectionProvider.getPreparedStatement( + "insert into Person (address_ID, ID) values (?, ?)" ); + verify( personPreparedStatement, times( 4 ) ).addBatch(); + } + + @Entity(name = "Address") + public static class Address { + @Id + @Column(name = "ID", nullable = false) + @SequenceGenerator(name = "ID", sequenceName = "ADDRESS_SEQ") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID") + private Long id; + } + + @Entity(name = "Person") + public static class Person { + @Id + @Column(name = "ID", nullable = false) + @SequenceGenerator(name = "ID", sequenceName = "ADDRESS_SEQ") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID") + private Long id; + + @ManyToOne + private Address address; + } +}