Merge remote-tracking branch 'upstream/master' into wip/6.0

This commit is contained in:
Andrea Boriero 2020-10-02 12:39:41 +01:00
commit 0bd2c32f76
22 changed files with 300 additions and 49 deletions

View File

@ -621,6 +621,9 @@ Write all SQL statements to the console. This is an alternative to setting the l
`*hibernate.format_sql*` (e.g. `true` or `false` (default value))::
Pretty-print the SQL in the log and console.
`*hibernate.highlight_sql*` (e.g. `true` or `false` (default value))::
Colorize the SQL in the console using ANSI escape codes.
`*hibernate.use_sql_comments*` (e.g. `true` or `false` (default value))::
If true, Hibernate generates comments inside the SQL, for easier debugging.

View File

@ -124,7 +124,7 @@ ext {
h2: "com.h2database:h2:${h2Version}",
hsqldb: "org.hsqldb:hsqldb:2.3.2",
derby: "org.apache.derby:derby:10.11.1.1",
postgresql: 'org.postgresql:postgresql:42.2.2',
postgresql: 'org.postgresql:postgresql:42.2.16',
mysql: 'mysql:mysql-connector-java:8.0.17',
mariadb: 'org.mariadb.jdbc:mariadb-java-client:2.2.3',
cockroachdb: 'org.postgresql:postgresql:42.2.8',

View File

@ -202,6 +202,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private boolean orderInsertsEnabled;
private boolean postInsertIdentifierDelayed;
private boolean enhancementAsProxyEnabled;
private boolean collectionsInDefaultFetchGroupEnabled;
// JPA callbacks
private boolean callbacksEnabled;
@ -1182,6 +1183,11 @@ public boolean isEnhancementAsProxyEnabled() {
return enhancementAsProxyEnabled;
}
@Override
public boolean isCollectionsInDefaultFetchGroupEnabled() {
return collectionsInDefaultFetchGroupEnabled;
}
@Override
public boolean isOmitJoinOfSuperclassTablesEnabled() {
return omitJoinOfSuperclassTablesEnabled;
@ -1486,6 +1492,11 @@ public void enableGeneratorNameScopeCompliance(boolean enabled) {
mutableJpaCompliance().setGeneratorNameScopeCompliance( enabled );
}
public void enableCollectionInDefaultFetchGroup(boolean enabled) {
this.collectionsInDefaultFetchGroupEnabled = enabled;
}
public void disableRefreshDetachedEntity() {
this.allowRefreshDetachedEntity = false;
}

View File

@ -459,6 +459,11 @@ public boolean isEnhancementAsProxyEnabled() {
return delegate.isEnhancementAsProxyEnabled();
}
@Override
public boolean isCollectionsInDefaultFetchGroupEnabled() {
return delegate.isCollectionsInDefaultFetchGroupEnabled();
}
@Override
public boolean isUseOfJdbcNamedParametersEnabled() {
return delegate().isUseOfJdbcNamedParametersEnabled();

View File

@ -348,5 +348,9 @@ default boolean isEnhancementAsProxyEnabled() {
*/
boolean isUseOfJdbcNamedParametersEnabled();
default boolean isCollectionsInDefaultFetchGroupEnabled() {
return false;
}
boolean isOmitJoinOfSuperclassTablesEnabled();
}

View File

@ -15,6 +15,7 @@
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.ToOne;
@ -30,7 +31,8 @@ public class EnhancementHelper {
public static boolean includeInBaseFetchGroup(
Property bootMapping,
boolean isEnhanced,
boolean allowEnhancementAsProxy) {
boolean allowEnhancementAsProxy,
boolean collectionsInDefaultFetchGroupEnabled) {
final Value value = bootMapping.getValue();
if ( ! isEnhanced ) {
@ -63,7 +65,8 @@ public static boolean includeInBaseFetchGroup(
return true;
}
return ! bootMapping.isLazy();
return collectionsInDefaultFetchGroupEnabled && ( value instanceof Collection )
|| ! bootMapping.isLazy();
}
public static <T> T performWork(

View File

@ -34,7 +34,8 @@ public class LazyAttributesMetadata implements Serializable {
public static LazyAttributesMetadata from(
PersistentClass mappedEntity,
boolean isEnhanced,
boolean allowEnhancementAsProxy) {
boolean allowEnhancementAsProxy,
boolean collectionsInDefaultFetchGroupEnabled) {
final Map<String, LazyAttributeDescriptor> lazyAttributeDescriptorMap = new LinkedHashMap<>();
final Map<String, Set<String>> fetchGroupToAttributesMap = new HashMap<>();
@ -47,7 +48,8 @@ public static LazyAttributesMetadata from(
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
property,
isEnhanced,
allowEnhancementAsProxy
allowEnhancementAsProxy,
collectionsInDefaultFetchGroupEnabled
);
if ( lazy ) {
final LazyAttributeDescriptor lazyAttributeDescriptor = LazyAttributeDescriptor.from( property, i, x++ );

View File

@ -731,6 +731,11 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
*/
String FORMAT_SQL ="hibernate.format_sql";
/**
* Enable highlighting of SQL logged to the console using ANSI escape codes
*/
String HIGHLIGHT_SQL ="hibernate.highlight_sql";
/**
* Add comments to the generated SQL
*/

View File

@ -190,6 +190,11 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
.register();
}
@Override
public String[] getDropSchemaCommand(String schemaName) {
return new String[] {"drop schema " + schemaName + " restrict"};
}
/**
* Since we're using {@code seconds_between()} and
* {@code add_seconds()}, it makes sense to use
@ -626,6 +631,7 @@ public boolean supportsNullPrecedence() {
* if expression has not been explicitly specified.
* @param nullPrecedence Nulls precedence. Default value: {@link NullPrecedence#NONE}.
*
* @return SQL string.
*/
@Override
public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nullPrecedence) {

View File

@ -15,7 +15,7 @@
*
* @author Steve Ebersole
*/
public class AnsiSqlKeywords {
public final class AnsiSqlKeywords {
/**
* Singleton access
*/
@ -23,7 +23,7 @@ public class AnsiSqlKeywords {
private final Set<String> keywordsSql2003;
public AnsiSqlKeywords() {
private AnsiSqlKeywords() {
final Set<String> keywordsSql2003 = new HashSet<>();
keywordsSql2003.add( "ADD" );
keywordsSql2003.add( "ALL" );
@ -281,5 +281,4 @@ public Set<String> sql2003() {
return keywordsSql2003;
}
}

View File

@ -20,6 +20,10 @@ public enum FormatStyle {
* Formatting for DDL (CREATE, ALTER, DROP, etc) statements
*/
DDL( "ddl", DDLFormatterImpl.INSTANCE ),
/**
* Syntax highlighting via ANSI escape codes
*/
HIGHLIGHT( "highlight", HighlightingFormatter.INSTANCE ),
/**
* No formatting
*/

View File

@ -0,0 +1,106 @@
/*
* 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.jdbc.internal;
import org.hibernate.engine.jdbc.env.spi.AnsiSqlKeywords;
import org.hibernate.internal.util.StringHelper;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
/**
* Performs basic syntax highlighting for SQL using ANSI escape codes.
*
* @author Gavin King
*/
public final class HighlightingFormatter implements Formatter {
private static final Set<String> KEYWORDS = new HashSet<>( AnsiSqlKeywords.INSTANCE.sql2003() );
static {
// additional keywords not reserved by ANSI SQL 2003
KEYWORDS.addAll( Arrays.asList( "KEY", "SEQUENCE", "CASCADE", "INCREMENT" ) );
}
public static final Formatter INSTANCE =
new HighlightingFormatter(
"34", // blue
"36", // cyan
"32"
);
private static final String SYMBOLS_AND_WS = "=><!+-*/()',.|&`\"?" + StringHelper.WHITESPACE;
private static String escape(String code) {
return "\u001b[" + code + "m";
};
private final String keywordEscape;
private final String stringEscape;
private final String quotedEscape;
private final String normalEscape;
/**
* @param keywordCode the ANSI escape code to use for highlighting SQL keywords
* @param stringCode the ANSI escape code to use for highlighting SQL strings
*/
public HighlightingFormatter(String keywordCode, String stringCode, String quotedCode) {
keywordEscape =escape( keywordCode );
stringEscape = escape( stringCode );
quotedEscape = escape( quotedCode );
normalEscape = escape( "0" );
}
@Override
public String format(String sql) {
StringBuilder result = new StringBuilder();
boolean inString = false;
boolean inQuoted = false;
for ( StringTokenizer tokenizer = new StringTokenizer( sql, SYMBOLS_AND_WS, true );
tokenizer.hasMoreTokens(); ) {
String token = tokenizer.nextToken();
switch ( token ) {
case "\"":
case "`": // for MySQL
if ( inString ) {
result.append( token );
}
else if ( inQuoted ) {
inQuoted = false;
result.append( token ).append( normalEscape );
}
else {
inQuoted = true;
result.append( quotedEscape ).append( token );
}
break;
case "'":
if ( inQuoted ) {
result.append( '\'' );
}
else if ( inString ) {
inString = false;
result.append( '\'' ).append( normalEscape );
}
else {
inString = true;
result.append( stringEscape ).append( '\'' );
}
break;
default:
if ( KEYWORDS.contains( token.toUpperCase() ) ) {
result.append( keywordEscape ).append( token ).append( normalEscape );
}
else {
result.append( token );
}
}
}
return result.toString();
}
}

View File

@ -55,9 +55,10 @@ public void configure(Map configValues) {
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
final boolean highlightSQL = ConfigurationHelper.getBoolean( Environment.HIGHLIGHT_SQL, configValues, false );
final long logSlowQuery = ConfigurationHelper.getLong( Environment.LOG_SLOW_QUERY, configValues, 0 );
this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL, logSlowQuery );
this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL, highlightSQL, logSlowQuery );
resultSetWrapper = new ResultSetWrapperImpl( serviceRegistry );
}

View File

@ -6,16 +6,15 @@
*/
package org.hibernate.engine.jdbc.spi;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.internal.Formatter;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.build.AllowSysOut;
import org.jboss.logging.Logger;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
/**
* Centralize logging for SQL statements.
*
@ -27,6 +26,7 @@ public class SqlStatementLogger {
private boolean logToStdout;
private boolean format;
private final boolean highlight;
/**
* Configuration value that indicates slow query. (In milliseconds) 0 - disabled.
@ -37,29 +37,42 @@ public class SqlStatementLogger {
* Constructs a new SqlStatementLogger instance.
*/
public SqlStatementLogger() {
this( false, false );
this( false, false, false );
}
/**
* Constructs a new SqlStatementLogger instance.
*
* @param logToStdout Should we log to STDOUT in addition to our internal logger.
* @param format Should we format the statements prior to logging
* @param format Should we format the statements in the console and log
*/
public SqlStatementLogger(boolean logToStdout, boolean format) {
this( logToStdout, format, 0 );
this( logToStdout, format, false );
}
/**
* Constructs a new SqlStatementLogger instance.
*
* @param logToStdout Should we log to STDOUT in addition to our internal logger.
* @param format Should we format the statements prior to logging
* @param format Should we format the statements in the console and log
* @param highlight Should we highlight the statements in the console
*/
public SqlStatementLogger(boolean logToStdout, boolean format, boolean highlight) {
this( logToStdout, format, highlight, 0 );
}
/**
* Constructs a new SqlStatementLogger instance.
*
* @param logToStdout Should we log to STDOUT in addition to our internal logger.
* @param format Should we format the statements in the console and log
* @param highlight Should we highlight the statements in the console
* @param logSlowQuery Should we logs query which executed slower than specified milliseconds. 0 - disabled.
*/
public SqlStatementLogger(boolean logToStdout, boolean format, long logSlowQuery) {
public SqlStatementLogger(boolean logToStdout, boolean format, boolean highlight, long logSlowQuery) {
this.logToStdout = logToStdout;
this.format = format;
this.highlight = highlight;
this.logSlowQuery = logSlowQuery;
}
@ -120,14 +133,18 @@ public void logStatement(String statement) {
*/
@AllowSysOut
public void logStatement(String statement, Formatter formatter) {
if ( format ) {
if ( logToStdout || LOG.isDebugEnabled() ) {
if ( logToStdout || LOG.isDebugEnabled() ) {
if ( format ) {
statement = formatter.format( statement );
}
if ( highlight ) {
statement = FormatStyle.HIGHLIGHT.getFormatter().format( statement );
}
}
LOG.debug( statement );
if ( logToStdout ) {
System.out.println( "Hibernate: " + statement );
String prefix = highlight ? "\u001b[35m[Hibernate]\u001b[0m " : "Hibernate: ";
System.out.println( prefix + statement );
}
}

View File

@ -1180,7 +1180,7 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
if ( prevBatchIdentifier.hasAnyParentEntityNames( batchIdentifier ) ) {
prevBatchIdentifier.parent = batchIdentifier;
}
if ( batchIdentifier.hasAnyChildEntityNames( prevBatchIdentifier ) ) {
else if ( batchIdentifier.hasAnyChildEntityNames( prevBatchIdentifier ) ) {
prevBatchIdentifier.parent = batchIdentifier;
}
}
@ -1192,7 +1192,7 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
nextBatchIdentifier.parent = batchIdentifier;
nextBatchIdentifier.getParentEntityNames().add( batchIdentifier.getEntityName() );
}
if ( batchIdentifier.hasAnyChildEntityNames( nextBatchIdentifier ) ) {
else if ( batchIdentifier.hasAnyChildEntityNames( nextBatchIdentifier ) ) {
nextBatchIdentifier.parent = batchIdentifier;
nextBatchIdentifier.getParentEntityNames().add( batchIdentifier.getEntityName() );
}

View File

@ -444,6 +444,18 @@ public static int[] trim(int[] from, int length) {
return trimmed;
}
public static Object[] toObjectArray(Object array) {
if ( array instanceof Object[] ) {
return ( Object[] ) array;
}
final int arrayLength = Array.getLength( array );
final Object[] outputArray = new Object[ arrayLength ];
for ( int i = 0; i < arrayLength; ++i ) {
outputArray[ i ] = Array.get( array, i );
}
return outputArray;
}
public static <T> List<T> toExpandableList(T[] values) {
if ( values == null ) {
return new ArrayList<>();

View File

@ -44,6 +44,7 @@
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
@ -671,7 +672,9 @@ public AbstractEntityPersister(
this.navigableRole = new NavigableRole( bootDescriptor.getEntityName() );
if ( creationContext.getSessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled() ) {
SessionFactoryOptions sessionFactoryOptions = creationContext.getSessionFactory().getSessionFactoryOptions();
if ( sessionFactoryOptions.isSecondLevelCacheEnabled() ) {
this.canWriteToCache = determineCanWriteToCache( bootDescriptor, cacheAccessStrategy );
this.canReadFromCache = determineCanReadFromCache( bootDescriptor, cacheAccessStrategy );
this.cacheAccessStrategy = cacheAccessStrategy;
@ -851,7 +854,8 @@ else if ( batchSize > 1 ) {
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
entityMetamodel.isInstrumented(),
creationContext.getSessionFactory().getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
if ( lazy ) {
@ -917,12 +921,6 @@ else if ( batchSize > 1 ) {
definedBySubclass.add( Boolean.valueOf( isDefinedBySubclass ) );
propNullables.add( Boolean.valueOf( prop.isOptional() || isDefinedBySubclass ) ); //TODO: is this completely correct?
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
entityMetamodel.isInstrumented(),
creationContext.getSessionFactory().getSessionFactoryOptions().isEnhancementAsProxyEnabled()
);
final Iterator colIter = prop.getColumnIterator();
String[] cols = new String[ prop.getColumnSpan() ];
String[] readers = new String[ prop.getColumnSpan() ];
@ -932,6 +930,12 @@ else if ( batchSize > 1 ) {
int[] formnos = new int[ prop.getColumnSpan() ];
int l = 0;
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
entityMetamodel.isInstrumented(),
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
while ( colIter.hasNext() ) {
final Selectable thing = (Selectable) colIter.next();
if ( thing.isFormula() ) {
@ -1041,7 +1045,7 @@ else if ( batchSize > 1 ) {
this.cacheEntryHelper = buildCacheEntryHelper();
if ( creationContext.getSessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled() ) {
if ( sessionFactoryOptions.isSecondLevelCacheEnabled() ) {
this.invalidateCache = canWriteToCache && determineWhetherToInvalidateCache( bootDescriptor, creationContext );
}
else {
@ -1190,7 +1194,7 @@ protected Map<String,String> generateLazySelectStringsByFetchGroup() {
}
if ( columnNumbers.size() == 0 && formulaNumbers.size() == 0 ) {
// only one-to-one is lazy fetched
// only one-to-one is lazily fetched
continue;
}
@ -1792,8 +1796,8 @@ public String selectFragment(String alias, String suffix) {
public String[] getIdentifierAliases(String suffix) {
// NOTE: this assumes something about how propertySelectFragment is implemented by the subclass!
// was toUnqotedAliasStrings( getIdentifierColumnNames() ) before - now tried
// to remove that unqoting and missing aliases..
// was toUnquotedAliasStrings( getIdentifierColumnNames() ) before - now tried
// to remove that unquoting and missing aliases..
return new Alias( suffix ).toAliasStrings( getIdentifierAliases() );
}
@ -1804,8 +1808,8 @@ public String[] getPropertyAliases(String suffix, int i) {
public String getDiscriminatorAlias(String suffix) {
// NOTE: this assumes something about how propertySelectFragment is implemented by the subclass!
// toUnqotedAliasStrings( getdiscriminatorColumnName() ) before - now tried
// to remove that unqoting and missing aliases..
// toUnquotedAliasStrings( getDiscriminatorColumnName() ) before - now tried
// to remove that unquoting and missing aliases..
return entityMetamodel.hasSubclasses() ?
new Alias( suffix ).toAliasString( getDiscriminatorAlias() ) :
null;
@ -2041,7 +2045,7 @@ public Object forceVersionIncrement(Object id, Object currentVersion, SharedSess
}
if ( isVersionPropertyGenerated() ) {
// the difficulty here is exactly what do we update in order to
// the difficulty here is exactly what we update in order to
// force the version to be incremented in the db...
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
}
@ -2530,7 +2534,7 @@ protected void initSubclassPropertyAliasesMap(PersistentClass model) throws Mapp
// aliases for composite-id's
if ( getIdentifierType().isComponentType() ) {
// Fetch embedded identifiers propertynames from the "virtual" identifier component
// Fetch embedded identifiers property names from the "virtual" identifier component
CompositeType componentId = (CompositeType) getIdentifierType();
String[] idPropertyNames = componentId.getPropertyNames();
String[] idAliases = getIdentifierAliases();
@ -2559,7 +2563,7 @@ protected void initSubclassPropertyAliasesMap(PersistentClass model) throws Mapp
);
}
else {
// embedded composite ids ( alias.idname1, alias.idname2 )
// embedded composite ids ( alias.idName1, alias.idName2 )
subclassPropertyAliases.put( idPropertyNames[i], new String[] {idAliases[i]} );
subclassPropertyColumnNames.put( idPropertyNames[i], new String[] {idColumnNames[i]} );
}
@ -2799,7 +2803,7 @@ public String generateUpdateString(
}
}
// select the correct row by either pk or rowid
// select the correct row by either pk or row id
if ( useRowId ) {
update.addPrimaryKeyColumns( new String[] {rowIdName} ); //TODO: eventually, rowIdName[j]
}
@ -3188,7 +3192,7 @@ public Object[] hydrate(
// should be using the entity root table as the driving table;
// another option here would be to choose some non-optional joined
// table to use as the driving table. In all likelihood, just using
// the root table is much simplier
// the root table is much simpler
// 2) Need to add the FK columns corresponding to each joined table
// to the generated select list; these would then be used when
// iterating the result set to determine whether all non-optional
@ -4337,7 +4341,7 @@ protected String renderSelect(
final String drivingAlias = generateTableAlias(
getRootAlias(),
drivingTable
); //we *could* regerate this inside each called method!
); //we *could* regenerate this inside each called method!
final String where = createWhereByKey( drivingTable, drivingAlias );
final String from = createFrom( drivingTable, drivingAlias );

View File

@ -10,6 +10,7 @@
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.engine.internal.UnsavedValueFactory;
import org.hibernate.engine.spi.IdentifierValue;
@ -169,10 +170,12 @@ public static NonIdentifierAttribute buildEntityBasedAttribute(
boolean alwaysDirtyCheck = type.isAssociationType() &&
( (AssociationType) type ).isAlwaysDirtyChecked();
SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions();
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
property,
lazyAvailable,
sessionFactory.getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
switch ( nature ) {

View File

@ -38,11 +38,12 @@ public static BytecodeEnhancementMetadata from(
PersistentClass persistentClass,
Set<String> identifierAttributeNames,
CompositeType nonAggregatedCidMapper,
boolean allowEnhancementAsProxy) {
boolean allowEnhancementAsProxy,
boolean collectionsInDefaultFetchGroupEnabled) {
final Class mappedClass = persistentClass.getMappedClass();
final boolean enhancedForLazyLoading = PersistentAttributeInterceptable.class.isAssignableFrom( mappedClass );
final LazyAttributesMetadata lazyAttributesMetadata = enhancedForLazyLoading
? LazyAttributesMetadata.from( persistentClass, true, allowEnhancementAsProxy )
? LazyAttributesMetadata.from( persistentClass, true, allowEnhancementAsProxy, collectionsInDefaultFetchGroupEnabled )
: LazyAttributesMetadata.nonEnhanced( persistentClass.getEntityName() );
return new BytecodeEnhancementMetadataPojoImpl(

View File

@ -18,6 +18,7 @@
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.NotYetImplementedException;
@ -138,6 +139,8 @@ public EntityMetamodel(
versioned = persistentClass.isVersioned();
SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions();
if ( persistentClass.hasPojoRepresentation() ) {
final Component identifierMapperComponent = persistentClass.getIdentifierMapper();
final CompositeType nonAggregatedCidMapper;
@ -161,7 +164,8 @@ public EntityMetamodel(
persistentClass,
idAttributeNames,
nonAggregatedCidMapper,
sessionFactory.getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
}
else {
@ -243,7 +247,8 @@ public EntityMetamodel(
boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
bytecodeEnhancementMetadata.isEnhancedForLazyLoading(),
sessionFactory.getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
if ( lazy ) {

View File

@ -0,0 +1,60 @@
package org.hibernate.internal;
import java.util.stream.Stream;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.TypedQuery;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Before;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Dragoş Haiduc
* @author Nathan Xu
*/
@TestForIssue( jiraKey = "HHH-14231" )
public class ScrollableResultsObjectArrayCastingTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Product.class };
}
@Before
public void SetUp() {
doInJPA( this::entityManagerFactory, entityManager -> {
Product product = new Product();
product.binaryValue = "".getBytes();
entityManager.persist( product );
} );
}
@Test
public void testNoClassCastExceptionThrown() {
doInJPA( this::entityManagerFactory, entityManager -> {
TypedQuery<byte[]> typedQuery = entityManager.createQuery( "select p.binaryValue from Product p", byte[].class );
Stream<byte[]> stream = typedQuery.getResultStream();
stream.findFirst();
} );
}
@Entity(name = "Product")
public static class Product {
@Id @GeneratedValue
Integer id;
String name;
@Lob
byte[] binaryValue;
}
}

View File

@ -57,7 +57,7 @@ public void stop() {
public void prepare(boolean allowAggressiveRelease) throws SQLException {
dialect = ConnectionProviderBuilder.getCorrespondingDialect();
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
sqlStatementLogger = new SqlStatementLogger( true, false );
sqlStatementLogger = new SqlStatementLogger( true, false, false );
Connection jdbcConnection = connectionProvider.getConnection();
try {