Merge remote-tracking branch 'upstream/master' into wip/6.0_merge_48
This commit is contained in:
commit
476ffb4299
|
@ -145,7 +145,7 @@ ext {
|
|||
// EL required by Hibernate Validator at test runtime
|
||||
expression_language: "org.glassfish:javax.el:${elVersion}",
|
||||
|
||||
c3p0: "com.mchange:c3p0:0.9.5.3",
|
||||
c3p0: "com.mchange:c3p0:0.9.5.5",
|
||||
ehcache: "net.sf.ehcache:ehcache:2.10.6",
|
||||
ehcache3: "org.ehcache:ehcache:3.6.1",
|
||||
jcache: "javax.cache:cache-api:1.0.0",
|
||||
|
|
|
@ -275,6 +275,9 @@ public class H2Dialect extends Dialect {
|
|||
if ( idx > 0 ) {
|
||||
return message.substring( idx + "violation: ".length() );
|
||||
}
|
||||
if ( sqle.getSQLState().equals("23506") ) {
|
||||
return constraintName.substring( 1, constraintName.indexOf(":") );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} );
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -1832,7 +1831,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
|
||||
// INSERTED KEYS HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
private HashMap<String,List<Object>> insertedKeysMap;
|
||||
private HashMap<String,HashSet<Object>> insertedKeysMap;
|
||||
|
||||
@Override
|
||||
public void registerInsertedKey(EntityPersister persister, Object id) {
|
||||
|
@ -1842,11 +1841,10 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
insertedKeysMap = new HashMap<>();
|
||||
}
|
||||
final String rootEntityName = persister.getRootEntityName();
|
||||
List<Object> insertedEntityIds = insertedKeysMap.get( rootEntityName );
|
||||
if ( insertedEntityIds == null ) {
|
||||
insertedEntityIds = new ArrayList<>();
|
||||
insertedKeysMap.put( rootEntityName, insertedEntityIds );
|
||||
}
|
||||
HashSet<Object> insertedEntityIds = insertedKeysMap.computeIfAbsent(
|
||||
rootEntityName,
|
||||
k -> new HashSet<>()
|
||||
);
|
||||
insertedEntityIds.add( id );
|
||||
}
|
||||
}
|
||||
|
@ -1856,7 +1854,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
// again, we only really care if the entity is cached
|
||||
if ( persister.canWriteToCache() ) {
|
||||
if ( insertedKeysMap != null ) {
|
||||
final List<Object> insertedEntityIds = insertedKeysMap.get( persister.getRootEntityName() );
|
||||
final HashSet<Object> insertedEntityIds = insertedKeysMap.get( persister.getRootEntityName() );
|
||||
if ( insertedEntityIds != null ) {
|
||||
return insertedEntityIds.contains( id );
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.engine.jdbc.batch.spi.BatchKey;
|
|||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import org.hibernate.resource.jdbc.spi.JdbcObserver;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -108,20 +109,21 @@ public class BatchingBatch extends AbstractBatchImpl {
|
|||
|
||||
private void performExecution() {
|
||||
LOG.debugf( "Executing batch size: %s", batchPosition );
|
||||
final JdbcObserver observer = getJdbcCoordinator().getJdbcSessionOwner().getJdbcSessionContext().getObserver();
|
||||
try {
|
||||
for ( Map.Entry<String,PreparedStatement> entry : getStatements().entrySet() ) {
|
||||
String sql = entry.getKey();
|
||||
final String sql = entry.getKey();
|
||||
try {
|
||||
final PreparedStatement statement = entry.getValue();
|
||||
final int[] rowCounts;
|
||||
try {
|
||||
getJdbcCoordinator().getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteBatchStart();
|
||||
observer.jdbcExecuteBatchStart();
|
||||
rowCounts = statement.executeBatch();
|
||||
}
|
||||
finally {
|
||||
getJdbcCoordinator().getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteBatchEnd();
|
||||
observer.jdbcExecuteBatchEnd();
|
||||
}
|
||||
checkRowCounts( rowCounts, statement );
|
||||
checkRowCounts( rowCounts, statement, sql );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
abortBatch();
|
||||
|
@ -140,13 +142,13 @@ public class BatchingBatch extends AbstractBatchImpl {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkRowCounts(int[] rowCounts, PreparedStatement ps) throws SQLException, HibernateException {
|
||||
private void checkRowCounts(int[] rowCounts, PreparedStatement ps, String statementSQL) throws SQLException, HibernateException {
|
||||
final int numberOfRowCounts = rowCounts.length;
|
||||
if ( batchPosition != 0 && numberOfRowCounts != batchPosition / getStatements().size() ) {
|
||||
LOG.unexpectedRowCounts();
|
||||
}
|
||||
for ( int i = 0; i < numberOfRowCounts; i++ ) {
|
||||
getKey().getExpectation().verifyOutcome( rowCounts[i], ps, i );
|
||||
getKey().getExpectation().verifyOutcome( rowCounts[i], ps, i, statementSQL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,16 +40,17 @@ public class NonBatchingBatch extends AbstractBatchImpl {
|
|||
public void addToBatch() {
|
||||
notifyObserversImplicitExecution();
|
||||
for ( Map.Entry<String,PreparedStatement> entry : getStatements().entrySet() ) {
|
||||
final String statementSQL = entry.getKey();
|
||||
try {
|
||||
final PreparedStatement statement = entry.getValue();
|
||||
final int rowCount = jdbcCoordinator.getResultSetReturn().executeUpdate( statement );
|
||||
getKey().getExpectation().verifyOutcome( rowCount, statement, 0 );
|
||||
getKey().getExpectation().verifyOutcome( rowCount, statement, 0, statementSQL );
|
||||
jdbcCoordinator.getResourceRegistry().release( statement );
|
||||
jdbcCoordinator.afterStatementExecution();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
abortBatch();
|
||||
throw sqlExceptionHelper().convert( e, "could not execute non-batched batch statement", entry.getKey() );
|
||||
throw sqlExceptionHelper().convert( e, "could not execute non-batched batch statement", statementSQL );
|
||||
}
|
||||
catch (JDBCException e) {
|
||||
abortBatch();
|
||||
|
|
|
@ -1189,9 +1189,11 @@ public class ActionQueue {
|
|||
|
||||
if ( nextBatchIdentifier.hasAnyParentEntityNames( batchIdentifier ) ) {
|
||||
nextBatchIdentifier.parent = batchIdentifier;
|
||||
nextBatchIdentifier.getParentEntityNames().add( batchIdentifier.getEntityName() );
|
||||
}
|
||||
if ( batchIdentifier.hasAnyChildEntityNames( nextBatchIdentifier ) ) {
|
||||
nextBatchIdentifier.parent = batchIdentifier;
|
||||
nextBatchIdentifier.getParentEntityNames().add( batchIdentifier.getEntityName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,11 @@ public interface Expectation {
|
|||
* @param rowCount The RDBMS reported "number of rows affected".
|
||||
* @param statement The statement representing the operation
|
||||
* @param batchPosition The position in the batch (if batching)
|
||||
* @param statementSQL The SQL backing the prepared statement, for logging purposes
|
||||
* @throws SQLException Exception from the JDBC driver
|
||||
* @throws HibernateException Problem processing the outcome.
|
||||
*/
|
||||
public void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition) throws SQLException, HibernateException;
|
||||
public void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String statementSQL) throws SQLException, HibernateException;
|
||||
|
||||
/**
|
||||
* Perform any special statement preparation.
|
||||
|
|
|
@ -45,17 +45,17 @@ public class Expectations {
|
|||
}
|
||||
}
|
||||
|
||||
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition) {
|
||||
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String statementSQL) {
|
||||
rowCount = determineRowCount( rowCount, statement );
|
||||
if ( batchPosition < 0 ) {
|
||||
checkNonBatched( rowCount, statement );
|
||||
checkNonBatched( rowCount, statementSQL );
|
||||
}
|
||||
else {
|
||||
checkBatched( rowCount, batchPosition, statement );
|
||||
checkBatched( rowCount, batchPosition, statementSQL );
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBatched(int rowCount, int batchPosition, PreparedStatement statement) {
|
||||
private void checkBatched(int rowCount, int batchPosition, String statementSQL) {
|
||||
if ( rowCount == -2 ) {
|
||||
LOG.debugf( "Success of batch update unknown: %s", batchPosition );
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ public class Expectations {
|
|||
"Batch update returned unexpected row count from update ["
|
||||
+ batchPosition + "]; actual row count: " + rowCount
|
||||
+ "; expected: " + expectedRowCount + "; statement executed: "
|
||||
+ statement
|
||||
+ statementSQL
|
||||
);
|
||||
}
|
||||
if ( expectedRowCount < rowCount ) {
|
||||
|
@ -80,11 +80,11 @@ public class Expectations {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkNonBatched(int rowCount, PreparedStatement statement) {
|
||||
private void checkNonBatched(int rowCount, String statementSQL) {
|
||||
if ( expectedRowCount > rowCount ) {
|
||||
throw new StaleStateException(
|
||||
"Unexpected row count: " + rowCount + "; expected: " + expectedRowCount
|
||||
+ "; statement executed: " + statement
|
||||
+ "; statement executed: " + statementSQL
|
||||
);
|
||||
}
|
||||
if ( expectedRowCount < rowCount ) {
|
||||
|
@ -150,7 +150,7 @@ public class Expectations {
|
|||
// Various Expectation instances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Expectation NONE = new Expectation() {
|
||||
public void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition) {
|
||||
public void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String statementSQL) {
|
||||
// explicitly doAfterTransactionCompletion no checking...
|
||||
}
|
||||
|
||||
|
|
|
@ -1335,7 +1335,7 @@ public abstract class AbstractCollectionPersister
|
|||
Expectation expectation = Expectations.appropriateExpectation( getDeleteAllCheckStyle() );
|
||||
boolean callable = isDeleteAllCallable();
|
||||
boolean useBatch = expectation.canBeBatched();
|
||||
String sql = getSQLDeleteString();
|
||||
final String sql = getSQLDeleteString();
|
||||
if ( useBatch ) {
|
||||
if ( removeBatchKey == null ) {
|
||||
removeBatchKey = new BasicBatchKey(
|
||||
|
@ -1366,7 +1366,7 @@ public abstract class AbstractCollectionPersister
|
|||
.addToBatch();
|
||||
}
|
||||
else {
|
||||
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
|
||||
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1, sql );
|
||||
}
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
|
@ -1436,7 +1436,7 @@ public abstract class AbstractCollectionPersister
|
|||
final PreparedStatement st;
|
||||
boolean callable = isInsertCallable();
|
||||
boolean useBatch = expectation.canBeBatched();
|
||||
String sql = getSQLInsertRowString();
|
||||
final String sql = getSQLInsertRowString();
|
||||
|
||||
if ( useBatch ) {
|
||||
if ( recreateBatchKey == null ) {
|
||||
|
@ -1475,7 +1475,7 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
else {
|
||||
expectation.verifyOutcome( jdbcCoordinator
|
||||
.getResultSetReturn().executeUpdate( st ), st, -1 );
|
||||
.getResultSetReturn().executeUpdate( st ), st, -1, sql );
|
||||
}
|
||||
|
||||
collection.afterRowInsert( this, entry, i );
|
||||
|
@ -1552,7 +1552,7 @@ public abstract class AbstractCollectionPersister
|
|||
final PreparedStatement st;
|
||||
boolean callable = isDeleteCallable();
|
||||
boolean useBatch = expectation.canBeBatched();
|
||||
String sql = getSQLDeleteRowString();
|
||||
final String sql = getSQLDeleteRowString();
|
||||
|
||||
if ( useBatch ) {
|
||||
if ( deleteBatchKey == null ) {
|
||||
|
@ -1598,7 +1598,7 @@ public abstract class AbstractCollectionPersister
|
|||
.addToBatch();
|
||||
}
|
||||
else {
|
||||
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
|
||||
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1, sql );
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
@ -1710,7 +1710,7 @@ public abstract class AbstractCollectionPersister
|
|||
session.getJdbcCoordinator().getBatch( insertBatchKey ).addToBatch();
|
||||
}
|
||||
else {
|
||||
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 );
|
||||
expectation.verifyOutcome( session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1, sql );
|
||||
}
|
||||
collection.afterRowInsert( this, entry, i );
|
||||
count++;
|
||||
|
|
|
@ -304,7 +304,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
|
|||
expectation.verifyOutcome(
|
||||
session.getJdbcCoordinator().getResultSetReturn().executeUpdate(
|
||||
st
|
||||
), st, -1
|
||||
), st, -1, sql
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
|||
expectation.verifyOutcome(
|
||||
session.getJdbcCoordinator()
|
||||
.getResultSetReturn()
|
||||
.executeUpdate( st ), st, -1
|
||||
.executeUpdate( st ), st, -1, sql
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -373,7 +373,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
|||
deleteExpectation.verifyOutcome(
|
||||
session.getJdbcCoordinator()
|
||||
.getResultSetReturn()
|
||||
.executeUpdate( st ), st, -1
|
||||
.executeUpdate( st ), st, -1, sql
|
||||
);
|
||||
}
|
||||
count++;
|
||||
|
@ -445,7 +445,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
|||
insertExpectation.verifyOutcome(
|
||||
session.getJdbcCoordinator()
|
||||
.getResultSetReturn()
|
||||
.executeUpdate( st ), st, -1
|
||||
.executeUpdate( st ), st, -1, sql
|
||||
);
|
||||
}
|
||||
count++;
|
||||
|
|
|
@ -2736,9 +2736,10 @@ public abstract class AbstractEntityPersister
|
|||
Object id,
|
||||
int tableNumber,
|
||||
Expectation expectation,
|
||||
PreparedStatement statement) throws HibernateException {
|
||||
PreparedStatement statement,
|
||||
String statementSQL) throws HibernateException {
|
||||
try {
|
||||
expectation.verifyOutcome( rows, statement, -1 );
|
||||
expectation.verifyOutcome( rows, statement, -1, statementSQL );
|
||||
}
|
||||
catch (StaleStateException e) {
|
||||
if ( !isNullableTable( tableNumber ) ) {
|
||||
|
@ -3396,7 +3397,7 @@ public abstract class AbstractEntityPersister
|
|||
expectation.verifyOutcome(
|
||||
session.getJdbcCoordinator()
|
||||
.getResultSetReturn()
|
||||
.executeUpdate( insert ), insert, -1
|
||||
.executeUpdate( insert ), insert, -1, sql
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3595,7 +3596,8 @@ public abstract class AbstractEntityPersister
|
|||
id,
|
||||
j,
|
||||
expectation,
|
||||
update
|
||||
update,
|
||||
sql
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3720,7 +3722,8 @@ public abstract class AbstractEntityPersister
|
|||
id,
|
||||
j,
|
||||
expectation,
|
||||
delete
|
||||
delete,
|
||||
sql
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* 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.engine.spi;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.jta.TestingJtaBootstrap;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
|
||||
/*
|
||||
* @author gajendra.jatav(raaz2.gajendra@gmail.com)
|
||||
*/
|
||||
public class BatchSortingTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected void addSettings(Map settings) {
|
||||
settings.put( Environment.ORDER_INSERTS, "true" );
|
||||
settings.put( Environment.ORDER_UPDATES, "true" );
|
||||
settings.put( Environment.STATEMENT_BATCH_SIZE, "5" );
|
||||
TestingJtaBootstrap.prepare( settings );
|
||||
}
|
||||
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[]{
|
||||
GeoCountry.class, GeoDistrict.class,
|
||||
GeoDistrictDetail.class, GeoNation.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13410" )
|
||||
public void batchInsertTest() {
|
||||
|
||||
doInHibernate(this::sessionFactory, session -> {
|
||||
GeoCountry country = new GeoCountry();
|
||||
GeoDistrict geoDistrict = new GeoDistrict();
|
||||
geoDistrict.setDistrictName( "SomeDistrict" );
|
||||
GeoDistrictDetail districtDetail = new GeoDistrictDetail();
|
||||
geoDistrict.setGeoDistrictDetail( districtDetail );
|
||||
GeoNation nation = new GeoNation();
|
||||
nation.setNationName( "NationName" );
|
||||
country.setCountryName( "CountryName" );
|
||||
session.persist( country );
|
||||
List<GeoDistrict> geoDistricts = new ArrayList<>();
|
||||
geoDistrict.setCountryId( country.getId() );
|
||||
geoDistricts.add( geoDistrict );
|
||||
country.setDistricts( geoDistricts );
|
||||
session.persist( geoDistrict );
|
||||
session.persist( nation );
|
||||
});
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class GeoCountry {
|
||||
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@OneToMany( fetch = FetchType.LAZY)
|
||||
@JoinColumn( name = "COUNTRY_ID", referencedColumnName = "ID", updatable = false, insertable = false)
|
||||
private List<GeoDistrict> districts;
|
||||
|
||||
@OneToOne( fetch = FetchType.LAZY)
|
||||
@JoinColumn( name = "NATION_ID")
|
||||
private GeoNation nation;
|
||||
|
||||
private String countryName;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<GeoDistrict> getDistricts() {
|
||||
return districts;
|
||||
}
|
||||
|
||||
public void setDistricts(List<GeoDistrict> districts) {
|
||||
this.districts = districts;
|
||||
}
|
||||
|
||||
public GeoNation getNation() {
|
||||
return nation;
|
||||
}
|
||||
|
||||
public void setNation(GeoNation nation) {
|
||||
this.nation = nation;
|
||||
}
|
||||
|
||||
public String getCountryName() {
|
||||
return countryName;
|
||||
}
|
||||
|
||||
public void setCountryName(String countryName) {
|
||||
this.countryName = countryName;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class GeoDistrict {
|
||||
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String districtName;
|
||||
|
||||
@Column( name = "COUNTRY_ID")
|
||||
private Long countryId;
|
||||
|
||||
@OneToOne( fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
||||
@JoinColumn( name = "DISTRICT_DTL_ID")
|
||||
private GeoDistrictDetail geoDistrictDetail;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDistrictName() {
|
||||
return districtName;
|
||||
}
|
||||
|
||||
public void setDistrictName(String districtName) {
|
||||
this.districtName = districtName;
|
||||
}
|
||||
|
||||
public Long getCountryId() {
|
||||
return countryId;
|
||||
}
|
||||
|
||||
public void setCountryId(Long countryId) {
|
||||
this.countryId = countryId;
|
||||
}
|
||||
|
||||
public GeoDistrictDetail getGeoDistrictDetail() {
|
||||
return geoDistrictDetail;
|
||||
}
|
||||
|
||||
public void setGeoDistrictDetail(GeoDistrictDetail geoDistrictDetail) {
|
||||
this.geoDistrictDetail = geoDistrictDetail;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class GeoDistrictDetail {
|
||||
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class GeoNation {
|
||||
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@Column( name = "GOV_ID")
|
||||
private Long govId;
|
||||
|
||||
@Column( name = "TEAM_ID")
|
||||
private Long teamId;
|
||||
|
||||
private String nationName;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getGovId() {
|
||||
return govId;
|
||||
}
|
||||
|
||||
public void setGovId(Long govId) {
|
||||
this.govId = govId;
|
||||
}
|
||||
|
||||
public Long getTeamId() {
|
||||
return teamId;
|
||||
}
|
||||
|
||||
public void setTeamId(Long teamId) {
|
||||
this.teamId = teamId;
|
||||
}
|
||||
|
||||
public String getNationName() {
|
||||
return nationName;
|
||||
}
|
||||
|
||||
public void setNationName(String nationName) {
|
||||
this.nationName = nationName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -92,6 +92,7 @@ public class BatchOptimisticLockingTest extends
|
|||
}
|
||||
catch (Exception expected) {
|
||||
assertEquals( OptimisticLockException.class, expected.getClass());
|
||||
assertEquals( "Batch update returned unexpected row count from update [1]; actual row count: 0; expected: 1; statement executed: update Person set name=?, version=? where id=? and version=?", expected.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* 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.inheritance;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-14103")
|
||||
public class TransientOverrideAsPersistentJoined extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testFindByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.find( Employee.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Employee writer = session.find( Employee.class, "John Smith" );
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
final Group group = ( (Writer) writer ).getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindBySubclass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.find( Editor.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = session.find( Writer.class, "John Smith" );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final List<Employee> employees = session.createQuery( "from Employee", Employee.class )
|
||||
.getResultList();
|
||||
assertEquals( 2, employees.size() );
|
||||
assertTrue( Editor.class.isInstance( employees.get( 0 ) ) );
|
||||
assertTrue( Writer.class.isInstance( employees.get( 1 ) ) );
|
||||
final Editor editor = (Editor) employees.get( 0 );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = (Writer) employees.get( 1 );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-12981")
|
||||
public void testQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-12981")
|
||||
public void testQueryByRootClassAndOverridenPropertyTreat() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee e where treat( e as Editor ).title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee e where treat( e as Writer).title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryBySublassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.createQuery( "from Editor where title=:title", Editor.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Writer writer = session.createQuery( "from Writer where title=:title", Writer.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertNotNull( writer.getGroup() );
|
||||
assertEquals( writer.getTitle(), writer.getGroup().getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-12981")
|
||||
public void testCriteriaQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
|
||||
final CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
|
||||
final CriteriaQuery<Employee> query = builder.createQuery( Employee.class );
|
||||
final Root<Employee> root = query.from( Employee.class );
|
||||
final ParameterExpression<String> parameter = builder.parameter( String.class, "title" );
|
||||
|
||||
final Predicate predicateEditor = builder.equal(
|
||||
builder.treat( root, Editor.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateEditor );
|
||||
final Employee editor = session.createQuery( query )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Predicate predicateWriter = builder.equal(
|
||||
builder.treat( root, Writer.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateWriter );
|
||||
final Employee writer = session.createQuery( query )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Job jobEditor = new Job("Edit");
|
||||
jobEditor.setEmployee(new Editor("Jane Smith", "Senior Editor"));
|
||||
Job jobWriter= new Job("Write");
|
||||
jobWriter.setEmployee(new Writer("John Smith", new Group("Writing")));
|
||||
|
||||
Employee editor = jobEditor.getEmployee();
|
||||
Employee writer = jobWriter.getEmployee();
|
||||
Group group = Writer.class.cast( writer ).getGroup();
|
||||
|
||||
session.persist( editor );
|
||||
session.persist( group );
|
||||
session.persist( writer );
|
||||
session.persist( jobEditor );
|
||||
session.persist( jobWriter );
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.createQuery( "delete from Job" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from Group" ).executeUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Employee.class,
|
||||
Editor.class,
|
||||
Writer.class,
|
||||
Group.class,
|
||||
Job.class
|
||||
};
|
||||
}
|
||||
|
||||
@Entity(name="Employee")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@DiscriminatorColumn(name="department")
|
||||
public static abstract class Employee {
|
||||
private String name;
|
||||
private String title;
|
||||
|
||||
protected Employee(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Editor")
|
||||
public static class Editor extends Employee {
|
||||
public Editor(String name, String title) {
|
||||
super(name);
|
||||
setTitle( title );
|
||||
}
|
||||
|
||||
@Column(name = "e_title")
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Editor() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Writer")
|
||||
public static class Writer extends Employee {
|
||||
private Group group;
|
||||
|
||||
public Writer(String name, Group group) {
|
||||
super(name);
|
||||
setGroup(group);
|
||||
}
|
||||
|
||||
// Cannot have a constraint on e_title because
|
||||
// Editor#title (which uses the same e_title column) can be non-null,
|
||||
// and there is no associated group.
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Column(name = "e_title", insertable = false, updatable = false)
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Writer() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
|
||||
protected void setGroup(Group group) {
|
||||
this.group = group;
|
||||
setTitle( group.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Group")
|
||||
@Table(name = "WorkGroup")
|
||||
public static class Group {
|
||||
private String name;
|
||||
|
||||
public Group(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected Group() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Job")
|
||||
public static class Job {
|
||||
private String name;
|
||||
private Employee employee;
|
||||
|
||||
public Job(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="employee_name")
|
||||
public Employee getEmployee() {
|
||||
return employee;
|
||||
}
|
||||
|
||||
protected Job() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setEmployee(Employee e) {
|
||||
this.employee = e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* 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.inheritance;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-14103")
|
||||
public class TransientOverrideAsPersistentMappedSuperclass extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testFindByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.find( Employee.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Employee writer = session.find( Employee.class, "John Smith" );
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
final Group group = ( (Writer) writer ).getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindBySubclass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.find( Editor.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = session.find( Writer.class, "John Smith" );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final List<Employee> employees = session.createQuery( "from Employee", Employee.class )
|
||||
.getResultList();
|
||||
assertEquals( 2, employees.size() );
|
||||
assertTrue( Editor.class.isInstance( employees.get( 0 ) ) );
|
||||
assertTrue( Writer.class.isInstance( employees.get( 1 ) ) );
|
||||
final Editor editor = (Editor) employees.get( 0 );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = (Writer) employees.get( 1 );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClassAndOverridenPropertyTreat() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee e where treat( e as Editor ).title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee e where treat( e as Writer).title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryBySublassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.createQuery( "from Editor where title=:title", Editor.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Writer writer = session.createQuery( "from Writer where title=:title", Writer.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertNotNull( writer.getGroup() );
|
||||
assertEquals( writer.getTitle(), writer.getGroup().getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCriteriaQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
|
||||
final CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
|
||||
final CriteriaQuery<Employee> query = builder.createQuery( Employee.class );
|
||||
final Root<Employee> root = query.from( Employee.class );
|
||||
final ParameterExpression<String> parameter = builder.parameter( String.class, "title" );
|
||||
|
||||
final Predicate predicateEditor = builder.equal(
|
||||
builder.treat( root, Editor.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateEditor );
|
||||
final Employee editor = session.createQuery( query )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Predicate predicateWriter = builder.equal(
|
||||
builder.treat( root, Writer.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateWriter );
|
||||
final Employee writer = session.createQuery( query )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Job jobEditor = new Job("Edit");
|
||||
jobEditor.setEmployee(new Editor("Jane Smith", "Senior Editor"));
|
||||
Job jobWriter= new Job("Write");
|
||||
jobWriter.setEmployee(new Writer("John Smith", new Group("Writing")));
|
||||
|
||||
Employee editor = jobEditor.getEmployee();
|
||||
Employee writer = jobWriter.getEmployee();
|
||||
Group group = Writer.class.cast( writer ).getGroup();
|
||||
|
||||
session.persist( editor );
|
||||
session.persist( group );
|
||||
session.persist( writer );
|
||||
session.persist( jobEditor );
|
||||
session.persist( jobWriter );
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.createQuery( "delete from Job" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from Group" ).executeUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Employee.class,
|
||||
Editor.class,
|
||||
Writer.class,
|
||||
Group.class,
|
||||
Job.class
|
||||
};
|
||||
}
|
||||
|
||||
@MappedSuperclass
|
||||
public static class AbstractEmployee {
|
||||
private String title;
|
||||
|
||||
@Transient
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
protected void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name="Employee")
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name="department")
|
||||
public static abstract class Employee extends AbstractEmployee {
|
||||
private String name;
|
||||
|
||||
protected Employee(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Editor")
|
||||
public static class Editor extends Employee {
|
||||
public Editor(String name, String title) {
|
||||
super(name);
|
||||
setTitle( title );
|
||||
}
|
||||
|
||||
@Column(name = "e_title")
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Editor() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Writer")
|
||||
public static class Writer extends Employee {
|
||||
private Group group;
|
||||
|
||||
public Writer(String name, Group group) {
|
||||
super(name);
|
||||
setGroup(group);
|
||||
}
|
||||
|
||||
// Cannot have a constraint on e_title because
|
||||
// Editor#title (which uses the same e_title column) can be non-null,
|
||||
// and there is no associated group.
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Column(name = "e_title", insertable = false, updatable = false)
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Writer() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
|
||||
protected void setGroup(Group group) {
|
||||
this.group = group;
|
||||
setTitle( group.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Group")
|
||||
@Table(name = "WorkGroup")
|
||||
public static class Group {
|
||||
private String name;
|
||||
|
||||
public Group(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected Group() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Job")
|
||||
public static class Job {
|
||||
private String name;
|
||||
private Employee employee;
|
||||
|
||||
public Job(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="employee_name")
|
||||
public Employee getEmployee() {
|
||||
return employee;
|
||||
}
|
||||
|
||||
protected Job() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setEmployee(Employee e) {
|
||||
this.employee = e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* 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.inheritance;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-14103")
|
||||
public class TransientOverrideAsPersistentSingleTable extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testFindByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.find( Employee.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Employee writer = session.find( Employee.class, "John Smith" );
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
final Group group = ( (Writer) writer ).getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindBySubclass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.find( Editor.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = session.find( Writer.class, "John Smith" );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final List<Employee> employees = session.createQuery( "from Employee", Employee.class )
|
||||
.getResultList();
|
||||
assertEquals( 2, employees.size() );
|
||||
assertTrue( Editor.class.isInstance( employees.get( 0 ) ) );
|
||||
assertTrue( Writer.class.isInstance( employees.get( 1 ) ) );
|
||||
final Editor editor = (Editor) employees.get( 0 );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = (Writer) employees.get( 1 );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClassAndOverridenPropertyTreat() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee e where treat( e as Editor ).title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee e where treat( e as Writer).title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryBySublassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.createQuery( "from Editor where title=:title", Editor.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Writer writer = session.createQuery( "from Writer where title=:title", Writer.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertNotNull( writer.getGroup() );
|
||||
assertEquals( writer.getTitle(), writer.getGroup().getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCriteriaQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
|
||||
final CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
|
||||
final CriteriaQuery<Employee> query = builder.createQuery( Employee.class );
|
||||
final Root<Employee> root = query.from( Employee.class );
|
||||
final ParameterExpression<String> parameter = builder.parameter( String.class, "title" );
|
||||
|
||||
final Predicate predicateEditor = builder.equal(
|
||||
builder.treat( root, Editor.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateEditor );
|
||||
final Employee editor = session.createQuery( query )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Predicate predicateWriter = builder.equal(
|
||||
builder.treat( root, Writer.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateWriter );
|
||||
final Employee writer = session.createQuery( query )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Job jobEditor = new Job("Edit");
|
||||
jobEditor.setEmployee(new Editor("Jane Smith", "Senior Editor"));
|
||||
Job jobWriter= new Job("Write");
|
||||
jobWriter.setEmployee(new Writer("John Smith", new Group("Writing")));
|
||||
|
||||
Employee editor = jobEditor.getEmployee();
|
||||
Employee writer = jobWriter.getEmployee();
|
||||
Group group = Writer.class.cast( writer ).getGroup();
|
||||
|
||||
session.persist( editor );
|
||||
session.persist( group );
|
||||
session.persist( writer );
|
||||
session.persist( jobEditor );
|
||||
session.persist( jobWriter );
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.createQuery( "delete from Job" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from Group" ).executeUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Employee.class,
|
||||
Editor.class,
|
||||
Writer.class,
|
||||
Group.class,
|
||||
Job.class
|
||||
};
|
||||
}
|
||||
|
||||
@Entity(name="Employee")
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name="department")
|
||||
public static abstract class Employee {
|
||||
private String name;
|
||||
private String title;
|
||||
|
||||
protected Employee(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Editor")
|
||||
public static class Editor extends Employee {
|
||||
public Editor(String name, String title) {
|
||||
super(name);
|
||||
setTitle( title );
|
||||
}
|
||||
|
||||
@Column(name = "e_title")
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Editor() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Writer")
|
||||
public static class Writer extends Employee {
|
||||
private Group group;
|
||||
|
||||
public Writer(String name, Group group) {
|
||||
super(name);
|
||||
setGroup(group);
|
||||
}
|
||||
|
||||
// Cannot have a constraint on e_title because
|
||||
// Editor#title (which uses the same e_title column) can be non-null,
|
||||
// and there is no associated group.
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Column(name = "e_title", insertable = false, updatable = false)
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Writer() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
|
||||
protected void setGroup(Group group) {
|
||||
this.group = group;
|
||||
setTitle( group.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Group")
|
||||
@Table(name = "WorkGroup")
|
||||
public static class Group {
|
||||
private String name;
|
||||
|
||||
public Group(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected Group() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Job")
|
||||
public static class Job {
|
||||
private String name;
|
||||
private Employee employee;
|
||||
|
||||
public Job(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="employee_name")
|
||||
public Employee getEmployee() {
|
||||
return employee;
|
||||
}
|
||||
|
||||
protected Job() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setEmployee(Employee e) {
|
||||
this.employee = e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* 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.inheritance;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-14103")
|
||||
public class TransientOverrideAsPersistentTablePerClass extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testFindByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.find( Employee.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Employee writer = session.find( Employee.class, "John Smith" );
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
final Group group = ( (Writer) writer ).getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindBySubclass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.find( Editor.class, "Jane Smith" );
|
||||
assertNotNull( editor );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = session.find( Writer.class, "John Smith" );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
final Job jobEditor = session.find( Job.class, "Edit" );
|
||||
assertSame( editor, jobEditor.getEmployee() );
|
||||
final Job jobWriter = session.find( Job.class, "Write" );
|
||||
assertSame( writer, jobWriter.getEmployee() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClass() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final List<Employee> employees = session.createQuery( "from Employee", Employee.class )
|
||||
.getResultList();
|
||||
assertEquals( 2, employees.size() );
|
||||
assertTrue( Editor.class.isInstance( employees.get( 0 ) ) );
|
||||
assertTrue( Writer.class.isInstance( employees.get( 1 ) ) );
|
||||
final Editor editor = (Editor) employees.get( 0 );
|
||||
assertEquals( "Senior Editor", editor.getTitle() );
|
||||
final Writer writer = (Writer) employees.get( 1 );
|
||||
assertEquals( "Writing", writer.getTitle() );
|
||||
assertNotNull( writer.getGroup() );
|
||||
final Group group = writer.getGroup();
|
||||
assertEquals( writer.getTitle(), group.getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee where title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryByRootClassAndOverridenPropertyTreat() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Employee editor = session.createQuery( "from Employee e where treat( e as Editor ).title=:title", Employee.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Employee writer = session.createQuery( "from Employee e where treat( e as Writer).title=:title", Employee.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryBySublassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
final Editor editor = session.createQuery( "from Editor where title=:title", Editor.class )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Writer writer = session.createQuery( "from Writer where title=:title", Writer.class )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertNotNull( writer.getGroup() );
|
||||
assertEquals( writer.getTitle(), writer.getGroup().getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCriteriaQueryByRootClassAndOverridenProperty() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
|
||||
final CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
|
||||
final CriteriaQuery<Employee> query = builder.createQuery( Employee.class );
|
||||
final Root<Employee> root = query.from( Employee.class );
|
||||
final ParameterExpression<String> parameter = builder.parameter( String.class, "title" );
|
||||
|
||||
final Predicate predicateEditor = builder.equal(
|
||||
builder.treat( root, Editor.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateEditor );
|
||||
final Employee editor = session.createQuery( query )
|
||||
.setParameter( "title", "Senior Editor" )
|
||||
.getSingleResult();
|
||||
assertTrue( Editor.class.isInstance( editor ) );
|
||||
|
||||
final Predicate predicateWriter = builder.equal(
|
||||
builder.treat( root, Writer.class ).get( "title" ),
|
||||
parameter
|
||||
);
|
||||
query.where( predicateWriter );
|
||||
final Employee writer = session.createQuery( query )
|
||||
.setParameter( "title", "Writing" )
|
||||
.getSingleResult();
|
||||
assertTrue( Writer.class.isInstance( writer ) );
|
||||
assertNotNull( ( (Writer) writer ).getGroup() );
|
||||
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
|
||||
});
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Job jobEditor = new Job("Edit");
|
||||
jobEditor.setEmployee(new Editor("Jane Smith", "Senior Editor"));
|
||||
Job jobWriter= new Job("Write");
|
||||
jobWriter.setEmployee(new Writer("John Smith", new Group("Writing")));
|
||||
|
||||
Employee editor = jobEditor.getEmployee();
|
||||
Employee writer = jobWriter.getEmployee();
|
||||
Group group = Writer.class.cast( writer ).getGroup();
|
||||
|
||||
session.persist( editor );
|
||||
session.persist( group );
|
||||
session.persist( writer );
|
||||
session.persist( jobEditor );
|
||||
session.persist( jobWriter );
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.createQuery( "delete from Job" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
session.createQuery( "delete from Group" ).executeUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Employee.class,
|
||||
Editor.class,
|
||||
Writer.class,
|
||||
Group.class,
|
||||
Job.class
|
||||
};
|
||||
}
|
||||
|
||||
@Entity(name="Employee")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
@DiscriminatorColumn(name="department")
|
||||
public static abstract class Employee {
|
||||
private String name;
|
||||
private String title;
|
||||
|
||||
protected Employee(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
protected Employee() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Editor")
|
||||
public static class Editor extends Employee {
|
||||
public Editor(String name, String title) {
|
||||
super(name);
|
||||
setTitle( title );
|
||||
}
|
||||
|
||||
@Column(name = "e_title")
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Editor() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Writer")
|
||||
public static class Writer extends Employee {
|
||||
private Group group;
|
||||
|
||||
public Writer(String name, Group group) {
|
||||
super(name);
|
||||
setGroup(group);
|
||||
}
|
||||
|
||||
// Cannot have a constraint on e_title because
|
||||
// Editor#title (which uses the same e_title column) can be non-null,
|
||||
// and there is no associated group.
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Column(name = "e_title", insertable = false, updatable = false)
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
super.setTitle( title );
|
||||
}
|
||||
|
||||
protected Writer() {
|
||||
// this form used by Hibernate
|
||||
super();
|
||||
}
|
||||
|
||||
protected void setGroup(Group group) {
|
||||
this.group = group;
|
||||
setTitle( group.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Group")
|
||||
@Table(name = "WorkGroup")
|
||||
public static class Group {
|
||||
private String name;
|
||||
|
||||
public Group(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected Group() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Job")
|
||||
public static class Job {
|
||||
private String name;
|
||||
private Employee employee;
|
||||
|
||||
public Job(String name) {
|
||||
this();
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="employee_name")
|
||||
public Employee getEmployee() {
|
||||
return employee;
|
||||
}
|
||||
|
||||
protected Job() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setEmployee(Employee e) {
|
||||
this.employee = e;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue