HHH-11005 - OneToMany generates incorrect SQL where MapKey is on superclass and using InheritanceType.JOINED

This commit is contained in:
Richard Barnes 2016-07-29 14:52:20 +01:00 committed by Vlad Mihalcea
parent 455d86307b
commit e75b017a46
14 changed files with 844 additions and 16 deletions

View File

@ -12,6 +12,7 @@ import java.util.Map;
import java.util.Random;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.InheritanceType;
import javax.persistence.MapKeyClass;
import org.hibernate.AnnotationException;
@ -30,6 +31,7 @@ import org.hibernate.cfg.CollectionPropertyHolder;
import org.hibernate.cfg.CollectionSecondPass;
import org.hibernate.cfg.Ejb3Column;
import org.hibernate.cfg.Ejb3JoinColumn;
import org.hibernate.cfg.InheritanceState;
import org.hibernate.cfg.PropertyData;
import org.hibernate.cfg.PropertyHolderBuilder;
import org.hibernate.cfg.PropertyPreloadedData;
@ -46,6 +48,7 @@ import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
@ -121,8 +124,13 @@ public class MapBinder extends CollectionBinder {
);
}
org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
// HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
InheritanceState inheritanceState = inheritanceStatePerClass.get( collType );
PersistentClass targetPropertyPersistentClass = InheritanceType.JOINED.equals( inheritanceState.getType() ) ?
mapProperty.getPersistentClass() :
associatedClass;
Value indexValue = createFormulatedValue(
mapProperty.getValue(), map, targetPropertyName, associatedClass, buildingContext
mapProperty.getValue(), map, targetPropertyName, associatedClass, targetPropertyPersistentClass, buildingContext
);
map.setIndex( indexValue );
}
@ -305,6 +313,7 @@ public class MapBinder extends CollectionBinder {
Collection collection,
String targetPropertyName,
PersistentClass associatedClass,
PersistentClass targetPropertyPersistentClass,
MetadataBuildingContext buildingContext) {
Value element = collection.getElement();
String fromAndWhere = null;
@ -322,7 +331,7 @@ public class MapBinder extends CollectionBinder {
throw new AnnotationException( "SecondaryTable JoinColumn cannot reference a non primary key" );
}
}
Iterator referencedEntityColumns;
Iterator<Selectable> referencedEntityColumns;
if ( referencedPropertyName == null ) {
referencedEntityColumns = associatedClass.getIdentifier().getColumnIterator();
}
@ -330,20 +339,23 @@ public class MapBinder extends CollectionBinder {
Property referencedProperty = associatedClass.getRecursiveProperty( referencedPropertyName );
referencedEntityColumns = referencedProperty.getColumnIterator();
}
String alias = "$alias$";
StringBuilder fromAndWhereSb = new StringBuilder( " from " )
.append( associatedClass.getTable().getName() )
//.append(" as ") //Oracle doesn't support it in subqueries
.append( " " )
.append( alias ).append( " where " );
Iterator collectionTableColumns = element.getColumnIterator();
while ( collectionTableColumns.hasNext() ) {
Column colColumn = (Column) collectionTableColumns.next();
Column refColumn = (Column) referencedEntityColumns.next();
fromAndWhereSb.append( alias ).append( '.' ).append( refColumn.getQuotedName() )
.append( '=' ).append( colColumn.getQuotedName() ).append( " and " );
fromAndWhere = getFromAndWhereFormula(
associatedClass.getTable().getName(),
element.getColumnIterator(),
referencedEntityColumns
);
}
else {
// HHH-11005 - only if we are OneToMany and location of map key property is at a different level, need to add a select
if ( !associatedClass.equals( targetPropertyPersistentClass ) ) {
fromAndWhere = getFromAndWhereFormula(
targetPropertyPersistentClass.getTable()
.getQualifiedTableName()
.toString(),
element.getColumnIterator(),
associatedClass.getIdentifier().getColumnIterator()
);
}
fromAndWhere = fromAndWhereSb.substring( 0, fromAndWhereSb.length() - 5 );
}
if ( value instanceof Component ) {
@ -368,7 +380,7 @@ public class MapBinder extends CollectionBinder {
newProperty.setSelectable( current.isSelectable() );
newProperty.setValue(
createFormulatedValue(
current.getValue(), collection, targetPropertyName, associatedClass, buildingContext
current.getValue(), collection, targetPropertyName, associatedClass, associatedClass, buildingContext
)
);
indexComponent.addProperty( newProperty );
@ -425,4 +437,27 @@ public class MapBinder extends CollectionBinder {
throw new AssertionFailure( "Unknown type encounters for map key: " + value.getClass() );
}
}
private String getFromAndWhereFormula(
String tableName,
Iterator<Selectable> collectionTableColumns,
Iterator<Selectable> referencedEntityColumns) {
String alias = "$alias$";
StringBuilder fromAndWhereSb = new StringBuilder( " from " )
.append( tableName )
//.append(" as ") //Oracle doesn't support it in subqueries
.append( " " )
.append( alias ).append( " where " );
while ( collectionTableColumns.hasNext() ) {
Column colColumn = (Column) collectionTableColumns.next();
Column refColumn = (Column) referencedEntityColumns.next();
fromAndWhereSb.append( alias )
.append( '.' )
.append( refColumn.getQuotedName() )
.append( '=' )
.append( colColumn.getQuotedName() )
.append( " and " );
}
return fromAndWhereSb.substring( 0, fromAndWhereSb.length() - 5 );
}
}

View File

@ -0,0 +1,36 @@
package org.hibernate.test.onetomany.inheritance.joined;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="BOOKTABJO")
public class Book extends Product {
private String isbn;
@ManyToOne
private Library library;
public Book() {
super();
}
public Book(String inventoryCode, String isbn) {
super(inventoryCode);
this.isbn = isbn;
}
public String getIsbn() {
return isbn;
}
public Library getLibrary() {
return library;
}
public void setLibrary(Library library) {
this.library = library;
}
}

View File

@ -0,0 +1,52 @@
package org.hibernate.test.onetomany.inheritance.joined;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="LIBRARYJO")
public class Library {
@Id
@GeneratedValue
private int entid;
@OneToMany(mappedBy="library", cascade = CascadeType.ALL)
@MapKey(name="inventoryCode")
private Map<String,Book> booksOnInventory = new HashMap<>();
@OneToMany(mappedBy="library", cascade = CascadeType.ALL)
@MapKey(name="isbn")
private Map<String,Book> booksOnIsbn = new HashMap<>();
public int getEntid() {
return entid;
}
public Map<String,Book> getBooksOnInventory() {
return booksOnInventory;
}
public Map<String, Book> getBooksOnIsbn() {
return booksOnIsbn;
}
public void addBook(Book book) {
book.setLibrary( this );
booksOnInventory.put( book.getInventoryCode(), book );
booksOnIsbn.put( book.getIsbn(), book );
}
public void removeBook(Book book) {
book.setLibrary( null );
booksOnInventory.remove( book.getInventoryCode() );
booksOnIsbn.remove( book.getIsbn() );
}
}

View File

@ -0,0 +1,142 @@
package org.hibernate.test.onetomany.inheritance.joined;
import java.util.List;
import java.util.Map.Entry;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@TestForIssue(jiraKey = "HHH-11005")
public class MappedSuperclassMapTest extends BaseNonConfigCoreFunctionalTestCase {
private static final Logger log = Logger.getLogger( MappedSuperclassMapTest.class );
private static final String SKU001 = "SKU001";
private static final String SKU002 = "SKU002";
private static final String WAR_AND_PEACE = "0140447938";
private static final String ANNA_KARENINA = "0140449175";
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{
Book.class,
Library.class,
Product.class
};
}
@Before
public void init() {
doInHibernate( this::sessionFactory, sess -> {
Book book1 = new Book( SKU001, WAR_AND_PEACE);
Book book2 = new Book( SKU002, ANNA_KARENINA);
sess.persist( book1 );
sess.flush();
sess.persist( book2 );
sess.flush();
Library library = new Library();
library.addBook( book1 );
library.addBook( book2 );
sess.persist(library);
} );
}
@Test
public void lookupEntities() {
doInHibernate( this::sessionFactory, sess -> {
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(2, library.getBooksOnInventory().size());
Book book = library.getBooksOnInventory().get( SKU001);
assertNotNull(book);
Library Library = library;
Library.getBooksOnIsbn().get( WAR_AND_PEACE );
assertEquals(WAR_AND_PEACE, book.getIsbn());
book = library.getBooksOnInventory().get(SKU002);
assertNotNull(book);
assertEquals(ANNA_KARENINA, book.getIsbn());
} );
}
@Test
public void lookupEntities_entrySet() {
doInHibernate( this::sessionFactory, sess -> {
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(2, library.getBooksOnInventory().size());
for (Entry<String,Book> entry : library.getBooksOnInventory().entrySet()) {
log.info("Found SKU " + entry.getKey() + " with ISBN " + entry.getValue().getIsbn());
}
} );
}
@Test
public void breakReferences() {
doInHibernate( this::sessionFactory, sess -> {
List<Book> books = sess.createQuery( "FROM Book").list();
assertEquals(2, books.size());
for (Book book : books) {
assertNotNull(book.getLibrary());
log.info("Found SKU " + book.getInventoryCode() + " with library " + book.getLibrary().getEntid());
}
for (Book book : books) {
book.getLibrary().removeBook( book );
}
} );
doInHibernate( this::sessionFactory, sess -> {
List<Book> books = sess.createQuery( "FROM Book").list();
assertEquals(2, books.size());
for (Book book : books) {
if (book.getLibrary() == null ) {
log.info("Found SKU " + book.getInventoryCode() + " with no library");
}
}
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(0, library.getBooksOnInventory().size());
log.info("Found Library " + library.getEntid() + " with no books");
} );
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
}
@Override
protected void cleanupTestData() throws Exception {
doInHibernate( this::sessionFactory, sess -> {
sess.createQuery( "delete from Book" ).executeUpdate();
sess.createQuery( "delete from Library" ).executeUpdate();
} );
}
@Override
protected boolean rebuildSessionFactoryOnError() {
return false;
}
}

View File

@ -0,0 +1,38 @@
package org.hibernate.test.onetomany.inheritance.joined;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="PRODTABJO")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Product {
@Id
@GeneratedValue
private int entid;
@Column(name="INVCODE")
private String inventoryCode;
public Product() {
}
public Product(String inventoryCode) {
this.inventoryCode = inventoryCode;
}
public int getEntid() {
return entid;
}
public String getInventoryCode() {
return inventoryCode;
}
}

View File

@ -0,0 +1,36 @@
package org.hibernate.test.onetomany.inheritance.perclass;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="BOOKTABPC")
public class Book extends Product {
private String isbn;
@ManyToOne(targetEntity=Library.class)
private Library library;
public Book() {
super();
}
public Book(String inventoryCode, String isbn) {
super(inventoryCode);
this.isbn = isbn;
}
public String getIsbn() {
return isbn;
}
public Library getLibrary() {
return library;
}
public void setLibrary(Library library) {
this.library = library;
}
}

View File

@ -0,0 +1,52 @@
package org.hibernate.test.onetomany.inheritance.perclass;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="LIBRARYPC")
public class Library {
@Id
@GeneratedValue
private int entid;
@OneToMany(mappedBy="library", cascade = CascadeType.ALL)
@MapKey(name="inventoryCode")
private Map<String,Book> booksOnInventory = new HashMap<>();
@OneToMany(mappedBy="library", cascade = CascadeType.ALL)
@MapKey(name="isbn")
private Map<String,Book> booksOnIsbn = new HashMap<>();
public int getEntid() {
return entid;
}
public Map<String,Book> getBooksOnInventory() {
return booksOnInventory;
}
public Map<String, Book> getBooksOnIsbn() {
return booksOnIsbn;
}
public void addBook(Book book) {
book.setLibrary( this );
booksOnInventory.put( book.getInventoryCode(), book );
booksOnIsbn.put( book.getIsbn(), book );
}
public void removeBook(Book book) {
book.setLibrary( null );
booksOnInventory.remove( book.getInventoryCode() );
booksOnIsbn.remove( book.getIsbn() );
}
}

View File

@ -0,0 +1,136 @@
package org.hibernate.test.onetomany.inheritance.perclass;
import java.util.List;
import java.util.Map.Entry;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@TestForIssue(jiraKey = "HHH-11005")
public class MappedSuperclassMapTest extends BaseNonConfigCoreFunctionalTestCase {
private static final Logger log = Logger.getLogger( MappedSuperclassMapTest.class );
private static final String SKU001 = "SKU001";
private static final String SKU002 = "SKU002";
private static final String WAR_AND_PEACE = "0140447938";
private static final String ANNA_KARENINA = "0140449175";
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{
Book.class,
Library.class,
Product.class
};
}
@Before
public void init() {
doInHibernate( this::sessionFactory, sess -> {
Library library = new Library();
library.addBook( new Book( SKU001, WAR_AND_PEACE) );
library.addBook( new Book( SKU002, ANNA_KARENINA) );
sess.persist(library);
} );
}
@Test
public void lookupEntities() {
doInHibernate( this::sessionFactory, sess -> {
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(2, library.getBooksOnInventory().size());
Book book = library.getBooksOnInventory().get( SKU001);
assertNotNull(book);
Library Library = library;
Library.getBooksOnIsbn().get( WAR_AND_PEACE );
assertEquals(WAR_AND_PEACE, book.getIsbn());
book = library.getBooksOnInventory().get(SKU002);
assertNotNull(book);
assertEquals(ANNA_KARENINA, book.getIsbn());
} );
}
@Test
public void lookupEntities_entrySet() {
doInHibernate( this::sessionFactory, sess -> {
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(2, library.getBooksOnInventory().size());
for (Entry<String,Book> entry : library.getBooksOnInventory().entrySet()) {
log.info("Found SKU " + entry.getKey() + " with ISBN " + entry.getValue().getIsbn());
}
} );
}
@Test
public void breakReferences() {
doInHibernate( this::sessionFactory, sess -> {
List<Book> books = sess.createQuery( "FROM Book").list();
assertEquals(2, books.size());
for (Book book : books) {
assertNotNull(book.getLibrary());
log.info("Found SKU " + book.getInventoryCode() + " with library " + book.getLibrary().getEntid());
}
for (Book book : books) {
book.getLibrary().removeBook( book );
}
} );
doInHibernate( this::sessionFactory, sess -> {
List<Book> books = sess.createQuery( "FROM Book").list();
assertEquals(2, books.size());
for (Book book : books) {
if (book.getLibrary() == null ) {
log.info("Found SKU " + book.getInventoryCode() + " with no library");
}
}
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(0, library.getBooksOnInventory().size());
log.info("Found Library " + library.getEntid() + " with no books");
} );
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
}
@Override
protected void cleanupTestData() throws Exception {
doInHibernate( this::sessionFactory, sess -> {
sess.createQuery( "delete from Book" ).executeUpdate();
sess.createQuery( "delete from Library" ).executeUpdate();
} );
}
@Override
protected boolean rebuildSessionFactoryOnError() {
return false;
}
}

View File

@ -0,0 +1,38 @@
package org.hibernate.test.onetomany.inheritance.perclass;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="PRODTABPC")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Product {
@Id
@GeneratedValue
private int entid;
@Column(name="INVCODE")
private String inventoryCode;
public Product() {
}
public Product(String inventoryCode) {
this.inventoryCode = inventoryCode;
}
public int getEntid() {
return entid;
}
public String getInventoryCode() {
return inventoryCode;
}
}

View File

@ -0,0 +1,35 @@
package org.hibernate.test.onetomany.inheritance.single;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
@Entity
public class Book extends Product {
private String isbn;
@ManyToOne
private Library library;
public Book() {
super();
}
public Book(String inventoryCode, String isbn) {
super(inventoryCode);
this.isbn = isbn;
}
public String getIsbn() {
return isbn;
}
public Library getLibrary() {
return library;
}
public void setLibrary(Library library) {
this.library = library;
}
}

View File

@ -0,0 +1,53 @@
package org.hibernate.test.onetomany.inheritance.single;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="INVENTORYSG")
public class Library {
@Id
@GeneratedValue
private int entid;
@OneToMany(mappedBy="library", cascade = CascadeType.ALL)
@MapKey(name="inventoryCode")
private Map<String,Book> booksOnInventory = new HashMap<>();
@OneToMany(mappedBy="library", cascade = CascadeType.ALL)
@MapKey(name="isbn")
private Map<String,Book> booksOnIsbn = new HashMap<>();
public int getEntid() {
return entid;
}
public Map<String,Book> getBooksOnInventory() {
return booksOnInventory;
}
public Map<String, Book> getBooksOnIsbn() {
return booksOnIsbn;
}
public void addBook(Book book) {
book.setLibrary( this );
booksOnInventory.put( book.getInventoryCode(), book );
booksOnIsbn.put( book.getIsbn(), book );
}
public void removeBook(Book book) {
book.setLibrary( null );
booksOnInventory.remove( book.getInventoryCode() );
booksOnIsbn.remove( book.getIsbn() );
}
}

View File

@ -0,0 +1,136 @@
package org.hibernate.test.onetomany.inheritance.single;
import java.util.List;
import java.util.Map.Entry;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@TestForIssue(jiraKey = "HHH-11005")
public class MappedSuperclassMapTest extends BaseNonConfigCoreFunctionalTestCase {
private static final Logger log = Logger.getLogger( MappedSuperclassMapTest.class );
private static final String SKU001 = "SKU001";
private static final String SKU002 = "SKU002";
private static final String WAR_AND_PEACE = "0140447938";
private static final String ANNA_KARENINA = "0140449175";
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{
Book.class,
Library.class,
Product.class
};
}
@Before
public void init() {
doInHibernate( this::sessionFactory, sess -> {
Library library = new Library();
library.addBook( new Book( SKU001, WAR_AND_PEACE) );
library.addBook( new Book( SKU002, ANNA_KARENINA) );
sess.persist(library);
} );
}
@Test
public void lookupEntities() {
doInHibernate( this::sessionFactory, sess -> {
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(2, library.getBooksOnInventory().size());
Book book = library.getBooksOnInventory().get( SKU001);
assertNotNull(book);
Library Library = library;
Library.getBooksOnIsbn().get( WAR_AND_PEACE );
assertEquals(WAR_AND_PEACE, book.getIsbn());
book = library.getBooksOnInventory().get(SKU002);
assertNotNull(book);
assertEquals(ANNA_KARENINA, book.getIsbn());
} );
}
@Test
public void lookupEntities_entrySet() {
doInHibernate( this::sessionFactory, sess -> {
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(2, library.getBooksOnInventory().size());
for (Entry<String,Book> entry : library.getBooksOnInventory().entrySet()) {
log.info("Found SKU " + entry.getKey() + " with ISBN " + entry.getValue().getIsbn());
}
} );
}
@Test
public void breakReferences() {
doInHibernate( this::sessionFactory, sess -> {
List<Book> books = sess.createQuery( "FROM Book").list();
assertEquals(2, books.size());
for (Book book : books) {
assertNotNull(book.getLibrary());
log.info("Found SKU " + book.getInventoryCode() + " with library " + book.getLibrary().getEntid());
}
for (Book book : books) {
book.getLibrary().removeBook( book );
}
} );
doInHibernate( this::sessionFactory, sess -> {
List<Book> books = sess.createQuery( "FROM Book").list();
assertEquals(2, books.size());
for (Book book : books) {
if (book.getLibrary() == null ) {
log.info("Found SKU " + book.getInventoryCode() + " with no library");
}
}
List<Library> libraries = sess.createQuery( "FROM Library").list();
assertEquals(1, libraries.size());
Library library = libraries.get( 0);
assertNotNull(library);
assertEquals(0, library.getBooksOnInventory().size());
log.info("Found Library " + library.getEntid() + " with no books");
} );
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
}
@Override
protected void cleanupTestData() throws Exception {
doInHibernate( this::sessionFactory, sess -> {
sess.createQuery( "delete from Book" ).executeUpdate();
sess.createQuery( "delete from Library" ).executeUpdate();
} );
}
@Override
protected boolean rebuildSessionFactoryOnError() {
return false;
}
}

View File

@ -0,0 +1,38 @@
package org.hibernate.test.onetomany.inheritance.single;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="PRODTABSG")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Product {
@Id
@GeneratedValue
private int entid;
@Column(name="INVCODE")
private String inventoryCode;
public Product() {
}
public Product(String inventoryCode) {
this.inventoryCode = inventoryCode;
}
public int getEntid() {
return entid;
}
public String getInventoryCode() {
return inventoryCode;
}
}

1
hibernate-orm Submodule

@ -0,0 +1 @@
Subproject commit f5a06771f77503bb72bb7c8fed11e0b9aab2fb17