diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java index a34d8cd1d2..df89ea701c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java @@ -1102,9 +1102,20 @@ public class ActionQueue { */ boolean hasParent(BatchIdentifier batchIdentifier) { return ( - parent == batchIdentifier || - ( parent != null && parent.hasParent( batchIdentifier ) ) || - ( parentEntityNames.contains( batchIdentifier.getEntityName() ) ) + parent == batchIdentifier + || ( parentEntityNames.contains( batchIdentifier.getEntityName() ) ) + || parent != null && parent.hasParent( batchIdentifier, new ArrayList<>() ) + ); + } + + private boolean hasParent(BatchIdentifier batchIdentifier, List stack) { + if ( !stack.contains( this ) && parent != null ) { + stack.add( this ); + return parent.hasParent( batchIdentifier, stack ); + } + return ( + parent == batchIdentifier + || parentEntityNames.contains( batchIdentifier.getEntityName() ) ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingHasParentTest.java b/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingHasParentTest.java new file mode 100644 index 0000000000..6e2b1dab0d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/insertordering/InsertOrderingHasParentTest.java @@ -0,0 +1,134 @@ +/* + * 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.util.ArrayList; +import java.util.Arrays; +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.Id; +import javax.persistence.ManyToMany; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +import org.hibernate.cfg.Environment; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; + +/** + * @author Andrea Boriero + */ +@TestForIssue(jiraKey = "HHH-12380") +public class InsertOrderingHasParentTest extends BaseNonConfigCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Author.class, Book.class, Comment.class }; + } + + @Override + protected void addSettings(Map settings) { + settings.put( Environment.ORDER_INSERTS, "true" ); + } + + @Test + public void testInsert() { + + doInHibernate( this::sessionFactory, session -> { + Book book = new Book(); + book.setComment( new Comment( "first comment" ) ); + book.setComments( Arrays.asList( new Comment( "second comment" ) ) ); + + Author author = new Author(); + author.setBook( book ); + + session.persist( author ); + } ); + + } + + @Entity(name = "Author") + public static class Author { + @Id + @GeneratedValue + Long id; + + @OneToOne(cascade = CascadeType.ALL) + Book book; + + public Book getBook() { + return book; + } + + public void setBook(Book book) { + this.book = book; + } + } + + @Entity(name = "Book") + public static class Book { + @Id + @GeneratedValue + Long id; + + @OneToOne(cascade = CascadeType.ALL) + Comment comment; + + @ManyToMany(cascade = CascadeType.ALL) + List comments = new ArrayList<>(); + + public Comment getComment() { + return comment; + } + + public void setComment(Comment comment) { + this.comment = comment; + } + + public List getComments() { + return comments; + } + + public void setComments(List comments) { + this.comments = comments; + } + } + + @Entity(name = "Comment") @Table(name = "book_comment") + public static class Comment { + @Id + @GeneratedValue + Long id; + + @Column(name = "book_comment") + String comment; + + public Comment() { + } + + public Comment(String comment) { + this.comment = comment; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + } + +}