/*
* 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.insertordering;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.BatchSize;
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.junit.Assert.assertEquals;
/**
* @author Vlad Mihalcea
*/
@TestForIssue(jiraKey = "HHH-9864")
public class InsertOrderingWithJoinedTableMultiLevelInheritance
extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
Address.class,
Person.class,
SpecialPerson.class,
AnotherPerson.class,
President.class,
Office.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 testBatchingAmongstSubClasses() {
doInHibernate( this::sessionFactory, session -> {
int iterations = 2;
for ( int i = 0; i < iterations; i++ ) {
final President president = new President();
president.addAddress( new Address() );
session.persist( president );
final AnotherPerson anotherPerson = new AnotherPerson();
Office office = new Office();
session.persist( office );
anotherPerson.office = office;
session.persist( anotherPerson );
final Person person = new Person();
session.persist( person );
final SpecialPerson specialPerson = new SpecialPerson();
specialPerson.addAddress( new Address() );
session.persist( specialPerson );
}
connectionProvider.clear();
} );
assertEquals( 17, connectionProvider.getPreparedStatements().size() );
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
}
@Override
protected void cleanupTestData() throws Exception {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete Address" ).executeUpdate();
session.createQuery( "delete Person" ).executeUpdate();
session.createQuery( "delete SpecialPerson" ).executeUpdate();
session.createQuery( "delete AnotherPerson" ).executeUpdate();
session.createQuery( "delete Office" ).executeUpdate();
session.createQuery( "delete President" ).executeUpdate();
} );
}
@Entity(name = "Address")
@Table(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 = "Office")
public static class Office {
@Id
@Column(name = "ID", nullable = false)
@SequenceGenerator(name = "ID", sequenceName = "ADDRESS_SEQ")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID")
private Long id;
}
@Entity(name = "Person")
@Table(name = "PERSON")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "CLASSINDICATOR", discriminatorType = DiscriminatorType.INTEGER)
public static class Person {
@Id
@Column(name = "ID", nullable = false)
@SequenceGenerator(name = "ID", sequenceName = "PERSON_SEQ")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID")
private Long id;
}
@Entity(name = "SpecialPerson")
public static class SpecialPerson extends Person {
@Column(name = "special")
private String special;
@OneToMany(orphanRemoval = true, cascade = {
CascadeType.PERSIST,
CascadeType.REMOVE
})
@JoinColumn(name = "PERSONID", referencedColumnName = "ID", nullable = false, updatable = false)
@BatchSize(size = 100)
private Set<Address> addresses = new HashSet<Address>();
public void addAddress(Address address) {
this.addresses.add( address );
}
}
@Entity(name = "AnotherPerson")
public static class AnotherPerson extends Person {
private boolean working;
@ManyToOne
private Office office;
}
@Entity(name = "President")
public static class President extends SpecialPerson {
@Column(name = "salary")
private BigDecimal salary;
}
}