Merge remote-tracking branch 'upstream/master' into wip/6.0_merge_37
This commit is contained in:
commit
5d572cc876
|
@ -368,6 +368,10 @@ task forbiddenApisSystemOut(type: CheckForbiddenApis, dependsOn: compileJava) {
|
|||
targetCompatibility = project.forbiddenAPITargetJDKCompatibility
|
||||
bundledSignatures += 'jdk-system-out'
|
||||
suppressAnnotations += ['org.hibernate.internal.build.AllowSysOut', 'org.hibernate.internal.build.AllowPrintStacktrace']
|
||||
|
||||
// This slows down the checks a little, but is necessary to avoid the gradle deamon holding on
|
||||
// to class definitions loaded previously - even possibly in a previous build.
|
||||
disableClassloadingCache = true
|
||||
}
|
||||
|
||||
task forbiddenApisUnsafe(type: CheckForbiddenApis, dependsOn: compileJava) {
|
||||
|
@ -381,6 +385,10 @@ task forbiddenApisUnsafe(type: CheckForbiddenApis, dependsOn: compileJava) {
|
|||
//
|
||||
// No idea how findbugs was missing these b4
|
||||
ignoreFailures = true
|
||||
|
||||
// This slows down the checks a little, but is necessary to avoid the gradle deamon holding on
|
||||
// to class definitions loaded previously - even possibly in a previous build.
|
||||
disableClassloadingCache = true
|
||||
}
|
||||
|
||||
task forbiddenApisNonPortable(type: CheckForbiddenApis, dependsOn: compileJava) {
|
||||
|
@ -388,6 +396,10 @@ task forbiddenApisNonPortable(type: CheckForbiddenApis, dependsOn: compileJava)
|
|||
classpath = project.sourceSets.main.compileClasspath + project.sourceSets.main.runtimeClasspath
|
||||
targetCompatibility = project.forbiddenAPITargetJDKCompatibility
|
||||
bundledSignatures += 'jdk-non-portable'
|
||||
|
||||
// This slows down the checks a little, but is necessary to avoid the gradle deamon holding on
|
||||
// to class definitions loaded previously - even possibly in a previous build.
|
||||
disableClassloadingCache = true
|
||||
}
|
||||
|
||||
task forbiddenApis
|
||||
|
|
|
@ -26,9 +26,9 @@ ext {
|
|||
weldVersion = '3.0.0.Final'
|
||||
|
||||
javassistVersion = '3.24.0-GA'
|
||||
byteBuddyVersion = '1.10.7'
|
||||
byteBuddyVersion = '1.10.10'
|
||||
|
||||
agroalVersion = '1.7'
|
||||
agroalVersion = '1.8'
|
||||
|
||||
assertjVersion = '3.14.0'
|
||||
|
||||
|
@ -59,7 +59,7 @@ ext {
|
|||
|
||||
// Annotations
|
||||
commons_annotations: "org.hibernate.common:hibernate-commons-annotations:${hibernateCommonsVersion}",
|
||||
jandex: 'org.jboss:jandex:2.1.1.Final',
|
||||
jandex: 'org.jboss:jandex:2.1.3.Final',
|
||||
classmate: 'com.fasterxml:classmate:1.5.1',
|
||||
|
||||
// Dom4J
|
||||
|
|
|
@ -25,6 +25,13 @@ public enum ConnectionReleaseMode{
|
|||
*/
|
||||
AFTER_STATEMENT,
|
||||
|
||||
/**
|
||||
* Indicates that JDBC connections should be released before each transaction
|
||||
* commits/rollbacks (works with both JTA-registered synch and HibernateTransaction API).
|
||||
* This mode may be used with an application server JTA datasource.
|
||||
*/
|
||||
BEFORE_TRANSACTION_COMPLETION,
|
||||
|
||||
/**
|
||||
* Indicates that JDBC connections should be released after each transaction
|
||||
* ends (works with both JTA-registered synch and HibernateTransaction API).
|
||||
|
|
|
@ -384,8 +384,6 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
final ConfigurationService cfgService = sessionFactoryServiceRegistry.getService( ConfigurationService.class );
|
||||
final ClassLoaderService classLoaderService = sessionFactoryServiceRegistry.getService( ClassLoaderService.class );
|
||||
|
||||
eventListenerRegistry.prepare( this );
|
||||
|
||||
for ( Map.Entry entry : ( (Map<?, ?>) cfgService.getSettings() ).entrySet() ) {
|
||||
if ( !String.class.isInstance( entry.getKey() ) ) {
|
||||
continue;
|
||||
|
|
|
@ -48,10 +48,13 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SessionFactoryBuilderImpl(MetadataImplementor metadata, BootstrapContext bootstrapContext) {
|
||||
this( metadata, new SessionFactoryOptionsBuilder(
|
||||
metadata.getMetadataBuildingOptions().getServiceRegistry(),
|
||||
bootstrapContext
|
||||
) );
|
||||
this(
|
||||
metadata,
|
||||
new SessionFactoryOptionsBuilder(
|
||||
metadata.getMetadataBuildingOptions().getServiceRegistry(),
|
||||
bootstrapContext
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
|
@ -266,7 +269,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder applyQuerySubstitutions(Map substitutions) {
|
||||
public SessionFactoryBuilder applyQuerySubstitutions(@SuppressWarnings("rawtypes") Map substitutions) {
|
||||
this.optionsBuilder.applyQuerySubstitutions( substitutions );
|
||||
return this;
|
||||
}
|
||||
|
@ -469,5 +472,4 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
public SessionFactoryOptions buildSessionFactoryOptions() {
|
||||
return optionsBuilder.buildOptions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* 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.boot.registry.selector.internal;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.dialect.CUBRIDDialect;
|
||||
import org.hibernate.dialect.Cache71Dialect;
|
||||
import org.hibernate.dialect.DB2390Dialect;
|
||||
import org.hibernate.dialect.DB2390V8Dialect;
|
||||
import org.hibernate.dialect.DB2400Dialect;
|
||||
import org.hibernate.dialect.DB2400V7R3Dialect;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.DerbyTenFiveDialect;
|
||||
import org.hibernate.dialect.DerbyTenSevenDialect;
|
||||
import org.hibernate.dialect.DerbyTenSixDialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.FirebirdDialect;
|
||||
import org.hibernate.dialect.FrontBaseDialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.HANAColumnStoreDialect;
|
||||
import org.hibernate.dialect.HANARowStoreDialect;
|
||||
import org.hibernate.dialect.HSQLDialect;
|
||||
import org.hibernate.dialect.InformixDialect;
|
||||
import org.hibernate.dialect.Ingres10Dialect;
|
||||
import org.hibernate.dialect.Ingres9Dialect;
|
||||
import org.hibernate.dialect.IngresDialect;
|
||||
import org.hibernate.dialect.InterbaseDialect;
|
||||
import org.hibernate.dialect.JDataStoreDialect;
|
||||
import org.hibernate.dialect.MckoiDialect;
|
||||
import org.hibernate.dialect.MimerSQLDialect;
|
||||
import org.hibernate.dialect.MySQL57Dialect;
|
||||
import org.hibernate.dialect.MySQL57InnoDBDialect;
|
||||
import org.hibernate.dialect.MySQL5Dialect;
|
||||
import org.hibernate.dialect.MySQL5InnoDBDialect;
|
||||
import org.hibernate.dialect.MySQL8Dialect;
|
||||
import org.hibernate.dialect.Oracle10gDialect;
|
||||
import org.hibernate.dialect.Oracle8iDialect;
|
||||
import org.hibernate.dialect.Oracle9iDialect;
|
||||
import org.hibernate.dialect.PointbaseDialect;
|
||||
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||
import org.hibernate.dialect.PostgreSQL82Dialect;
|
||||
import org.hibernate.dialect.PostgreSQL9Dialect;
|
||||
import org.hibernate.dialect.PostgresPlusDialect;
|
||||
import org.hibernate.dialect.ProgressDialect;
|
||||
import org.hibernate.dialect.SAPDBDialect;
|
||||
import org.hibernate.dialect.SQLServer2005Dialect;
|
||||
import org.hibernate.dialect.SQLServer2008Dialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.dialect.Sybase11Dialect;
|
||||
import org.hibernate.dialect.SybaseASE157Dialect;
|
||||
import org.hibernate.dialect.SybaseASE15Dialect;
|
||||
import org.hibernate.dialect.SybaseAnywhereDialect;
|
||||
import org.hibernate.dialect.TeradataDialect;
|
||||
import org.hibernate.dialect.TimesTenDialect;
|
||||
|
||||
public class DefaultDialectSelector implements LazyServiceResolver<Dialect> {
|
||||
|
||||
@Override
|
||||
public Class<? extends Dialect> resolve(final String name) {
|
||||
Objects.requireNonNull( name);
|
||||
if ( name.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
//Let's organize all string matches in groups by first letter:
|
||||
final char n = name.charAt( 0 );
|
||||
switch ( n ) {
|
||||
case 'C': return caseC( name );
|
||||
case 'D': return caseD( name );
|
||||
case 'F': return caseF( name );
|
||||
case 'H': return caseH( name );
|
||||
case 'I': return caseI( name );
|
||||
case 'J': return caseJ( name );
|
||||
case 'M': return caseM( name );
|
||||
case 'O': return caseO( name );
|
||||
case 'P': return caseP( name );
|
||||
case 'S': return caseS( name );
|
||||
case 'T': return caseT( name );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseC(final String name) {
|
||||
if ( name.equals( "Cache71" ) ) {
|
||||
return Cache71Dialect.class;
|
||||
}
|
||||
if ( name.equals( "CUBRID" ) ) {
|
||||
return CUBRIDDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseD(final String name) {
|
||||
if ( name.equals( "DB2" ) ) {
|
||||
return DB2Dialect.class;
|
||||
}
|
||||
if ( name.equals( "DB2390" ) ) {
|
||||
return DB2390Dialect.class;
|
||||
}
|
||||
if ( name.equals( "DB2390V8" ) ) {
|
||||
return DB2390V8Dialect.class;
|
||||
}
|
||||
if ( name.equals( "DB2400" ) ) {
|
||||
return DB2400Dialect.class;
|
||||
}
|
||||
if ( name.equals( "DB2400V7R3" ) ) {
|
||||
return DB2400V7R3Dialect.class;
|
||||
}
|
||||
if ( name.equals( "DerbyTenFive" ) ) {
|
||||
return DerbyTenFiveDialect.class;
|
||||
}
|
||||
if ( name.equals( "DerbyTenSix" ) ) {
|
||||
return DerbyTenSixDialect.class;
|
||||
}
|
||||
if ( name.equals( "DerbyTenSeven" ) ) {
|
||||
return DerbyTenSevenDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseF(final String name) {
|
||||
if ( name.equals( "Firebird" ) ) {
|
||||
return FirebirdDialect.class;
|
||||
}
|
||||
if ( name.equals( "FrontBase" ) ) {
|
||||
return FrontBaseDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseH(final String name) {
|
||||
if ( name.equals( "H2" ) ) {
|
||||
return H2Dialect.class;
|
||||
}
|
||||
if ( name.equals( "HANAColumnStore" ) ) {
|
||||
return HANAColumnStoreDialect.class;
|
||||
}
|
||||
if ( name.equals( "HANARowStore" ) ) {
|
||||
return HANARowStoreDialect.class;
|
||||
}
|
||||
if ( name.equals( "HSQL" ) ) {
|
||||
return HSQLDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseI(final String name) {
|
||||
if ( name.equals( "Informix" ) ) {
|
||||
return InformixDialect.class;
|
||||
}
|
||||
if ( name.equals( "Ingres" ) ) {
|
||||
return IngresDialect.class;
|
||||
}
|
||||
if ( name.equals( "Ingres9" ) ) {
|
||||
return Ingres9Dialect.class;
|
||||
}
|
||||
if ( name.equals( "Ingres10" ) ) {
|
||||
return Ingres10Dialect.class;
|
||||
}
|
||||
if ( name.equals( "Interbase" ) ) {
|
||||
return InterbaseDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseJ(final String name) {
|
||||
if ( name.equals( "JDataStore" ) ) {
|
||||
return JDataStoreDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseM(final String name) {
|
||||
if ( name.equals( "Mckoi" ) ) {
|
||||
return MckoiDialect.class;
|
||||
}
|
||||
if ( name.equals( "MimerSQL" ) ) {
|
||||
return MimerSQLDialect.class;
|
||||
}
|
||||
if ( name.equals( "MySQL5" ) ) {
|
||||
return MySQL5Dialect.class;
|
||||
}
|
||||
if ( name.equals( "MySQL5InnoDB" ) ) {
|
||||
return MySQL5InnoDBDialect.class;
|
||||
}
|
||||
if ( name.equals( "MySQL57InnoDB" ) ) {
|
||||
return MySQL57InnoDBDialect.class;
|
||||
}
|
||||
if ( name.equals( "MySQL57" ) ) {
|
||||
return MySQL57Dialect.class;
|
||||
}
|
||||
if ( name.equals( "MySQL8" ) ) {
|
||||
return MySQL8Dialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseO(final String name) {
|
||||
if ( name.equals( "Oracle8i" ) ) {
|
||||
return Oracle8iDialect.class;
|
||||
}
|
||||
if ( name.equals( "Oracle9i" ) ) {
|
||||
return Oracle9iDialect.class;
|
||||
}
|
||||
if ( name.equals( "Oracle10g" ) ) {
|
||||
return Oracle10gDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseP(final String name) {
|
||||
if ( name.equals( "Pointbase" ) ) {
|
||||
return PointbaseDialect.class;
|
||||
}
|
||||
if ( name.equals( "PostgresPlus" ) ) {
|
||||
return PostgresPlusDialect.class;
|
||||
}
|
||||
if ( name.equals( "PostgreSQL81" ) ) {
|
||||
return PostgreSQL81Dialect.class;
|
||||
}
|
||||
if ( name.equals( "PostgreSQL82" ) ) {
|
||||
return PostgreSQL82Dialect.class;
|
||||
}
|
||||
if ( name.equals( "PostgreSQL9" ) ) {
|
||||
return PostgreSQL9Dialect.class;
|
||||
}
|
||||
if ( name.equals( "Progress" ) ) {
|
||||
return ProgressDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseS(final String name) {
|
||||
if ( name.equals( "SAPDB" ) ) {
|
||||
return SAPDBDialect.class;
|
||||
}
|
||||
if ( name.equals( "SQLServer" ) ) {
|
||||
return SQLServerDialect.class;
|
||||
}
|
||||
if ( name.equals( "SQLServer2005" ) ) {
|
||||
return SQLServer2005Dialect.class;
|
||||
}
|
||||
if ( name.equals( "SQLServer2008" ) ) {
|
||||
return SQLServer2008Dialect.class;
|
||||
}
|
||||
if ( name.equals( "Sybase11" ) ) {
|
||||
return Sybase11Dialect.class;
|
||||
}
|
||||
if ( name.equals( "SybaseAnywhere" ) ) {
|
||||
return SybaseAnywhereDialect.class;
|
||||
}
|
||||
if ( name.equals( "Sybase11" ) ) {
|
||||
return Sybase11Dialect.class;
|
||||
}
|
||||
if ( name.equals( "SybaseAnywhere" ) ) {
|
||||
return SybaseAnywhereDialect.class;
|
||||
}
|
||||
if ( name.equals( "SybaseASE15" ) ) {
|
||||
return SybaseASE15Dialect.class;
|
||||
}
|
||||
if ( name.equals( "SybaseASE157" ) ) {
|
||||
return SybaseASE157Dialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends Dialect> caseT(final String name) {
|
||||
if ( name.equals( "Teradata" ) ) {
|
||||
return TeradataDialect.class;
|
||||
}
|
||||
if ( name.equals( "TimesTen" ) ) {
|
||||
return TimesTenDialect.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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.boot.registry.selector.internal;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.BorlandEnterpriseServerJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JOTMJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JOnASJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JRun4JtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.OC4JJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.OrionJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.ResinJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.SapNetWeaverJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.SunOneJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
|
||||
public class DefaultJtaPlatformSelector implements LazyServiceResolver<JtaPlatform> {
|
||||
|
||||
@Override
|
||||
public Class<? extends JtaPlatform> resolve(final String name) {
|
||||
Objects.requireNonNull( name);
|
||||
if ( name.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
//Let's organize all string matches in groups by first letter:
|
||||
final char n = name.charAt( 0 );
|
||||
switch ( n ) {
|
||||
case 'B': return caseB( name );
|
||||
case 'J': return caseJ( name );
|
||||
case 'W': return caseW( name );
|
||||
case 'o': return caseLegacy( name, this );
|
||||
default: return caseOthers( name );
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<? extends JtaPlatform> caseB(final String name) {
|
||||
if ( "Bitronix".equals( name ) ) {
|
||||
return BitronixJtaPlatform.class;
|
||||
}
|
||||
if ( "Borland".equals( name ) ) {
|
||||
return BorlandEnterpriseServerJtaPlatform.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends JtaPlatform> caseJ(final String name) {
|
||||
if ( "JBossAS".equals( name ) ) {
|
||||
return JBossAppServerJtaPlatform.class;
|
||||
}
|
||||
if ( "JBossTS".equals( name ) ) {
|
||||
return JBossStandAloneJtaPlatform.class;
|
||||
}
|
||||
if ( "JOnAS".equals( name ) ) {
|
||||
return JOnASJtaPlatform.class;
|
||||
}
|
||||
if ( "JOTM".equals( name ) ) {
|
||||
return JOTMJtaPlatform.class;
|
||||
}
|
||||
if ( "JRun4".equals( name ) ) {
|
||||
return JRun4JtaPlatform.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends JtaPlatform> caseW(final String name) {
|
||||
if ( "Weblogic".equals( name ) ) {
|
||||
return WeblogicJtaPlatform.class;
|
||||
}
|
||||
if ( "WebSphereLiberty".equals( name ) ) {
|
||||
return WebSphereLibertyJtaPlatform.class;
|
||||
}
|
||||
if ( "WebSphere".equals( name ) ) {
|
||||
return WebSphereJtaPlatform.class;
|
||||
}
|
||||
if ( "WebSphereExtended".equals( name ) ) {
|
||||
return WebSphereExtendedJtaPlatform.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<? extends JtaPlatform> caseOthers(final String name) {
|
||||
if ( "Atomikos".equals( name ) ) {
|
||||
return AtomikosJtaPlatform.class;
|
||||
}
|
||||
if ( "OC4J".equals( name ) ) {
|
||||
return OC4JJtaPlatform.class;
|
||||
}
|
||||
if ( "Orion".equals( name ) ) {
|
||||
return OrionJtaPlatform.class;
|
||||
}
|
||||
if ( "Resin".equals( name ) ) {
|
||||
return ResinJtaPlatform.class;
|
||||
}
|
||||
if ( "SapNetWeaver".equals( name ) ) {
|
||||
return SapNetWeaverJtaPlatform.class;
|
||||
}
|
||||
if ( "SunOne".equals( name ) ) {
|
||||
return SunOneJtaPlatform.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special case: we have several old fully qualified classnames which need to
|
||||
* be remapped to their new names for backwards compatibility reasons.
|
||||
* @param name
|
||||
* @param defaultJtaPlatformSelector
|
||||
* @return
|
||||
*/
|
||||
private static Class<? extends JtaPlatform> caseLegacy(
|
||||
final String name,
|
||||
final DefaultJtaPlatformSelector defaultJtaPlatformSelector) {
|
||||
|
||||
//First, let's deal with the special cases which don't follow any recognizable pattern:
|
||||
if ( name.equals( "org.hibernate.service.jta.platform.internal.BorlandEnterpriseServerJtaPlatform" ) ) {
|
||||
return BorlandEnterpriseServerJtaPlatform.class;
|
||||
}
|
||||
if ( name.equals( "org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" ) ) {
|
||||
return JBossAppServerJtaPlatform.class;
|
||||
}
|
||||
if ( name.equals( "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform" ) ) {
|
||||
return JBossStandAloneJtaPlatform.class;
|
||||
}
|
||||
//This one shouldn't be necessary as it matches the implementation FQN, but let's translate the existing
|
||||
//code faithfully.
|
||||
if ( name.equals( "org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform" ) ) {
|
||||
return WebSphereLibertyJtaPlatform.class;
|
||||
}
|
||||
|
||||
//All other ones follow a pattern, beginning with the same prefix and ending with the same postfix,
|
||||
//if your remove those the remaining section happens to match the short name.
|
||||
final String LEGACY_PREFIX = "org.hibernate.service.jta.platform.internal.";
|
||||
final String LEGACY_POSTFIX = "JtaPlatform";
|
||||
|
||||
//All these follow the same pattern, allowing us to use recursion into the main method:
|
||||
if ( name.startsWith( LEGACY_PREFIX ) && name.endsWith( LEGACY_POSTFIX ) ) {
|
||||
final String cleanName = name.substring( LEGACY_PREFIX.length(), name.length() - LEGACY_POSTFIX.length() );
|
||||
return defaultJtaPlatformSelector.resolve( cleanName );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.boot.registry.selector.internal;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LazyServiceResolver<T> {
|
||||
|
||||
Class<? extends T> resolve(String name);
|
||||
|
||||
}
|
|
@ -23,16 +23,6 @@ import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
|||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.internal.SimpleCacheKeysFactory;
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.dialect.CUBRIDDialect;
|
||||
import org.hibernate.dialect.Cache71Dialect;
|
||||
import org.hibernate.dialect.DB2390Dialect;
|
||||
import org.hibernate.dialect.DB2390V8Dialect;
|
||||
import org.hibernate.dialect.DB2400Dialect;
|
||||
import org.hibernate.dialect.DB2400V7R3Dialect;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.DerbyTenFiveDialect;
|
||||
import org.hibernate.dialect.DerbyTenSevenDialect;
|
||||
import org.hibernate.dialect.DerbyTenSixDialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.FirebirdDialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
|
@ -152,8 +142,8 @@ public class StrategySelectorBuilder {
|
|||
final StrategySelectorImpl strategySelector = new StrategySelectorImpl( classLoaderService );
|
||||
|
||||
// build the baseline...
|
||||
addDialects( strategySelector );
|
||||
addJtaPlatforms( strategySelector );
|
||||
strategySelector.registerStrategyLazily( Dialect.class, new DefaultDialectSelector() );
|
||||
strategySelector.registerStrategyLazily( JtaPlatform.class, new DefaultJtaPlatformSelector() );
|
||||
addTransactionCoordinatorBuilders( strategySelector );
|
||||
addSqmMultiTableMutationStrategies( strategySelector );
|
||||
addImplicitNamingStrategies( strategySelector );
|
||||
|
|
|
@ -13,7 +13,9 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategyCreator;
|
||||
|
@ -28,10 +30,11 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StrategySelectorImpl implements StrategySelector {
|
||||
|
||||
private static final Logger log = Logger.getLogger( StrategySelectorImpl.class );
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final StrategyCreator STANDARD_STRATEGY_CREATOR = strategyClass -> {
|
||||
private static final StrategyCreator STANDARD_STRATEGY_CREATOR = strategyClass -> {
|
||||
try {
|
||||
return strategyClass.newInstance();
|
||||
}
|
||||
|
@ -43,8 +46,14 @@ public class StrategySelectorImpl implements StrategySelector {
|
|||
}
|
||||
};
|
||||
|
||||
//Map based approach: most suited for explicit registrations from integrators
|
||||
private final Map<Class,Map<String,Class>> namedStrategyImplementorByStrategyMap = new ConcurrentHashMap<>();
|
||||
|
||||
//"Lazy" approach: more efficient as we aim to not initialize all implementation classes;
|
||||
//this is preferable for internal services such as Dialect, as we have a significant amount of them, making
|
||||
//it worthwhile to try be a bit more efficient about them.
|
||||
private final Map<Class, LazyServiceResolver> lazyStrategyImplementorByStrategyMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final ClassLoaderService classLoaderService;
|
||||
|
||||
/**
|
||||
|
@ -56,6 +65,13 @@ public class StrategySelectorImpl implements StrategySelector {
|
|||
this.classLoaderService = classLoaderService;
|
||||
}
|
||||
|
||||
public <T> void registerStrategyLazily(Class<T> strategy, LazyServiceResolver<T> resolver) {
|
||||
LazyServiceResolver previous = lazyStrategyImplementorByStrategyMap.put( strategy, resolver );
|
||||
if ( previous != null ) {
|
||||
throw new HibernateException( "Detected a second LazyServiceResolver replacing an existing LazyServiceResolver implementation for strategy " + strategy.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void registerStrategyImplementor(Class<T> strategy, String name, Class<? extends T> implementation) {
|
||||
final Map<String,Class> namedStrategyImplementorMap = namedStrategyImplementorByStrategyMap.computeIfAbsent(
|
||||
|
@ -124,6 +140,14 @@ public class StrategySelectorImpl implements StrategySelector {
|
|||
}
|
||||
}
|
||||
|
||||
LazyServiceResolver lazyServiceResolver = lazyStrategyImplementorByStrategyMap.get( strategy );
|
||||
if ( lazyServiceResolver != null ) {
|
||||
Class resolve = lazyServiceResolver.resolve( name );
|
||||
if ( resolve != null ) {
|
||||
return resolve;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return classLoaderService.classForName( name );
|
||||
}
|
||||
|
@ -175,6 +199,10 @@ public class StrategySelectorImpl implements StrategySelector {
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection getRegisteredStrategyImplementors(Class strategy) {
|
||||
LazyServiceResolver lazyServiceResolver = lazyStrategyImplementorByStrategyMap.get( strategy );
|
||||
if ( lazyServiceResolver != null ) {
|
||||
throw new StrategySelectionException( "Can't use this method on for strategy types which are embedded in the core library" );
|
||||
}
|
||||
final Map<String, Class> registrations = namedStrategyImplementorByStrategyMap.get( strategy );
|
||||
if ( registrations == null ) {
|
||||
return Collections.emptySet();
|
||||
|
|
|
@ -439,7 +439,8 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
|
|||
|
||||
@Override
|
||||
public void beforeTransactionCompletion() {
|
||||
owner.beforeTransactionCompletion();
|
||||
this.owner.beforeTransactionCompletion();
|
||||
this.logicalConnection.beforeTransactionCompletion();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.profile.FetchProfile;
|
||||
import org.hibernate.engine.query.spi.QueryPlanCache;
|
||||
import org.hibernate.event.spi.EventEngine;
|
||||
import org.hibernate.exception.spi.SQLExceptionConverter;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
|
@ -143,6 +145,11 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
|
|||
return delegate.getRuntimeMetamodels();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventEngine getEventEngine() {
|
||||
return delegate.getEventEngine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws HibernateException {
|
||||
delegate.close();
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.profile.FetchProfile;
|
||||
import org.hibernate.engine.query.spi.QueryPlanCache;
|
||||
import org.hibernate.event.spi.EventEngine;
|
||||
import org.hibernate.exception.spi.SQLExceptionConverter;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
|
@ -113,6 +115,11 @@ public interface SessionFactoryImplementor
|
|||
*/
|
||||
ServiceRegistryImplementor getServiceRegistry();
|
||||
|
||||
/**
|
||||
* Get the EventEngine associated with this SessionFactory
|
||||
*/
|
||||
EventEngine getEventEngine();
|
||||
|
||||
/**
|
||||
* Retrieve fetch profile by name.
|
||||
*
|
||||
|
|
|
@ -21,11 +21,14 @@ import org.hibernate.event.service.spi.EventListenerGroup;
|
|||
import org.hibernate.event.service.spi.EventListenerRegistrationException;
|
||||
import org.hibernate.event.service.spi.JpaBootstrapSensitive;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.jpa.event.spi.CallbackRegistry;
|
||||
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Standard EventListenerGroup implementation
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
|
@ -33,15 +36,20 @@ class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
|
|||
private static final Logger log = Logger.getLogger( EventListenerGroupImpl.class );
|
||||
|
||||
private final EventType<T> eventType;
|
||||
private final EventListenerRegistryImpl listenerRegistry;
|
||||
private final CallbackRegistry callbackRegistry;
|
||||
private final boolean isJpaBootstrap;
|
||||
|
||||
private final Set<DuplicationStrategy> duplicationStrategies = new LinkedHashSet<>();
|
||||
|
||||
private T[] listeners = null;
|
||||
|
||||
public EventListenerGroupImpl(EventType<T> eventType, EventListenerRegistryImpl listenerRegistry) {
|
||||
public EventListenerGroupImpl(
|
||||
EventType<T> eventType,
|
||||
CallbackRegistry callbackRegistry,
|
||||
boolean isJpaBootstrap) {
|
||||
this.eventType = eventType;
|
||||
this.listenerRegistry = listenerRegistry;
|
||||
this.callbackRegistry = callbackRegistry;
|
||||
this.isJpaBootstrap = isJpaBootstrap;
|
||||
|
||||
duplicationStrategies.add(
|
||||
// At minimum make sure we do not register the same exact listener class multiple times.
|
||||
|
@ -267,14 +275,12 @@ class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
|
|||
}
|
||||
|
||||
private void performInjections(T listener) {
|
||||
if ( CallbackRegistryConsumer.class.isInstance( listener ) ) {
|
||||
( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( listenerRegistry.getCallbackRegistry() );
|
||||
if ( listener instanceof CallbackRegistryConsumer ) {
|
||||
( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( callbackRegistry );
|
||||
}
|
||||
|
||||
if ( JpaBootstrapSensitive.class.isInstance( listener ) ) {
|
||||
( (JpaBootstrapSensitive) listener ).wasJpaBootstrap(
|
||||
listenerRegistry.getSessionFactory().getSessionFactoryOptions().isJpaBootstrap()
|
||||
);
|
||||
if ( listener instanceof JpaBootstrapSensitive ) {
|
||||
( (JpaBootstrapSensitive) listener ).wasJpaBootstrap( isJpaBootstrap );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
package org.hibernate.event.service.internal;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.internal.DefaultAutoFlushEventListener;
|
||||
import org.hibernate.event.internal.DefaultDeleteEventListener;
|
||||
import org.hibernate.event.internal.DefaultDirtyCheckEventListener;
|
||||
|
@ -40,16 +39,11 @@ import org.hibernate.event.internal.PostDeleteEventListenerStandardImpl;
|
|||
import org.hibernate.event.internal.PostInsertEventListenerStandardImpl;
|
||||
import org.hibernate.event.internal.PostUpdateEventListenerStandardImpl;
|
||||
import org.hibernate.event.service.spi.DuplicationStrategy;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistrationException;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.jpa.event.internal.CallbackRegistryImplementor;
|
||||
import org.hibernate.jpa.event.internal.CallbacksFactory;
|
||||
import org.hibernate.jpa.event.spi.CallbackBuilder;
|
||||
import org.hibernate.jpa.event.spi.CallbackRegistry;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
|
||||
import static org.hibernate.event.spi.EventType.AUTO_FLUSH;
|
||||
|
@ -90,126 +84,29 @@ import static org.hibernate.event.spi.EventType.SAVE_UPDATE;
|
|||
import static org.hibernate.event.spi.EventType.UPDATE;
|
||||
|
||||
/**
|
||||
* Standard implementation of EventListenerRegistry
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppable {
|
||||
private Map<Class,Object> listenerClassToInstanceMap = new HashMap<>();
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final EventListenerGroup[] eventListeners;
|
||||
private final Map<Class<?>,Object> listenerClassToInstanceMap = new HashMap<>();
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final CallbackRegistryImplementor callbackRegistry;
|
||||
private volatile EventListenerGroupImpl[] registeredEventListeners;
|
||||
private CallbackBuilder callbackBuilder;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link EventListenerRegistryImpl#EventListenerRegistryImpl(BootstrapContext, SessionFactoryImplementor)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
EventListenerRegistryImpl(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryOptions sessionFactoryOptions,
|
||||
ServiceRegistryImplementor registry) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
|
||||
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory );
|
||||
|
||||
this.registeredEventListeners = buildListenerGroups();
|
||||
}
|
||||
|
||||
EventListenerRegistryImpl(BootstrapContext bootstrapContext, SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory );
|
||||
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder(
|
||||
sessionFactory, bootstrapContext.getReflectionManager() );
|
||||
this.registeredEventListeners = buildListenerGroups();
|
||||
}
|
||||
|
||||
SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
CallbackRegistry getCallbackRegistry() {
|
||||
return callbackRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(MetadataImplementor metadata) {
|
||||
if ( callbackBuilder == null ) {
|
||||
// TODO : not needed anymore when the deprecate constructor will be removed
|
||||
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder( sessionFactory, metadata.getMetadataBuildingOptions().getReflectionManager()
|
||||
);
|
||||
}
|
||||
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
|
||||
if ( persistentClass.getClassName() == null ) {
|
||||
// we can have non java class persisted by hibernate
|
||||
continue;
|
||||
}
|
||||
callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
|
||||
|
||||
for ( Iterator propertyIterator = persistentClass.getDeclaredPropertyIterator();
|
||||
propertyIterator.hasNext(); ) {
|
||||
Property property = (Property) propertyIterator.next();
|
||||
|
||||
if ( property.getType().isComponentType() ) {
|
||||
callbackBuilder.buildCallbacksForEmbeddable(
|
||||
property,
|
||||
persistentClass.getClassName(),
|
||||
callbackRegistry
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private synchronized <T> EventListenerGroupImpl<T> getOrCreateEventListenerGroup(EventType<T> eventType) {
|
||||
final int sizeOriginal = this.registeredEventListeners.length;
|
||||
final EventListenerGroupImpl[] registeredEventListenersNew;
|
||||
if ( eventType.ordinal() < sizeOriginal ) {
|
||||
final EventListenerGroupImpl registeredEventListener = registeredEventListeners[ eventType.ordinal() ];
|
||||
if ( registeredEventListener != null ) {
|
||||
// eventType has already been registered;
|
||||
return registeredEventListener; // EARLY RETURN
|
||||
}
|
||||
// eventType has not been registered yet.
|
||||
// Its EventListenerGroupImpl will be created and added to registeredEventListeners below.
|
||||
// There is already space for the new EventType in this.registeredEventListeners.
|
||||
registeredEventListenersNew = this.registeredEventListeners;
|
||||
}
|
||||
else {
|
||||
// eventType is a custom EventType, and there is not enough space in
|
||||
// registeredEventListeners to accommodate it.
|
||||
|
||||
// Allocate a new array to hold listener groups for *all* EventType values that currently exist.
|
||||
// This way an existing, unregistered EventType with a larger ordinal will not require another
|
||||
// allocation when it gets registered in the future.
|
||||
final int sizeNew = Math.max( eventType.ordinal() + 1, EventType.values().size() );
|
||||
registeredEventListenersNew = new EventListenerGroupImpl[sizeNew];
|
||||
|
||||
// First copy the existing listeners to registeredEventListenersNew.
|
||||
System.arraycopy( this.registeredEventListeners, 0, registeredEventListenersNew, 0, sizeOriginal );
|
||||
}
|
||||
|
||||
final EventListenerGroupImpl listenerGroup = new EventListenerGroupImpl(
|
||||
eventType,
|
||||
EventListenerRegistryImpl.this
|
||||
);
|
||||
registeredEventListenersNew[eventType.ordinal()] = listenerGroup;
|
||||
|
||||
// Now update the reference.
|
||||
this.registeredEventListeners = registeredEventListenersNew;
|
||||
|
||||
return listenerGroup;
|
||||
@SuppressWarnings("rawtypes")
|
||||
private EventListenerRegistryImpl(EventListenerGroup[] eventListeners) {
|
||||
this.eventListeners = eventListeners;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <T> EventListenerGroupImpl<T> getEventListenerGroup(EventType<T> eventType) {
|
||||
if ( registeredEventListeners.length < eventType.ordinal() + 1 ) {
|
||||
public <T> EventListenerGroup<T> getEventListenerGroup(EventType<T> eventType) {
|
||||
if ( eventListeners.length < eventType.ordinal() + 1 ) {
|
||||
// eventTpe is a custom EventType that has not been registered.
|
||||
// registeredEventListeners array was not allocated enough space to
|
||||
// accommodate it.
|
||||
throw new HibernateException( "Unable to find listeners for type [" + eventType.eventName() + "]" );
|
||||
}
|
||||
final EventListenerGroupImpl<T> listeners = registeredEventListeners[ eventType.ordinal() ];
|
||||
final EventListenerGroup<T> listeners = eventListeners[ eventType.ordinal() ];
|
||||
if ( listeners == null ) {
|
||||
throw new HibernateException( "Unable to find listeners for type [" + eventType.eventName() + "]" );
|
||||
}
|
||||
|
@ -218,7 +115,8 @@ public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppab
|
|||
|
||||
@Override
|
||||
public void addDuplicationStrategy(DuplicationStrategy strategy) {
|
||||
for ( EventListenerGroupImpl group : registeredEventListeners ) {
|
||||
//noinspection rawtypes
|
||||
for ( EventListenerGroup group : eventListeners ) {
|
||||
if ( group != null ) {
|
||||
group.addDuplicationStrategy( strategy );
|
||||
}
|
||||
|
@ -252,6 +150,7 @@ public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppab
|
|||
|
||||
private <T> T instantiateListener(Class<T> listenerClass) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
return listenerClass.newInstance();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
|
@ -265,7 +164,7 @@ public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppab
|
|||
@Override
|
||||
@SafeVarargs
|
||||
public final <T> void setListeners(EventType<T> type, T... listeners) {
|
||||
EventListenerGroupImpl<T> registeredListeners = getOrCreateEventListenerGroup( type );
|
||||
final EventListenerGroup<T> registeredListeners = getEventListenerGroup( type );
|
||||
registeredListeners.clear();
|
||||
if ( listeners != null ) {
|
||||
for ( T listener : listeners ) {
|
||||
|
@ -283,7 +182,7 @@ public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppab
|
|||
@Override
|
||||
@SafeVarargs
|
||||
public final <T> void appendListeners(EventType<T> type, T... listeners) {
|
||||
getOrCreateEventListenerGroup( type ).appendListeners( listeners );
|
||||
getEventListenerGroup( type ).appendListeners( listeners );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -295,281 +194,206 @@ public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppab
|
|||
@Override
|
||||
@SafeVarargs
|
||||
public final <T> void prependListeners(EventType<T> type, T... listeners) {
|
||||
getOrCreateEventListenerGroup( type ).prependListeners( listeners );
|
||||
}
|
||||
|
||||
private EventListenerGroupImpl[] buildListenerGroups() {
|
||||
EventListenerGroupImpl[] listenerArray = new EventListenerGroupImpl[ EventType.values().size() ];
|
||||
|
||||
// auto-flush listeners
|
||||
prepareListeners(
|
||||
AUTO_FLUSH,
|
||||
new DefaultAutoFlushEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// create listeners
|
||||
prepareListeners(
|
||||
PERSIST,
|
||||
new DefaultPersistEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// create-onflush listeners
|
||||
prepareListeners(
|
||||
PERSIST_ONFLUSH,
|
||||
new DefaultPersistOnFlushEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// delete listeners
|
||||
prepareListeners(
|
||||
DELETE,
|
||||
new DefaultDeleteEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// dirty-check listeners
|
||||
prepareListeners(
|
||||
DIRTY_CHECK,
|
||||
new DefaultDirtyCheckEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// evict listeners
|
||||
prepareListeners(
|
||||
EVICT,
|
||||
new DefaultEvictEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
prepareListeners(
|
||||
CLEAR,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// flush listeners
|
||||
prepareListeners(
|
||||
FLUSH,
|
||||
new DefaultFlushEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// flush-entity listeners
|
||||
prepareListeners(
|
||||
FLUSH_ENTITY,
|
||||
new DefaultFlushEntityEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// load listeners
|
||||
prepareListeners(
|
||||
LOAD,
|
||||
new DefaultLoadEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// resolve natural-id listeners
|
||||
prepareListeners(
|
||||
RESOLVE_NATURAL_ID,
|
||||
new DefaultResolveNaturalIdEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// load-collection listeners
|
||||
prepareListeners(
|
||||
INIT_COLLECTION,
|
||||
new DefaultInitializeCollectionEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// lock listeners
|
||||
prepareListeners(
|
||||
LOCK,
|
||||
new DefaultLockEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// merge listeners
|
||||
prepareListeners(
|
||||
MERGE,
|
||||
new DefaultMergeEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-collection-recreate listeners
|
||||
prepareListeners(
|
||||
PRE_COLLECTION_RECREATE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-collection-remove listeners
|
||||
prepareListeners(
|
||||
PRE_COLLECTION_REMOVE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-collection-update listeners
|
||||
prepareListeners(
|
||||
PRE_COLLECTION_UPDATE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-delete listeners
|
||||
prepareListeners(
|
||||
PRE_DELETE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-insert listeners
|
||||
prepareListeners(
|
||||
PRE_INSERT,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-load listeners
|
||||
prepareListeners(
|
||||
PRE_LOAD,
|
||||
new DefaultPreLoadEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// pre-update listeners
|
||||
prepareListeners(
|
||||
PRE_UPDATE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-collection-recreate listeners
|
||||
prepareListeners(
|
||||
POST_COLLECTION_RECREATE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-collection-remove listeners
|
||||
prepareListeners(
|
||||
POST_COLLECTION_REMOVE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-collection-update listeners
|
||||
prepareListeners(
|
||||
POST_COLLECTION_UPDATE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-commit-delete listeners
|
||||
prepareListeners(
|
||||
POST_COMMIT_DELETE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-commit-insert listeners
|
||||
prepareListeners(
|
||||
POST_COMMIT_INSERT,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-commit-update listeners
|
||||
prepareListeners(
|
||||
POST_COMMIT_UPDATE,
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-delete listeners
|
||||
prepareListeners(
|
||||
POST_DELETE,
|
||||
new PostDeleteEventListenerStandardImpl(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-insert listeners
|
||||
prepareListeners(
|
||||
POST_INSERT,
|
||||
new PostInsertEventListenerStandardImpl(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-load listeners
|
||||
prepareListeners(
|
||||
POST_LOAD,
|
||||
new DefaultPostLoadEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// post-update listeners
|
||||
prepareListeners(
|
||||
POST_UPDATE,
|
||||
new PostUpdateEventListenerStandardImpl(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// update listeners
|
||||
prepareListeners(
|
||||
UPDATE,
|
||||
new DefaultUpdateEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// refresh listeners
|
||||
prepareListeners(
|
||||
REFRESH,
|
||||
new DefaultRefreshEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// replicate listeners
|
||||
prepareListeners(
|
||||
REPLICATE,
|
||||
new DefaultReplicateEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// save listeners
|
||||
prepareListeners(
|
||||
SAVE,
|
||||
new DefaultSaveEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
// save-update listeners
|
||||
prepareListeners(
|
||||
SAVE_UPDATE,
|
||||
new DefaultSaveOrUpdateEventListener(),
|
||||
listenerArray
|
||||
);
|
||||
|
||||
return listenerArray;
|
||||
}
|
||||
|
||||
private <T> void prepareListeners(EventType<T> type, EventListenerGroupImpl[] listenerArray) {
|
||||
prepareListeners( type, null, listenerArray );
|
||||
}
|
||||
|
||||
private <T> void prepareListeners(EventType<T> type, T defaultListener, EventListenerGroupImpl[] listenerArray) {
|
||||
final EventListenerGroupImpl<T> listenerGroup;
|
||||
if ( type == EventType.POST_COMMIT_DELETE
|
||||
|| type == EventType.POST_COMMIT_INSERT
|
||||
|| type == EventType.POST_COMMIT_UPDATE ) {
|
||||
listenerGroup = new PostCommitEventListenerGroupImpl<>( type, this );
|
||||
}
|
||||
else {
|
||||
listenerGroup = new EventListenerGroupImpl<>( type, this );
|
||||
}
|
||||
|
||||
if ( defaultListener != null ) {
|
||||
listenerGroup.appendListener( defaultListener );
|
||||
}
|
||||
listenerArray[ type.ordinal() ] = listenerGroup;
|
||||
getEventListenerGroup( type ).prependListeners( listeners );
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void stop() {
|
||||
if ( callbackRegistry != null ) {
|
||||
callbackRegistry.release();
|
||||
// legacy - no longer used
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Builder
|
||||
|
||||
public static class Builder {
|
||||
private final CallbackRegistryImplementor callbackRegistry;
|
||||
private final boolean jpaBootstrap;
|
||||
|
||||
private final Map<EventType<?>,EventListenerGroup<?>> listenerGroupMap = new TreeMap<>(
|
||||
Comparator.comparing( EventType::ordinal )
|
||||
);
|
||||
|
||||
public Builder(CallbackRegistryImplementor callbackRegistry, boolean jpaBootstrap) {
|
||||
this.callbackRegistry = callbackRegistry;
|
||||
this.jpaBootstrap = jpaBootstrap;
|
||||
|
||||
applyStandardListeners();
|
||||
}
|
||||
if ( callbackBuilder != null ) {
|
||||
callbackBuilder.release();
|
||||
|
||||
private void applyStandardListeners() {
|
||||
// auto-flush listeners
|
||||
prepareListeners( AUTO_FLUSH, new DefaultAutoFlushEventListener() );
|
||||
|
||||
// create listeners
|
||||
prepareListeners( PERSIST, new DefaultPersistEventListener() );
|
||||
|
||||
// create-onflush listeners
|
||||
prepareListeners( PERSIST_ONFLUSH, new DefaultPersistOnFlushEventListener() );
|
||||
|
||||
// delete listeners
|
||||
prepareListeners( DELETE, new DefaultDeleteEventListener() );
|
||||
|
||||
// dirty-check listeners
|
||||
prepareListeners( DIRTY_CHECK, new DefaultDirtyCheckEventListener() );
|
||||
|
||||
// evict listeners
|
||||
prepareListeners( EVICT, new DefaultEvictEventListener() );
|
||||
|
||||
prepareListeners( CLEAR );
|
||||
|
||||
// flush listeners
|
||||
prepareListeners( FLUSH, new DefaultFlushEventListener() );
|
||||
|
||||
// flush-entity listeners
|
||||
prepareListeners( FLUSH_ENTITY, new DefaultFlushEntityEventListener() );
|
||||
|
||||
// load listeners
|
||||
prepareListeners( LOAD, new DefaultLoadEventListener() );
|
||||
|
||||
// resolve natural-id listeners
|
||||
prepareListeners( RESOLVE_NATURAL_ID, new DefaultResolveNaturalIdEventListener() );
|
||||
|
||||
// load-collection listeners
|
||||
prepareListeners( INIT_COLLECTION, new DefaultInitializeCollectionEventListener() );
|
||||
|
||||
// lock listeners
|
||||
prepareListeners( LOCK, new DefaultLockEventListener() );
|
||||
|
||||
// merge listeners
|
||||
prepareListeners( MERGE, new DefaultMergeEventListener() );
|
||||
|
||||
// pre-collection-recreate listeners
|
||||
prepareListeners( PRE_COLLECTION_RECREATE );
|
||||
|
||||
// pre-collection-remove listeners
|
||||
prepareListeners( PRE_COLLECTION_REMOVE );
|
||||
|
||||
// pre-collection-update listeners
|
||||
prepareListeners( PRE_COLLECTION_UPDATE );
|
||||
|
||||
// pre-delete listeners
|
||||
prepareListeners( PRE_DELETE );
|
||||
|
||||
// pre-insert listeners
|
||||
prepareListeners( PRE_INSERT );
|
||||
|
||||
// pre-load listeners
|
||||
prepareListeners( PRE_LOAD, new DefaultPreLoadEventListener() );
|
||||
|
||||
// pre-update listeners
|
||||
prepareListeners( PRE_UPDATE );
|
||||
|
||||
// post-collection-recreate listeners
|
||||
prepareListeners( POST_COLLECTION_RECREATE );
|
||||
|
||||
// post-collection-remove listeners
|
||||
prepareListeners( POST_COLLECTION_REMOVE );
|
||||
|
||||
// post-collection-update listeners
|
||||
prepareListeners( POST_COLLECTION_UPDATE );
|
||||
|
||||
// post-commit-delete listeners
|
||||
prepareListeners( POST_COMMIT_DELETE );
|
||||
|
||||
// post-commit-insert listeners
|
||||
prepareListeners( POST_COMMIT_INSERT );
|
||||
|
||||
// post-commit-update listeners
|
||||
prepareListeners( POST_COMMIT_UPDATE );
|
||||
|
||||
// post-delete listeners
|
||||
prepareListeners( POST_DELETE, new PostDeleteEventListenerStandardImpl() );
|
||||
|
||||
// post-insert listeners
|
||||
prepareListeners( POST_INSERT, new PostInsertEventListenerStandardImpl() );
|
||||
|
||||
// post-load listeners
|
||||
prepareListeners( POST_LOAD, new DefaultPostLoadEventListener() );
|
||||
|
||||
// post-update listeners
|
||||
prepareListeners( POST_UPDATE, new PostUpdateEventListenerStandardImpl() );
|
||||
|
||||
// update listeners
|
||||
prepareListeners( UPDATE, new DefaultUpdateEventListener() );
|
||||
|
||||
// refresh listeners
|
||||
prepareListeners( REFRESH, new DefaultRefreshEventListener() );
|
||||
|
||||
// replicate listeners
|
||||
prepareListeners( REPLICATE, new DefaultReplicateEventListener() );
|
||||
|
||||
// save listeners
|
||||
prepareListeners( SAVE, new DefaultSaveEventListener() );
|
||||
|
||||
// save-update listeners
|
||||
prepareListeners( SAVE_UPDATE, new DefaultSaveOrUpdateEventListener() );
|
||||
}
|
||||
|
||||
public <T> void prepareListeners(EventType<T> eventType) {
|
||||
prepareListeners( eventType, null );
|
||||
}
|
||||
|
||||
public <T> void prepareListeners(EventType<T> type, T defaultListener) {
|
||||
prepareListeners(
|
||||
type,
|
||||
defaultListener,
|
||||
t -> {
|
||||
if ( type == EventType.POST_COMMIT_DELETE
|
||||
|| type == EventType.POST_COMMIT_INSERT
|
||||
|| type == EventType.POST_COMMIT_UPDATE ) {
|
||||
return new PostCommitEventListenerGroupImpl<>( type, callbackRegistry, jpaBootstrap );
|
||||
}
|
||||
else {
|
||||
return new EventListenerGroupImpl<>( type, callbackRegistry, jpaBootstrap );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public <T> void prepareListeners(
|
||||
EventType<T> type,
|
||||
T defaultListener,
|
||||
Function<EventType<T>,EventListenerGroupImpl<T>> groupCreator) {
|
||||
final EventListenerGroupImpl listenerGroup = groupCreator.apply( type );
|
||||
|
||||
if ( defaultListener != null ) {
|
||||
listenerGroup.appendListener( defaultListener );
|
||||
}
|
||||
|
||||
listenerGroupMap.put( type, listenerGroup );
|
||||
}
|
||||
|
||||
public <T> EventListenerGroup<T> getListenerGroup(EventType<T> eventType) {
|
||||
//noinspection unchecked
|
||||
return (EventListenerGroup<T>) listenerGroupMap.get( eventType );
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public EventListenerRegistry buildRegistry(Map<String, EventType> registeredEventTypes) {
|
||||
// validate contiguity of the event-type ordinals and build the EventListenerGroups array
|
||||
|
||||
final ArrayList<EventType> eventTypeList = new ArrayList<>( registeredEventTypes.values() );
|
||||
eventTypeList.sort( Comparator.comparing( EventType::ordinal ) );
|
||||
|
||||
final EventListenerGroup[] eventListeners = new EventListenerGroup[ eventTypeList.size() ];
|
||||
|
||||
int previous = -1;
|
||||
for ( int i = 0; i < eventTypeList.size(); i++ ) {
|
||||
final EventType eventType = eventTypeList.get( i );
|
||||
|
||||
assert i == eventType.ordinal();
|
||||
assert i - 1 == previous;
|
||||
|
||||
eventListeners[i] = listenerGroupMap.get( eventType );
|
||||
|
||||
previous = i;
|
||||
}
|
||||
|
||||
return new EventListenerRegistryImpl( eventListeners );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* 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.event.service.internal;
|
||||
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiatorContext;
|
||||
|
||||
/**
|
||||
* Service initiator for {@link EventListenerRegistry}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EventListenerServiceInitiator implements SessionFactoryServiceInitiator<EventListenerRegistry> {
|
||||
public static final EventListenerServiceInitiator INSTANCE = new EventListenerServiceInitiator();
|
||||
|
||||
@Override
|
||||
public Class<EventListenerRegistry> getServiceInitiated() {
|
||||
return EventListenerRegistry.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventListenerRegistry initiateService(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryOptions sessionFactoryOptions,
|
||||
ServiceRegistryImplementor registry) {
|
||||
return new EventListenerRegistryImpl( sessionFactory, sessionFactoryOptions, registry );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventListenerRegistry initiateService(SessionFactoryServiceInitiatorContext context) {
|
||||
return new EventListenerRegistryImpl( context.getSessionFactory(), context.getSessionFactoryOptions(), context.getServiceRegistry());
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import org.hibernate.event.spi.PostCommitInsertEventListener;
|
|||
import org.hibernate.event.spi.PostCommitUpdateEventListener;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.jpa.event.spi.CallbackRegistry;
|
||||
|
||||
/**
|
||||
* Historically, the listeners for the post-commit events simply reused the
|
||||
|
@ -27,8 +28,11 @@ class PostCommitEventListenerGroupImpl<T> extends EventListenerGroupImpl<T> {
|
|||
|
||||
private final Class extendedListenerContract;
|
||||
|
||||
public PostCommitEventListenerGroupImpl(EventType<T> eventType, EventListenerRegistryImpl listenerRegistry) {
|
||||
super( eventType, listenerRegistry );
|
||||
public PostCommitEventListenerGroupImpl(
|
||||
EventType<T> eventType,
|
||||
CallbackRegistry callbackRegistry,
|
||||
boolean isJpaBootstrap) {
|
||||
super( eventType, callbackRegistry, isJpaBootstrap );
|
||||
|
||||
if ( eventType == EventType.POST_COMMIT_DELETE ) {
|
||||
this.extendedListenerContract = PostCommitDeleteEventListener.class;
|
||||
|
|
|
@ -19,7 +19,14 @@ import org.hibernate.service.Service;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EventListenerRegistry extends Service, Serializable {
|
||||
void prepare(MetadataImplementor metadata);
|
||||
/**
|
||||
* @deprecated this method was only ever used to initialize the CallbackRegistry
|
||||
* which is now managed as part of the EventEngine
|
||||
*/
|
||||
@Deprecated
|
||||
default void prepare(MetadataImplementor metadata) {
|
||||
// by default do nothing now
|
||||
}
|
||||
|
||||
<T> EventListenerGroup<T> getEventListenerGroup(EventType<T> eventType);
|
||||
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* 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.event.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.internal.EventListenerRegistryImpl;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jpa.event.internal.CallbackRegistryImplementor;
|
||||
import org.hibernate.jpa.event.internal.CallbacksFactory;
|
||||
import org.hibernate.jpa.event.spi.CallbackBuilder;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
|
||||
/**
|
||||
* Composite for the things related to Hibernate's event system.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EventEngine {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final Map<String,EventType> registeredEventTypes;
|
||||
private final EventListenerRegistry listenerRegistry;
|
||||
|
||||
private final CallbackRegistryImplementor callbackRegistry;
|
||||
private final CallbackBuilder callbackBuilder;
|
||||
|
||||
public EventEngine(
|
||||
MetadataImplementor mappings,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// resolve (JPA) callback handlers
|
||||
|
||||
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions() );
|
||||
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder(
|
||||
sessionFactory.getSessionFactoryOptions(),
|
||||
sessionFactory.getServiceRegistry(),
|
||||
mappings.getMetadataBuildingOptions().getReflectionManager()
|
||||
);
|
||||
|
||||
for ( PersistentClass persistentClass : mappings.getEntityBindings() ) {
|
||||
if ( persistentClass.getClassName() == null ) {
|
||||
// we can have dynamic (non-java class) mapping
|
||||
continue;
|
||||
}
|
||||
|
||||
this.callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
|
||||
|
||||
for ( Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator(); propertyIterator.hasNext(); ) {
|
||||
final Property property = propertyIterator.next();
|
||||
|
||||
if ( property.getType().isComponentType() ) {
|
||||
this.callbackBuilder.buildCallbacksForEmbeddable(
|
||||
property,
|
||||
persistentClass.getClassName(),
|
||||
callbackRegistry
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// resolve event types and listeners
|
||||
|
||||
final EventListenerRegistryImpl.Builder listenerRegistryBuilder = new EventListenerRegistryImpl.Builder(
|
||||
callbackRegistry,
|
||||
sessionFactory.getSessionFactoryOptions().isJpaBootstrap()
|
||||
);
|
||||
|
||||
final Map<String,EventType> eventTypes = new HashMap<>();
|
||||
EventType.registerStandardTypes( eventTypes );
|
||||
|
||||
final EventEngineContributions contributionManager = new EventEngineContributions() {
|
||||
@Override
|
||||
public <T> EventType<T> findEventType(String name) {
|
||||
//noinspection unchecked
|
||||
return eventTypes.get( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> EventType<T> contributeEventType(String name, Class<T> listenerRole) {
|
||||
final EventType<T> eventType = registerEventType( name, listenerRole );
|
||||
|
||||
listenerRegistryBuilder.prepareListeners( eventType );
|
||||
|
||||
return eventType;
|
||||
}
|
||||
|
||||
private <T> EventType<T> registerEventType(String name, Class<T> listenerRole) {
|
||||
if ( name == null ) {
|
||||
throw new HibernateException( "Custom event-type name must be non-null." );
|
||||
}
|
||||
|
||||
if ( listenerRole == null ) {
|
||||
throw new HibernateException( "Custom event-type listener role must be non-null." );
|
||||
}
|
||||
|
||||
// make sure it does not match an existing name...
|
||||
if ( eventTypes.containsKey( name ) ) {
|
||||
final EventType<?> existing = eventTypes.get( name );
|
||||
throw new HibernateException(
|
||||
"Custom event-type already registered: " + name + " => " + existing
|
||||
);
|
||||
}
|
||||
|
||||
final EventType<T> eventType = EventType.create(
|
||||
name,
|
||||
listenerRole,
|
||||
eventTypes.size()
|
||||
);
|
||||
|
||||
eventTypes.put( name, eventType );
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> EventType<T> contributeEventType(String name, Class<T> listenerRole, T... defaultListeners) {
|
||||
final EventType<T> eventType = contributeEventType( name, listenerRole );
|
||||
|
||||
if ( defaultListeners != null ) {
|
||||
final EventListenerGroup<T> listenerGroup = listenerRegistryBuilder.getListenerGroup( eventType );
|
||||
listenerGroup.appendListeners( defaultListeners );
|
||||
}
|
||||
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void configureListeners(
|
||||
EventType<T> eventType,
|
||||
Consumer<EventListenerGroup<T>> action) {
|
||||
if ( ! eventTypes.containsValue( eventType ) ) {
|
||||
throw new HibernateException( "EventType [" + eventType + "] not registered" );
|
||||
}
|
||||
|
||||
action.accept( listenerRegistryBuilder.getListenerGroup( eventType ) );
|
||||
}
|
||||
};
|
||||
|
||||
final Collection<EventEngineContributor> discoveredContributors = sessionFactory.getServiceRegistry()
|
||||
.getService( ClassLoaderService.class )
|
||||
.loadJavaServices( EventEngineContributor.class );
|
||||
if ( CollectionHelper.isNotEmpty( discoveredContributors ) ) {
|
||||
for ( EventEngineContributor contributor : discoveredContributors ) {
|
||||
contributor.contribute( contributionManager );
|
||||
}
|
||||
}
|
||||
|
||||
this.registeredEventTypes = Collections.unmodifiableMap( eventTypes );
|
||||
this.listenerRegistry = listenerRegistryBuilder.buildRegistry( registeredEventTypes );
|
||||
}
|
||||
|
||||
public Collection<EventType<?>> getRegisteredEventTypes() {
|
||||
//noinspection unchecked,rawtypes
|
||||
return (Collection) registeredEventTypes.values();
|
||||
}
|
||||
|
||||
public <T> EventType<T> findRegisteredEventType(String name) {
|
||||
//noinspection unchecked
|
||||
return registeredEventTypes.get( name );
|
||||
}
|
||||
|
||||
public EventListenerRegistry getListenerRegistry() {
|
||||
return listenerRegistry;
|
||||
}
|
||||
|
||||
public CallbackRegistryImplementor getCallbackRegistry() {
|
||||
return callbackRegistry;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if ( listenerRegistry instanceof Stoppable ) {
|
||||
( (Stoppable) listenerRegistry ).stop();
|
||||
}
|
||||
|
||||
callbackRegistry.release();
|
||||
|
||||
callbackBuilder.release();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.event.spi;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
|
||||
/**
|
||||
* Callback for {@link EventEngineContributor}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EventEngineContributions {
|
||||
/**
|
||||
* Return the EventType by name, if one
|
||||
*/
|
||||
<T> EventType<T> findEventType(String name);
|
||||
|
||||
/**
|
||||
* Register a custom event type.
|
||||
*
|
||||
* @apiNote We except the "raw" state rather than an `EventType` instance to account for
|
||||
* the `EventType#ordinal` property. All registered types must be contiguous, so we handle
|
||||
* the ordinality behind the scenes
|
||||
*/
|
||||
<T> EventType<T> contributeEventType(String name, Class<T> listenerRole);
|
||||
|
||||
/**
|
||||
* Register a custom event type with a default listener.
|
||||
*/
|
||||
<T> EventType<T> contributeEventType(String name, Class<T> listenerRole, T... defaultListener);
|
||||
|
||||
/**
|
||||
* Perform an action against the listener group for the specified event-type
|
||||
*/
|
||||
<T> void configureListeners(EventType<T> eventType, Consumer<EventListenerGroup<T>> action);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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.event.spi;
|
||||
|
||||
/**
|
||||
* Integration contract for contributing event types and listeners to the Hibernate event system.
|
||||
*
|
||||
* Discoverable via Java's service loading mechanism ({@link java.util.ServiceLoader})
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EventEngineContributor {
|
||||
/**
|
||||
* Apply the contributions
|
||||
*/
|
||||
void contribute(EventEngineContributions target);
|
||||
}
|
|
@ -10,14 +10,12 @@ import java.lang.reflect.Field;
|
|||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Enumeration of the recognized types of events, including meta-information about each.
|
||||
|
@ -25,8 +23,10 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public final class EventType<T> {
|
||||
private static final Logger LOG = CoreLogging.logger( EventType.class );
|
||||
private static AtomicInteger typeCounter = new AtomicInteger( 0 );
|
||||
/**
|
||||
* Used to assign ordinals for the standard event-types
|
||||
*/
|
||||
private static AtomicInteger STANDARD_TYPE_COUNTER = new AtomicInteger( 0 );
|
||||
|
||||
public static final EventType<LoadEventListener> LOAD = create( "load", LoadEventListener.class );
|
||||
public static final EventType<ResolveNaturalIdEventListener> RESOLVE_NATURAL_ID = create( "resolve-natural-id", ResolveNaturalIdEventListener.class );
|
||||
|
@ -128,11 +128,12 @@ public final class EventType<T> {
|
|||
* Maintain a map of {@link EventType} instances keyed by name for lookup by name as well as {@link #values()}
|
||||
* resolution.
|
||||
*/
|
||||
private static final Map<String,EventType> EVENT_TYPE_BY_NAME_MAP = AccessController.doPrivileged(
|
||||
@SuppressWarnings({"rawtypes", "Convert2Lambda"})
|
||||
private static final Map<String,EventType> STANDARD_TYPE_BY_NAME_MAP = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Map<String, EventType>>() {
|
||||
@Override
|
||||
public Map<String, EventType> run() {
|
||||
final Map<String, EventType> typeByNameMap = new ConcurrentHashMap<>();
|
||||
final Map<String, EventType> typeByNameMap = new HashMap<>();
|
||||
for ( Field field : EventType.class.getDeclaredFields() ) {
|
||||
if ( EventType.class.isAssignableFrom( field.getType() ) ) {
|
||||
try {
|
||||
|
@ -144,11 +145,20 @@ public final class EventType<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
return typeByNameMap;
|
||||
|
||||
return Collections.unmodifiableMap( typeByNameMap );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
private static <T> EventType<T> create(String name, Class<T> listenerRole) {
|
||||
return new EventType<>( name, listenerRole, STANDARD_TYPE_COUNTER.getAndIncrement(), true );
|
||||
}
|
||||
|
||||
public static <T> EventType<T> create(String name, Class<T> listenerRole, int ordinal) {
|
||||
return new EventType<>( name, listenerRole, ordinal, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an {@link EventType} by its name
|
||||
*
|
||||
|
@ -158,11 +168,12 @@ public final class EventType<T> {
|
|||
*
|
||||
* @throws HibernateException If eventName is null, or if eventName does not correlate to any known event type.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static EventType resolveEventTypeByName(final String eventName) {
|
||||
if ( eventName == null ) {
|
||||
throw new HibernateException( "event name to resolve cannot be null" );
|
||||
}
|
||||
final EventType eventType = EVENT_TYPE_BY_NAME_MAP.get( eventName );
|
||||
final EventType eventType = STANDARD_TYPE_BY_NAME_MAP.get( eventName );
|
||||
if ( eventType == null ) {
|
||||
throw new HibernateException( "Unable to locate proper event type for event name [" + eventName + "]" );
|
||||
}
|
||||
|
@ -170,37 +181,44 @@ public final class EventType<T> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a collection of all {@link EventType} instances.
|
||||
*
|
||||
* @return All {@link EventType} instances
|
||||
* Get a collection of all the standard {@link EventType} instances.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static Collection<EventType> values() {
|
||||
return EVENT_TYPE_BY_NAME_MAP.values();
|
||||
return STANDARD_TYPE_BY_NAME_MAP.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used from {@link EventEngine} to "prime" the registered event-type map.
|
||||
*
|
||||
* Simply copy the values into its (passed) Map
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
static void registerStandardTypes(Map<String, EventType> eventTypes) {
|
||||
eventTypes.putAll( STANDARD_TYPE_BY_NAME_MAP );
|
||||
}
|
||||
|
||||
private final String eventName;
|
||||
private final Class<T> baseListenerInterface;
|
||||
private final int ordinal;
|
||||
private final boolean isStandardEvent;
|
||||
|
||||
private EventType(String eventName, Class<T> baseListenerInterface) {
|
||||
private EventType(String eventName, Class<T> baseListenerInterface, int ordinal, boolean isStandardEvent) {
|
||||
this.eventName = eventName;
|
||||
this.baseListenerInterface = baseListenerInterface;
|
||||
this.ordinal = typeCounter.getAndIncrement();
|
||||
this.ordinal = ordinal;
|
||||
this.isStandardEvent = isStandardEvent;
|
||||
}
|
||||
|
||||
public String eventName() {
|
||||
return eventName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Class baseListenerInterface() {
|
||||
return baseListenerInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return eventName();
|
||||
}
|
||||
|
||||
/**
|
||||
* EventType is effectively an enumeration. Since there is a known, limited number of possible types, we expose an
|
||||
* ordinal for each in order to be able to efficiently do associations elsewhere in the codebase (array vs. Map)
|
||||
|
@ -213,4 +231,15 @@ public final class EventType<T> {
|
|||
return ordinal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this event-type one of the standard event-types?
|
||||
*/
|
||||
public boolean isStandardEvent() {
|
||||
return isStandardEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return eventName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ import org.hibernate.engine.spi.SessionOwner;
|
|||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventEngine;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
|
@ -171,6 +172,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
private final transient Map<String,Object> properties;
|
||||
|
||||
private final transient SessionFactoryServiceRegistry serviceRegistry;
|
||||
private final transient EventEngine eventEngine;
|
||||
private final transient JdbcServices jdbcServices;
|
||||
|
||||
// todo : org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor too?
|
||||
|
@ -212,6 +214,8 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
|
||||
bootMetamodel.initSessionFactory( this );
|
||||
|
||||
this.eventEngine = new EventEngine( metadata, this );
|
||||
|
||||
final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class );
|
||||
|
||||
String sfName = settings.getSessionFactoryName();
|
||||
|
@ -578,6 +582,11 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
return queryEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventEngine getEventEngine() {
|
||||
return eventEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcServices getJdbcServices() {
|
||||
return jdbcServices;
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.boot.spi.SessionFactoryOptions;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.event.spi.CallbackBuilder;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* The intent of this class is to use a lighter implementation
|
||||
|
@ -18,9 +19,8 @@ import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
|||
* {@link org.hibernate.boot.spi.SessionFactoryOptions#areJPACallbacksEnabled()}
|
||||
*/
|
||||
public final class CallbacksFactory {
|
||||
|
||||
public static CallbackRegistryImplementor buildCallbackRegistry(SessionFactoryImplementor sessionFactory) {
|
||||
if ( jpaCallBacksEnabled( sessionFactory ) ) {
|
||||
public static CallbackRegistryImplementor buildCallbackRegistry(SessionFactoryOptions options) {
|
||||
if ( jpaCallBacksEnabled( options ) ) {
|
||||
return new CallbackRegistryImpl();
|
||||
}
|
||||
else {
|
||||
|
@ -29,10 +29,11 @@ public final class CallbacksFactory {
|
|||
}
|
||||
|
||||
public static CallbackBuilder buildCallbackBuilder(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryOptions options,
|
||||
ServiceRegistry serviceRegistry,
|
||||
ReflectionManager reflectionManager) {
|
||||
if ( jpaCallBacksEnabled( sessionFactory ) ) {
|
||||
final ManagedBeanRegistry managedBeanRegistry = sessionFactory.getServiceRegistry().getService( ManagedBeanRegistry.class );
|
||||
if ( jpaCallBacksEnabled( options ) ) {
|
||||
final ManagedBeanRegistry managedBeanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
|
||||
return new CallbackBuilderLegacyImpl(
|
||||
managedBeanRegistry,
|
||||
reflectionManager
|
||||
|
@ -43,8 +44,7 @@ public final class CallbacksFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean jpaCallBacksEnabled(SessionFactoryImplementor sessionFactory) {
|
||||
SessionFactoryOptions options = sessionFactory.getSessionFactoryOptions();
|
||||
private static boolean jpaCallBacksEnabled(SessionFactoryOptions options) {
|
||||
return options.areJPACallbacksEnabled();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,11 @@ public abstract class AbstractLogicalConnectionImplementor implements LogicalCon
|
|||
log.trace( "LogicalConnection#afterStatement" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTransactionCompletion() {
|
||||
log.trace( "LogicalConnection#beforeTransactionCompletion" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTransaction() {
|
||||
log.trace( "LogicalConnection#afterTransaction" );
|
||||
|
|
|
@ -148,6 +148,15 @@ public class LogicalConnectionManagedImpl extends AbstractLogicalConnectionImple
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTransactionCompletion() {
|
||||
super.beforeTransactionCompletion();
|
||||
if ( connectionHandlingMode.getReleaseMode() == ConnectionReleaseMode.BEFORE_TRANSACTION_COMPLETION ) {
|
||||
log.debug( "Initiating JDBC connection release from beforeTransactionCompletion" );
|
||||
releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTransaction() {
|
||||
super.afterTransaction();
|
||||
|
|
|
@ -35,6 +35,13 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
|
|||
*/
|
||||
void afterStatement();
|
||||
|
||||
/**
|
||||
* Notification indicating a transaction is about to be completed, so to trigger
|
||||
* releasing of the connection if needed ({@link org.hibernate.ConnectionReleaseMode#BEFORE_TRANSACTION_COMPLETION}
|
||||
* is enabled)
|
||||
*/
|
||||
void beforeTransactionCompletion();
|
||||
|
||||
/**
|
||||
* Notification indicating a transaction has completed to trigger
|
||||
* {@link org.hibernate.ConnectionReleaseMode#AFTER_TRANSACTION} releasing if needed
|
||||
|
|
|
@ -15,6 +15,7 @@ import static org.hibernate.ConnectionAcquisitionMode.AS_NEEDED;
|
|||
import static org.hibernate.ConnectionAcquisitionMode.IMMEDIATELY;
|
||||
import static org.hibernate.ConnectionReleaseMode.AFTER_STATEMENT;
|
||||
import static org.hibernate.ConnectionReleaseMode.AFTER_TRANSACTION;
|
||||
import static org.hibernate.ConnectionReleaseMode.BEFORE_TRANSACTION_COMPLETION;
|
||||
import static org.hibernate.ConnectionReleaseMode.ON_CLOSE;
|
||||
|
||||
/**
|
||||
|
@ -39,6 +40,11 @@ public enum PhysicalConnectionHandlingMode {
|
|||
* after each statement is executed.
|
||||
*/
|
||||
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT( AS_NEEDED, AFTER_STATEMENT ),
|
||||
/**
|
||||
* The Connection will be acquired as soon as it is needed; it will be released
|
||||
* before commit/rollback.
|
||||
*/
|
||||
DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION( AS_NEEDED, BEFORE_TRANSACTION_COMPLETION ),
|
||||
/**
|
||||
* The Connection will be acquired as soon as it is needed; it will be released
|
||||
* after each transaction is completed.
|
||||
|
@ -99,6 +105,9 @@ public enum PhysicalConnectionHandlingMode {
|
|||
case AFTER_STATEMENT: {
|
||||
return DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT;
|
||||
}
|
||||
case BEFORE_TRANSACTION_COMPLETION: {
|
||||
return DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION;
|
||||
}
|
||||
case AFTER_TRANSACTION: {
|
||||
return DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
|||
import org.hibernate.service.spi.SessionFactoryServiceInitiatorContext;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -28,11 +30,12 @@ public class SessionFactoryServiceRegistryImpl
|
|||
extends AbstractServiceRegistryImpl
|
||||
implements SessionFactoryServiceRegistry, SessionFactoryServiceInitiatorContext {
|
||||
|
||||
private static final Logger log = Logger.getLogger( SessionFactoryServiceRegistryImpl.class );
|
||||
|
||||
private final SessionFactoryOptions sessionFactoryOptions;
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private EventListenerRegistry cachedEventListenerRegistry;
|
||||
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public SessionFactoryServiceRegistryImpl(
|
||||
ServiceRegistryImplementor parent,
|
||||
List<SessionFactoryServiceInitiator> initiators,
|
||||
|
@ -63,7 +66,7 @@ public class SessionFactoryServiceRegistryImpl
|
|||
|
||||
@Override
|
||||
public <R extends Service> void configureService(ServiceBinding<R> serviceBinding) {
|
||||
if ( Configurable.class.isInstance( serviceBinding.getService() ) ) {
|
||||
if ( serviceBinding.getService() instanceof Configurable ) {
|
||||
( (Configurable) serviceBinding.getService() ).configure( getService( ConfigurationService.class ).getSettings() );
|
||||
}
|
||||
}
|
||||
|
@ -85,22 +88,16 @@ public class SessionFactoryServiceRegistryImpl
|
|||
|
||||
@Override
|
||||
public <R extends Service> R getService(Class<R> serviceRole) {
|
||||
|
||||
//HHH-11051 cache EventListenerRegistry
|
||||
if ( serviceRole.equals( EventListenerRegistry.class ) ) {
|
||||
if ( cachedEventListenerRegistry == null ) {
|
||||
cachedEventListenerRegistry = (EventListenerRegistry) super.getService( serviceRole );
|
||||
}
|
||||
return (R) cachedEventListenerRegistry;
|
||||
log.debug(
|
||||
"EventListenerRegistry access via ServiceRegistry is deprecated. " +
|
||||
"Use `sessionFactory.getEventEngine().getListenerRegistry()` instead"
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return (R) sessionFactory.getEventEngine().getListenerRegistry();
|
||||
}
|
||||
|
||||
return super.getService( serviceRole );
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void destroy() {
|
||||
super.destroy();
|
||||
this.cachedEventListenerRegistry = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.engine.query.spi.NativeQueryInterpreterInitiator;
|
||||
import org.hibernate.engine.spi.CacheInitiator;
|
||||
import org.hibernate.event.service.internal.EventListenerServiceInitiator;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||
import org.hibernate.stat.internal.StatisticsInitiator;
|
||||
|
||||
|
@ -26,7 +25,6 @@ public final class StandardSessionFactoryServiceInitiators {
|
|||
public static List<SessionFactoryServiceInitiator> buildStandardServiceInitiatorList() {
|
||||
final ArrayList<SessionFactoryServiceInitiator> serviceInitiators = new ArrayList<>();
|
||||
|
||||
serviceInitiators.add( EventListenerServiceInitiator.INSTANCE );
|
||||
serviceInitiators.add( StatisticsInitiator.INSTANCE );
|
||||
serviceInitiators.add( CacheInitiator.INSTANCE );
|
||||
serviceInitiators.add( NativeQueryInterpreterInitiator.INSTANCE );
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.event.spi.LoadEventListener;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
|
||||
@TestForIssue( jiraKey = "HHH-13890" )
|
||||
public class CustomEventTypeTest {
|
||||
private final String EVENT_TYPE_NAME = "operation";
|
||||
private final String OTHER_EVENT_TYPE_NAME = "other-operation";
|
||||
|
||||
@Test
|
||||
public void testAddCustomEventType() {
|
||||
final int numberOfEventTypesOriginal = EventType.values().size();
|
||||
|
||||
try {
|
||||
EventType.resolveEventTypeByName( EVENT_TYPE_NAME );
|
||||
fail( "Should have thrown HibernateException" );
|
||||
}
|
||||
catch(HibernateException expected) {
|
||||
}
|
||||
|
||||
final EventType<CustomListener> eventType = EventType.addCustomEventType( EVENT_TYPE_NAME, CustomListener.class );
|
||||
assertEquals( EVENT_TYPE_NAME, eventType.eventName() );
|
||||
assertEquals( CustomListener.class, eventType.baseListenerInterface() );
|
||||
assertEquals( numberOfEventTypesOriginal, eventType.ordinal() );
|
||||
assertTrue( EventType.values().contains( eventType ) );
|
||||
assertEquals( numberOfEventTypesOriginal + 1, EventType.values().size() );
|
||||
|
||||
final EventType<OtherCustomListener> otherEventType = EventType.addCustomEventType( OTHER_EVENT_TYPE_NAME, OtherCustomListener.class );
|
||||
assertEquals( OTHER_EVENT_TYPE_NAME, otherEventType.eventName() );
|
||||
assertEquals( OtherCustomListener.class, otherEventType.baseListenerInterface() );
|
||||
assertEquals( numberOfEventTypesOriginal + 1, otherEventType.ordinal() );
|
||||
assertEquals( numberOfEventTypesOriginal + 2, EventType.values().size() );
|
||||
|
||||
// Adding an event type with the same name and base listener as one that exists, should be OK.
|
||||
EventType.addCustomEventType( "load", LoadEventListener.class );
|
||||
|
||||
// Adding an event type with the same name but different listener as one that exists, should fail.
|
||||
try {
|
||||
EventType.addCustomEventType( "load", CustomListener.class );
|
||||
fail( "Should have thrown HibernateException" );
|
||||
}
|
||||
catch (HibernateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public interface CustomListener {
|
||||
}
|
||||
|
||||
public interface OtherCustomListener {
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package org.hibernate.event.service.internal;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.hibernate.event.service.spi.DuplicationStrategy;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
|
@ -32,7 +31,7 @@ public class EventListenerDuplicationStrategyTest {
|
|||
|
||||
Tracker tracker = new Tracker();
|
||||
ClearEvent event = new ClearEvent( null );
|
||||
EventListenerGroup<ClearEventListener> listenerGroup = new EventListenerGroupImpl( EventType.CLEAR, null );
|
||||
EventListenerGroup<ClearEventListener> listenerGroup = new EventListenerGroupImpl( EventType.CLEAR, null, false );
|
||||
|
||||
@Test
|
||||
public void testListenersIterator() {
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.id;
|
|||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
|
@ -47,7 +46,7 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
|
|||
|
||||
private StandardServiceRegistry serviceRegistry;
|
||||
private SessionFactoryImplementor sessionFactory;
|
||||
private SequenceStyleGenerator generator;
|
||||
private SequenceGenerator generator;
|
||||
private SessionImplementor sessionImpl;
|
||||
private SequenceValueExtractor sequenceValueExtractor;
|
||||
|
||||
|
@ -58,22 +57,19 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
|
|||
.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
|
||||
.build();
|
||||
|
||||
generator = new SequenceStyleGenerator();
|
||||
|
||||
MetadataBuildingContext buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry );
|
||||
// Build the properties used to configure the id generator
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty( SequenceStyleGenerator.SEQUENCE_PARAM, TEST_SEQUENCE );
|
||||
properties.setProperty( SequenceStyleGenerator.OPT_PARAM, "legacy-hilo" );
|
||||
properties.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "0" ); // JPA allocationSize of 1
|
||||
properties.setProperty( SequenceGenerator.SEQUENCE, TEST_SEQUENCE );
|
||||
properties.setProperty( SequenceHiLoGenerator.MAX_LO, "0" ); // JPA allocationSize of 1
|
||||
|
||||
properties.put(
|
||||
PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER,
|
||||
new ObjectNameNormalizer() {
|
||||
@Override
|
||||
protected MetadataBuildingContext getBuildingContext() {
|
||||
return new MetadataBuildingContextTestingImpl( serviceRegistry );
|
||||
}
|
||||
}
|
||||
buildingContext.getObjectNameNormalizer()
|
||||
);
|
||||
|
||||
generator = new SequenceHiLoGenerator();
|
||||
generator.configure( StandardBasicTypes.LONG, properties, serviceRegistry );
|
||||
|
||||
final Metadata metadata = new MetadataSources( serviceRegistry ).buildMetadata();
|
||||
|
@ -84,9 +80,9 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
public void tearDown() {
|
||||
if ( sessionImpl != null && !sessionImpl.isClosed() ) {
|
||||
((Session) sessionImpl).close();
|
||||
sessionImpl.close();
|
||||
}
|
||||
if ( sessionFactory != null ) {
|
||||
sessionFactory.close();
|
||||
|
@ -100,31 +96,23 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
|
|||
public void testHiLoAlgorithm() {
|
||||
sessionImpl = (SessionImpl) sessionFactory.openSession();
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// historically the hilo generators skipped the initial block of values;
|
||||
// so the first generated id value is maxlo + 1, here be 4
|
||||
assertEquals( 1L, generateValue() );
|
||||
|
||||
// which should also perform the first read on the sequence which should set it to its "start with" value (1)
|
||||
assertEquals( 1L, extractSequenceValue() );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
assertEquals( 2L, generateValue() );
|
||||
assertEquals( 2L, extractSequenceValue() );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
assertEquals( 3L, generateValue() );
|
||||
assertEquals( 3L, extractSequenceValue() );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
assertEquals( 4L, generateValue() );
|
||||
assertEquals( 4L, extractSequenceValue() );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
assertEquals( 5L, generateValue() );
|
||||
assertEquals( 5L, extractSequenceValue() );
|
||||
|
||||
((Session) sessionImpl).close();
|
||||
sessionImpl.close();
|
||||
}
|
||||
|
||||
private long extractSequenceValue() {
|
||||
|
@ -133,7 +121,7 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
|
|||
|
||||
private long generateValue() {
|
||||
Long generatedValue;
|
||||
Transaction transaction = ((Session) sessionImpl).beginTransaction();
|
||||
Transaction transaction = sessionImpl.beginTransaction();
|
||||
generatedValue = (Long) generator.generate( sessionImpl, null );
|
||||
transaction.commit();
|
||||
return generatedValue.longValue();
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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.id;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.model.naming.ObjectNameNormalizer;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.internal.SessionImpl;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.hibernate.testing.boot.MetadataBuildingContextTestingImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@RequiresDialectFeature(DialectChecks.SupportsSequences.class)
|
||||
public class SequenceStyleGeneratorBehavesLikeSequeceHiloGeneratorWitZeroIncrementSizeTest extends BaseUnitTestCase {
|
||||
private static final String TEST_SEQUENCE = "test_sequence";
|
||||
|
||||
private StandardServiceRegistry serviceRegistry;
|
||||
private SessionFactoryImplementor sessionFactory;
|
||||
private SequenceStyleGenerator generator;
|
||||
private SessionImplementor sessionImpl;
|
||||
private SequenceValueExtractor sequenceValueExtractor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
serviceRegistry = new StandardServiceRegistryBuilder()
|
||||
.enableAutoClose()
|
||||
.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
|
||||
.build();
|
||||
|
||||
generator = new SequenceStyleGenerator();
|
||||
|
||||
// Build the properties used to configure the id generator
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty( SequenceStyleGenerator.SEQUENCE_PARAM, TEST_SEQUENCE );
|
||||
properties.setProperty( SequenceStyleGenerator.OPT_PARAM, "legacy-hilo" );
|
||||
properties.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "0" ); // JPA allocationSize of 1
|
||||
properties.put(
|
||||
PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER,
|
||||
new ObjectNameNormalizer() {
|
||||
@Override
|
||||
protected MetadataBuildingContext getBuildingContext() {
|
||||
return new MetadataBuildingContextTestingImpl( serviceRegistry );
|
||||
}
|
||||
}
|
||||
);
|
||||
generator.configure( StandardBasicTypes.LONG, properties, serviceRegistry );
|
||||
|
||||
final Metadata metadata = new MetadataSources( serviceRegistry ).buildMetadata();
|
||||
generator.registerExportables( metadata.getDatabase() );
|
||||
|
||||
sessionFactory = (SessionFactoryImplementor) metadata.buildSessionFactory();
|
||||
sequenceValueExtractor = new SequenceValueExtractor( sessionFactory.getDialect(), TEST_SEQUENCE );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if ( sessionImpl != null && !sessionImpl.isClosed() ) {
|
||||
sessionImpl.close();
|
||||
}
|
||||
if ( sessionFactory != null ) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
if ( serviceRegistry != null ) {
|
||||
StandardServiceRegistryBuilder.destroy( serviceRegistry );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHiLoAlgorithm() {
|
||||
sessionImpl = (SessionImpl) sessionFactory.openSession();
|
||||
|
||||
assertEquals( 1L, generateValue() );
|
||||
|
||||
assertEquals( 1L, extractSequenceValue() );
|
||||
|
||||
assertEquals( 2L, generateValue() );
|
||||
assertEquals( 2L, extractSequenceValue() );
|
||||
|
||||
assertEquals( 3L, generateValue() );
|
||||
assertEquals( 3L, extractSequenceValue() );
|
||||
|
||||
assertEquals( 4L, generateValue() );
|
||||
assertEquals( 4L, extractSequenceValue() );
|
||||
|
||||
assertEquals( 5L, generateValue() );
|
||||
assertEquals( 5L, extractSequenceValue() );
|
||||
|
||||
sessionImpl.close();
|
||||
}
|
||||
|
||||
private long extractSequenceValue() {
|
||||
return sequenceValueExtractor.extractSequenceValue( sessionImpl );
|
||||
}
|
||||
|
||||
private long generateValue() {
|
||||
Long generatedValue;
|
||||
Transaction transaction = sessionImpl.beginTransaction();
|
||||
generatedValue = (Long) generator.generate( sessionImpl, null );
|
||||
transaction.commit();
|
||||
return generatedValue.longValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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.connections;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.internal.UserSuppliedConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.env.ConnectionProviderBuilder;
|
||||
import org.hibernate.testing.jta.TestingJtaBootstrap;
|
||||
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
|
||||
import org.hibernate.testing.transaction.TransactionUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.xa.XAResource;
|
||||
import javax.transaction.xa.Xid;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Luis Barreiro
|
||||
*/
|
||||
@RequiresDialect( H2Dialect.class )
|
||||
public class BeforeCompletionReleaseTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Map getConfig() {
|
||||
Map config = super.getConfig();
|
||||
TestingJtaBootstrap.prepare( config );
|
||||
config.put( AvailableSettings.CONNECTION_PROVIDER, new ConnectionProviderDecorator() );
|
||||
config.put( AvailableSettings.CONNECTION_HANDLING, PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION );
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { Thing.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionAcquisitionCount() {
|
||||
TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Thing thing = new Thing();
|
||||
thing.setId( 1 );
|
||||
entityManager.persist( thing );
|
||||
});
|
||||
}
|
||||
|
||||
// --- //
|
||||
|
||||
@Entity(name = "Thing")
|
||||
@Table(name = "Thing")
|
||||
public static class Thing {
|
||||
|
||||
@Id
|
||||
public Integer id;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
// --- //
|
||||
|
||||
public static class ConnectionProviderDecorator extends UserSuppliedConnectionProviderImpl {
|
||||
|
||||
private final ConnectionProvider dataSource;
|
||||
|
||||
public ConnectionProviderDecorator() {
|
||||
this.dataSource = ConnectionProviderBuilder.buildConnectionProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
Connection connection = dataSource.getConnection();
|
||||
|
||||
try {
|
||||
Transaction tx = TestingJtaPlatformImpl.transactionManager().getTransaction();
|
||||
if ( tx != null) {
|
||||
tx.enlistResource( new XAResource() {
|
||||
|
||||
@Override public void commit(Xid xid, boolean onePhase) {
|
||||
try {
|
||||
assertTrue( "Connection should be closed prior to commit", connection.isClosed() );
|
||||
} catch ( SQLException e ) {
|
||||
fail( "Unexpected SQLException: " + e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void end(Xid xid, int flags) {
|
||||
}
|
||||
|
||||
@Override public void forget(Xid xid) {
|
||||
}
|
||||
|
||||
@Override public int getTransactionTimeout() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public boolean isSameRM(XAResource xares) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public int prepare(Xid xid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public Xid[] recover(int flag) {
|
||||
return new Xid[0];
|
||||
}
|
||||
|
||||
@Override public void rollback(Xid xid) {
|
||||
try {
|
||||
assertTrue( "Connection should be closed prior to rollback", connection.isClosed() );
|
||||
} catch ( SQLException e ) {
|
||||
fail( "Unexpected SQLException: " + e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean setTransactionTimeout(int seconds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public void start(Xid xid, int flags) {
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch ( SystemException | RollbackException e ) {
|
||||
fail( e.getMessage() );
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection(Connection connection) throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.jpa.event.spi.CallbackRegistry;
|
||||
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@TestForIssue( jiraKey = "HHH-13890")
|
||||
public class CustomEventTypeRegisterListenerTest extends BaseCoreFunctionalTestCase {
|
||||
public enum Category {
|
||||
CLOTHING,
|
||||
FURNITURE
|
||||
}
|
||||
|
||||
private final TheIntegrator theIntegrator = new TheIntegrator();
|
||||
|
||||
@Override
|
||||
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
|
||||
builder.applyIntegrator( theIntegrator );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetListenerClasses() {
|
||||
testNormalUsage( theIntegrator.eventTypeForSetListenerClasses(), UsesSetClasses.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetListenerObjects() {
|
||||
testNormalUsage( theIntegrator.eventTypeForSetListenerObjects(), UsesSetObjects.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendListenerClasses() {
|
||||
testNormalUsage( theIntegrator.eventTypeForAppendListenerClasses(), UsesAppendClasses.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendListenerObjects() {
|
||||
testNormalUsage( theIntegrator.eventTypeForAppendListenerObjects(), UsesAppendObjects.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrependListenerClasses() {
|
||||
testNormalUsage( theIntegrator.eventTypeForPrependListenerClasses(), UsesPrependClasses.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrependListenerObjects() {
|
||||
testNormalUsage( theIntegrator.eventTypeForPrependListenerObjects(), UsesPrependObjects.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisteredEventType() {
|
||||
final EventListenerRegistry eventListenerRegistry =
|
||||
sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
|
||||
try {
|
||||
eventListenerRegistry.getEventListenerGroup( theIntegrator.eventTypeUnregistered() );
|
||||
fail( "HibernateException should have been thrown." );
|
||||
}
|
||||
catch (HibernateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Listener> void testNormalUsage(EventType<T> eventType, Class<T> baseListenerClass) {
|
||||
final Item clothing = new Item( Category.CLOTHING );
|
||||
final Item furniture = new Item( Category.FURNITURE );
|
||||
final Item other = new Item();
|
||||
|
||||
final EventListenerRegistry eventListenerRegistry =
|
||||
sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
|
||||
final EventListenerGroup<T> group =
|
||||
eventListenerRegistry.getEventListenerGroup( eventType );
|
||||
for ( Object listener : group.listeners() ) {
|
||||
assertNotNull( ( (ItemNameGeneratorListener) listener).getCallbackRegistry() );
|
||||
}
|
||||
|
||||
final ItemNameGeneratorEvent clothingEvent = new ItemNameGeneratorEvent( clothing );
|
||||
group.fireEventOnEachListener( clothingEvent, Listener::onGenerateItemName );
|
||||
assertEquals( "C100", clothing.name );
|
||||
|
||||
final ItemNameGeneratorEvent furnitureEvent = new ItemNameGeneratorEvent( furniture );
|
||||
group.fireEventOnEachListener( furnitureEvent, Listener::onGenerateItemName );
|
||||
assertEquals( "F200", furniture.name );
|
||||
|
||||
final ItemNameGeneratorEvent otherEvent = new ItemNameGeneratorEvent( other );
|
||||
group.fireEventOnEachListener( otherEvent, Listener::onGenerateItemName );
|
||||
assertEquals( "O300", other.name );
|
||||
}
|
||||
|
||||
@Entity(name = "Item")
|
||||
public static class Item {
|
||||
|
||||
@Id
|
||||
private int id;
|
||||
|
||||
private Category category;
|
||||
|
||||
private String name;
|
||||
|
||||
Item() {
|
||||
}
|
||||
Item(Category category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ItemNameGeneratorEvent {
|
||||
private Item item;
|
||||
|
||||
public ItemNameGeneratorEvent(Item item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onGenerateItemName(ItemNameGeneratorEvent event);
|
||||
}
|
||||
|
||||
public interface ItemNameGeneratorListener extends Listener, CallbackRegistryConsumer {
|
||||
CallbackRegistry getCallbackRegistry();
|
||||
}
|
||||
|
||||
public interface UsesSetClasses extends Listener {
|
||||
}
|
||||
public interface UsesSetObjects extends Listener {
|
||||
}
|
||||
public interface UsesAppendClasses extends Listener {
|
||||
}
|
||||
public interface UsesAppendObjects extends Listener{
|
||||
}
|
||||
public interface UsesPrependClasses extends Listener {
|
||||
}
|
||||
public interface UsesPrependObjects extends Listener {
|
||||
}
|
||||
public interface Unregistered {
|
||||
}
|
||||
|
||||
public static abstract class AbstractItemNameGeneratorListener implements ItemNameGeneratorListener {
|
||||
private AtomicInteger counter;
|
||||
private CallbackRegistry callbackRegistry = null;
|
||||
|
||||
protected AbstractItemNameGeneratorListener(int startValue) {
|
||||
counter = new AtomicInteger( startValue );
|
||||
}
|
||||
|
||||
public void onGenerateItemName(ItemNameGeneratorEvent event) {
|
||||
if ( event.item.name == null && getCategory() == event.item.category ) {
|
||||
event.item.name = getPrefix() + counter.getAndIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Category getCategory();
|
||||
public abstract String getPrefix();
|
||||
|
||||
@Override
|
||||
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
|
||||
this.callbackRegistry = callbackRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallbackRegistry getCallbackRegistry() {
|
||||
return callbackRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class ClothingGeneratorListener extends AbstractItemNameGeneratorListener {
|
||||
protected ClothingGeneratorListener() {
|
||||
super( 100 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategory() {
|
||||
return Category.CLOTHING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "C";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ClothingGeneratorListenerSetClasses extends ClothingGeneratorListener implements UsesSetClasses {
|
||||
}
|
||||
public static class ClothingGeneratorListenerSetObjects extends ClothingGeneratorListener implements UsesSetObjects {
|
||||
}
|
||||
public static class ClothingGeneratorListenerAppendClasses extends ClothingGeneratorListener implements UsesAppendClasses {
|
||||
}
|
||||
public static class ClothingGeneratorListenerAppendObjects extends ClothingGeneratorListener implements UsesAppendObjects {
|
||||
}
|
||||
public static class ClothingGeneratorListenerPrependClasses extends ClothingGeneratorListener implements UsesPrependClasses {
|
||||
}
|
||||
public static class ClothingGeneratorListenerPrependObjects extends ClothingGeneratorListener implements UsesPrependObjects {
|
||||
}
|
||||
|
||||
public static abstract class FurnitureGeneratorListener extends AbstractItemNameGeneratorListener {
|
||||
protected FurnitureGeneratorListener() {
|
||||
super( 200 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategory() {
|
||||
return Category.FURNITURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "F";
|
||||
}
|
||||
}
|
||||
|
||||
public static class FurnitureGeneratorListenerSetClasses extends FurnitureGeneratorListener implements UsesSetClasses {
|
||||
}
|
||||
public static class FurnitureGeneratorListenerSetObjects extends FurnitureGeneratorListener implements UsesSetObjects {
|
||||
}
|
||||
public static class FurnitureGeneratorListenerAppendClasses extends FurnitureGeneratorListener implements UsesAppendClasses {
|
||||
}
|
||||
public static class FurnitureGeneratorListenerAppendObjects extends FurnitureGeneratorListener implements UsesAppendObjects {
|
||||
}
|
||||
public static class FurnitureGeneratorListenerPrependClasses extends FurnitureGeneratorListener implements UsesPrependClasses {
|
||||
}
|
||||
public static class FurnitureGeneratorListenerPrependObjects extends FurnitureGeneratorListener implements UsesPrependObjects {
|
||||
}
|
||||
|
||||
public static abstract class OtherGeneratorListener extends AbstractItemNameGeneratorListener {
|
||||
protected OtherGeneratorListener() {
|
||||
super( 300 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return "O";
|
||||
}
|
||||
}
|
||||
|
||||
public static class OtherGeneratorListenerSetClasses extends OtherGeneratorListener implements UsesSetClasses {
|
||||
}
|
||||
public static class OtherGeneratorListenerSetObjects extends OtherGeneratorListener implements UsesSetObjects {
|
||||
}
|
||||
public static class OtherGeneratorListenerAppendClasses extends OtherGeneratorListener implements UsesAppendClasses {
|
||||
}
|
||||
public static class OtherGeneratorListenerAppendObjects extends OtherGeneratorListener implements UsesAppendObjects {
|
||||
}
|
||||
public static class OtherGeneratorListenerPrependClasses extends OtherGeneratorListener implements UsesPrependClasses {
|
||||
}
|
||||
public static class OtherGeneratorListenerPrependObjects extends OtherGeneratorListener implements UsesPrependObjects {
|
||||
}
|
||||
|
||||
public static class TheIntegrator implements Integrator {
|
||||
|
||||
private EventType<UsesSetClasses> eventTypeForSetListenerClasses;
|
||||
private EventType<UsesSetObjects> eventTypeForSetListenerObjects;
|
||||
|
||||
private EventType<UsesPrependClasses> eventTypeForPrependListenerClasses;
|
||||
private EventType<UsesPrependObjects> eventTypeForPrependListenerObjects;
|
||||
|
||||
private EventType<UsesAppendClasses> eventTypeForAppendListenerClasses;
|
||||
private EventType<UsesAppendObjects> eventTypeForAppendListenerObjects;
|
||||
|
||||
private EventType<Unregistered> eventTypeUnregistered;
|
||||
|
||||
@Override
|
||||
public void integrate(
|
||||
Metadata metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
|
||||
eventTypeForSetListenerClasses = EventType.addCustomEventType( "eventTypeForSetListenerClasses", UsesSetClasses.class );
|
||||
eventTypeForSetListenerObjects = EventType.addCustomEventType( "eventTypeForSetListenerObjects", UsesSetObjects.class );
|
||||
|
||||
eventTypeForPrependListenerClasses = EventType.addCustomEventType( "eventTypeForPrependListenerClasses", UsesPrependClasses.class );
|
||||
eventTypeForPrependListenerObjects = EventType.addCustomEventType( "eventTypeForPrependListenerObjects", UsesPrependObjects.class );
|
||||
|
||||
eventTypeForAppendListenerClasses = EventType.addCustomEventType( "eventTypeForAppendListenerClasses", UsesAppendClasses.class );
|
||||
eventTypeForAppendListenerObjects = EventType.addCustomEventType( "eventTypeForAppendListenerObjects", UsesAppendObjects.class );
|
||||
|
||||
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
|
||||
eventListenerRegistry.setListeners(
|
||||
eventTypeForSetListenerClasses,
|
||||
ClothingGeneratorListenerSetClasses.class,
|
||||
FurnitureGeneratorListenerSetClasses.class,
|
||||
OtherGeneratorListenerSetClasses.class
|
||||
);
|
||||
eventListenerRegistry.setListeners(
|
||||
eventTypeForSetListenerObjects,
|
||||
new ClothingGeneratorListenerSetObjects(),
|
||||
new FurnitureGeneratorListenerSetObjects(),
|
||||
new OtherGeneratorListenerSetObjects()
|
||||
);
|
||||
|
||||
eventListenerRegistry.prependListeners(
|
||||
eventTypeForPrependListenerClasses,
|
||||
ClothingGeneratorListenerPrependClasses.class,
|
||||
FurnitureGeneratorListenerPrependClasses.class,
|
||||
OtherGeneratorListenerPrependClasses.class
|
||||
);
|
||||
eventListenerRegistry.prependListeners(
|
||||
eventTypeForPrependListenerObjects,
|
||||
new ClothingGeneratorListenerPrependObjects(),
|
||||
new FurnitureGeneratorListenerPrependObjects(),
|
||||
new OtherGeneratorListenerPrependObjects()
|
||||
);
|
||||
|
||||
eventListenerRegistry.appendListeners(
|
||||
eventTypeForAppendListenerClasses,
|
||||
ClothingGeneratorListenerAppendClasses.class,
|
||||
FurnitureGeneratorListenerAppendClasses.class,
|
||||
OtherGeneratorListenerAppendClasses.class
|
||||
);
|
||||
eventListenerRegistry.appendListeners(
|
||||
eventTypeForAppendListenerObjects,
|
||||
new ClothingGeneratorListenerAppendObjects(),
|
||||
new FurnitureGeneratorListenerAppendObjects(),
|
||||
new OtherGeneratorListenerAppendObjects()
|
||||
);
|
||||
|
||||
// add an EventType that does not get registered
|
||||
eventTypeUnregistered = EventType.addCustomEventType( "unregistered", Unregistered.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disintegrate(
|
||||
SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
}
|
||||
|
||||
public EventType<UsesSetClasses> eventTypeForSetListenerClasses() {
|
||||
return eventTypeForSetListenerClasses;
|
||||
}
|
||||
|
||||
public EventType<UsesSetObjects> eventTypeForSetListenerObjects() {
|
||||
return eventTypeForSetListenerObjects;
|
||||
}
|
||||
|
||||
public EventType<UsesPrependClasses> eventTypeForPrependListenerClasses() {
|
||||
return eventTypeForPrependListenerClasses;
|
||||
}
|
||||
|
||||
public EventType<UsesPrependObjects> eventTypeForPrependListenerObjects() {
|
||||
return eventTypeForPrependListenerObjects;
|
||||
}
|
||||
|
||||
public EventType<UsesAppendClasses> eventTypeForAppendListenerClasses() {
|
||||
return eventTypeForAppendListenerClasses;
|
||||
}
|
||||
|
||||
public EventType<UsesAppendObjects> eventTypeForAppendListenerObjects() {
|
||||
return eventTypeForAppendListenerObjects;
|
||||
}
|
||||
|
||||
public EventType<Unregistered> eventTypeUnregistered() {
|
||||
return eventTypeUnregistered;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventEngine;
|
||||
import org.hibernate.event.spi.EventEngineContributions;
|
||||
import org.hibernate.event.spi.EventEngineContributor;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13890")
|
||||
public class EventEngineContributionsTests extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected void configureBootstrapServiceRegistryBuilder(BootstrapServiceRegistryBuilder bsrb) {
|
||||
super.configureBootstrapServiceRegistryBuilder( bsrb );
|
||||
bsrb.applyClassLoaderService( new TestingClassLoaderService() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEventAccess() {
|
||||
final EventEngine eventEngine = sessionFactory().getEventEngine();
|
||||
|
||||
{
|
||||
final EventType<SexyRxySaveListener> saveEventType = eventEngine.findRegisteredEventType( SexyRxySaveListener.EVENT_NAME );
|
||||
assertThat( saveEventType, sameInstance( TheContributor.INSTANCE.saveEventType ) );
|
||||
assertThat( saveEventType.isStandardEvent(), is( false ) );
|
||||
|
||||
final EventListenerRegistry listenerRegistry = eventEngine.getListenerRegistry();
|
||||
final EventListenerGroup<SexyRxySaveListener> listenerGroup = listenerRegistry.getEventListenerGroup( saveEventType );
|
||||
assertThat( listenerGroup.count(), is( 1 ) );
|
||||
|
||||
listenerGroup.fireEventOnEachListener( RxySaveEvent.INSTANCE, SexyRxySaveListener::doIt );
|
||||
|
||||
assertThat( SexyRxySaveListener.INSTANCE.didIt, is(true ) );
|
||||
}
|
||||
|
||||
{
|
||||
final EventType<SexyRxyPersistListener> persistEventType = eventEngine.findRegisteredEventType( SexyRxyPersistListener.EVENT_NAME );
|
||||
assertThat( persistEventType, sameInstance( TheContributor.INSTANCE.persistEventType ) );
|
||||
assertThat( persistEventType.isStandardEvent(), is( false ) );
|
||||
|
||||
final EventListenerRegistry listenerRegistry = eventEngine.getListenerRegistry();
|
||||
final EventListenerGroup<SexyRxyPersistListener> listenerGroup = listenerRegistry.getEventListenerGroup( persistEventType );
|
||||
assertThat( listenerGroup.count(), is( 1 ) );
|
||||
|
||||
listenerGroup.fireEventOnEachListener( RxyPersistEvent.INSTANCE, SexyRxyPersistListener::doIt );
|
||||
|
||||
assertThat( SexyRxyPersistListener.INSTANCE.didIt, is(true ) );
|
||||
}
|
||||
}
|
||||
|
||||
public interface SexyRxyBaseListener {
|
||||
}
|
||||
|
||||
public static class RxySaveEvent {
|
||||
public static final RxySaveEvent INSTANCE = new RxySaveEvent();
|
||||
}
|
||||
|
||||
public static class SexyRxySaveListener implements SexyRxyBaseListener {
|
||||
public static final String EVENT_NAME = "rx-save";
|
||||
|
||||
public static final SexyRxySaveListener INSTANCE = new SexyRxySaveListener();
|
||||
|
||||
private boolean didIt;
|
||||
|
||||
public void doIt(RxySaveEvent event) {
|
||||
didIt = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RxyPersistEvent {
|
||||
public static final RxyPersistEvent INSTANCE = new RxyPersistEvent();
|
||||
}
|
||||
|
||||
public static class SexyRxyPersistListener implements SexyRxyBaseListener {
|
||||
public static final String EVENT_NAME = "rx-persist";
|
||||
|
||||
public static final SexyRxyPersistListener INSTANCE = new SexyRxyPersistListener();
|
||||
|
||||
private boolean didIt;
|
||||
|
||||
public void doIt(RxyPersistEvent event) {
|
||||
didIt = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TheContributor implements EventEngineContributor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final TheContributor INSTANCE = new TheContributor();
|
||||
|
||||
private EventType<SexyRxySaveListener> saveEventType;
|
||||
private EventType<SexyRxyPersistListener> persistEventType;
|
||||
|
||||
@Override
|
||||
public void contribute(EventEngineContributions target) {
|
||||
saveEventType = target.contributeEventType(
|
||||
SexyRxySaveListener.EVENT_NAME,
|
||||
SexyRxySaveListener.class,
|
||||
SexyRxySaveListener.INSTANCE
|
||||
);
|
||||
|
||||
persistEventType = target.contributeEventType(
|
||||
SexyRxyPersistListener.EVENT_NAME,
|
||||
SexyRxyPersistListener.class
|
||||
);
|
||||
|
||||
target.configureListeners(
|
||||
persistEventType,
|
||||
(group) -> group.appendListener( SexyRxyPersistListener.INSTANCE )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestingClassLoaderService extends ClassLoaderServiceImpl {
|
||||
@Override
|
||||
public <S> Collection<S> loadJavaServices(Class<S> serviceContract) {
|
||||
if ( serviceContract.equals( EventEngineContributor.class ) ) {
|
||||
//noinspection unchecked
|
||||
return (Collection<S>) Collections.singleton( TheContributor.INSTANCE );
|
||||
}
|
||||
|
||||
return super.loadJavaServices( serviceContract );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistry;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Concurrency test that registering a custom EventType does not interfere with
|
||||
* looking up a registered EventListenerGroup.
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13890")
|
||||
public class EventTypeListenerRegistryConcurrencyTest {
|
||||
private static CoreMessageLogger LOG = CoreLogging.messageLogger( EventTypeListenerRegistryConcurrencyTest.class );
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
final TheConcurrencyIntegrator integrator = new TheConcurrencyIntegrator();
|
||||
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
|
||||
.applyIntegrator( integrator )
|
||||
.build();
|
||||
SessionFactoryImplementor sessionFactory = null;
|
||||
try {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr ).build();
|
||||
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
|
||||
.buildMetadata()
|
||||
.getSessionFactoryBuilder()
|
||||
.build();
|
||||
integrator.checkResults( sessionFactory.getServiceRegistry() );
|
||||
}
|
||||
finally {
|
||||
if ( sessionFactory != null ) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
bsr.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class TheConcurrencyIntegrator implements Integrator {
|
||||
private final int NUMBER_OF_EVENT_TYPES_NEW = 10000;
|
||||
private final int NUMBER_OF_THREADS = 10;
|
||||
private final AtomicInteger START_VALUE = new AtomicInteger( 0 );
|
||||
private final List<Exception> exceptions = new ArrayList<>();
|
||||
private final Set<EventType> customEventTypes = new HashSet<>( NUMBER_OF_EVENT_TYPES_NEW );
|
||||
|
||||
// Capture number of "standard" event types (before adding custom event types).
|
||||
private final int numberEventTypesBefore = EventType.values().size();
|
||||
|
||||
@Override
|
||||
public void integrate(
|
||||
Metadata metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
|
||||
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
|
||||
final Runnable createAndRegisterEventTypes = () -> {
|
||||
for ( int i = START_VALUE.getAndIncrement();
|
||||
i < NUMBER_OF_EVENT_TYPES_NEW;
|
||||
i += NUMBER_OF_THREADS ) {
|
||||
final EventType eventType = EventType.addCustomEventType(
|
||||
"event" + i,
|
||||
DummyListener.class
|
||||
);
|
||||
try {
|
||||
eventListenerRegistry.setListeners( eventType, new DummyListener() );
|
||||
eventListenerRegistry.getEventListenerGroup( eventType );
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LOG.info( ex );
|
||||
exceptions.add( ex );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final Runnable eventListenerGroupsGetter = () -> {
|
||||
while( true ) {
|
||||
try {
|
||||
assertNotNull( eventListenerRegistry.getEventListenerGroup( EventType.AUTO_FLUSH ) );
|
||||
}
|
||||
catch (Exception ex) {
|
||||
exceptions.add( ex );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final Thread[] threadsCreateAndRegisterEventTypes = new Thread[NUMBER_OF_THREADS];
|
||||
final Thread[] threadsEventListenerGroupsGetter = new Thread[NUMBER_OF_THREADS];
|
||||
for ( int i = 0 ; i < NUMBER_OF_THREADS; i++ ) {
|
||||
threadsCreateAndRegisterEventTypes[i] = new Thread( createAndRegisterEventTypes );
|
||||
threadsEventListenerGroupsGetter[i] = new Thread( eventListenerGroupsGetter );
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < NUMBER_OF_THREADS; i++ ) {
|
||||
threadsCreateAndRegisterEventTypes[i].start();
|
||||
threadsEventListenerGroupsGetter[i].start();
|
||||
}
|
||||
|
||||
try {
|
||||
for ( int i = 0; i < NUMBER_OF_THREADS; i++ ) {
|
||||
threadsCreateAndRegisterEventTypes[i].join();
|
||||
threadsEventListenerGroupsGetter[i].interrupt();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
LOG.info( ex );
|
||||
exceptions.add( ex );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disintegrate(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
}
|
||||
|
||||
public void checkResults(ServiceRegistry serviceRegistry) {
|
||||
LOG.info( exceptions );
|
||||
assertTrue( exceptions.isEmpty() );
|
||||
assertEquals( numberEventTypesBefore + NUMBER_OF_EVENT_TYPES_NEW, EventType.values().size() );
|
||||
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
for ( EventType eventType : customEventTypes) {
|
||||
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
|
||||
final Iterator iterator = eventListenerGroup.listeners().iterator();
|
||||
assertTrue( iterator.hasNext() );
|
||||
assertTrue( DummyListener.class.isInstance( iterator.next() ) );
|
||||
assertFalse( iterator.hasNext() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DummyListener {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.strategyselectors;
|
||||
|
||||
import org.hibernate.boot.registry.selector.internal.DefaultDialectSelector;
|
||||
import org.hibernate.dialect.*;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DefaultDialectSelectorTest {
|
||||
|
||||
private DefaultDialectSelector strategySelector = new DefaultDialectSelector();
|
||||
|
||||
@Test
|
||||
public void verifyAllDialectNamingResolve() {
|
||||
testDialectNamingResolution( Cache71Dialect.class );
|
||||
testDialectNamingResolution( CUBRIDDialect.class );
|
||||
testDialectNamingResolution( DB2Dialect.class );
|
||||
testDialectNamingResolution( DB2390Dialect.class );
|
||||
testDialectNamingResolution( DB2390V8Dialect.class );
|
||||
testDialectNamingResolution( DB2400Dialect.class );
|
||||
testDialectNamingResolution( DB2400V7R3Dialect.class );
|
||||
testDialectNamingResolution( DerbyTenFiveDialect.class );
|
||||
testDialectNamingResolution( DerbyTenSixDialect.class );
|
||||
testDialectNamingResolution( DerbyTenSevenDialect.class );
|
||||
testDialectNamingResolution( FirebirdDialect.class );
|
||||
testDialectNamingResolution( FrontBaseDialect.class );
|
||||
testDialectNamingResolution( H2Dialect.class );
|
||||
testDialectNamingResolution( HANAColumnStoreDialect.class );
|
||||
testDialectNamingResolution( HANARowStoreDialect.class );
|
||||
testDialectNamingResolution( HSQLDialect.class );
|
||||
testDialectNamingResolution( InformixDialect.class );
|
||||
testDialectNamingResolution( IngresDialect.class );
|
||||
testDialectNamingResolution( Ingres9Dialect.class );
|
||||
testDialectNamingResolution( Ingres10Dialect.class );
|
||||
testDialectNamingResolution( InterbaseDialect.class );
|
||||
testDialectNamingResolution( JDataStoreDialect.class );
|
||||
|
||||
testDialectNamingResolution( MckoiDialect.class );
|
||||
testDialectNamingResolution( MimerSQLDialect.class );
|
||||
testDialectNamingResolution( MySQL5Dialect.class );
|
||||
testDialectNamingResolution( MySQL5InnoDBDialect.class );
|
||||
testDialectNamingResolution( MySQL57InnoDBDialect.class );
|
||||
testDialectNamingResolution( MySQL57Dialect.class );
|
||||
testDialectNamingResolution( MySQL8Dialect.class );
|
||||
testDialectNamingResolution( Oracle8iDialect.class );
|
||||
testDialectNamingResolution( Oracle9iDialect.class );
|
||||
testDialectNamingResolution( Oracle10gDialect.class );
|
||||
|
||||
testDialectNamingResolution( PointbaseDialect.class );
|
||||
testDialectNamingResolution( PostgresPlusDialect.class );
|
||||
testDialectNamingResolution( PostgreSQL81Dialect.class );
|
||||
testDialectNamingResolution( PostgreSQL82Dialect.class );
|
||||
testDialectNamingResolution( PostgreSQL9Dialect.class );
|
||||
testDialectNamingResolution( ProgressDialect.class );
|
||||
|
||||
testDialectNamingResolution( SAPDBDialect.class );
|
||||
testDialectNamingResolution( SQLServerDialect.class );
|
||||
testDialectNamingResolution( SQLServer2005Dialect.class );
|
||||
testDialectNamingResolution( SQLServer2008Dialect.class );
|
||||
testDialectNamingResolution( Sybase11Dialect.class );
|
||||
testDialectNamingResolution( SybaseAnywhereDialect.class );
|
||||
testDialectNamingResolution( SybaseASE15Dialect.class );
|
||||
testDialectNamingResolution( SybaseASE157Dialect.class );
|
||||
testDialectNamingResolution( TeradataDialect.class );
|
||||
testDialectNamingResolution( TimesTenDialect.class );
|
||||
}
|
||||
|
||||
private void testDialectNamingResolution(final Class<?> dialectClass) {
|
||||
String simpleName = dialectClass.getSimpleName();
|
||||
if ( simpleName.endsWith( "Dialect" ) ) {
|
||||
simpleName = simpleName.substring( 0, simpleName.length() - "Dialect".length() );
|
||||
}
|
||||
Class<? extends Dialect> aClass = strategySelector.resolve( simpleName );
|
||||
Assert.assertNotNull( aClass );
|
||||
Assert.assertEquals( dialectClass, aClass );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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.strategyselectors;
|
||||
|
||||
import org.hibernate.boot.registry.selector.internal.DefaultJtaPlatformSelector;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.BorlandEnterpriseServerJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JOTMJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JOnASJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JRun4JtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.OC4JJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.OrionJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.ResinJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.SapNetWeaverJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.SunOneJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JtaPlatformSelectorTest {
|
||||
|
||||
private final DefaultJtaPlatformSelector strategySelector = new DefaultJtaPlatformSelector();
|
||||
|
||||
@Test
|
||||
public void verifyAllJtaPlatformResolve() {
|
||||
|
||||
// N.B. it might seem that there is some reduncancy, but it's not the case: the FQNs listed
|
||||
// here are legacy full classnames which are being re-mapped to the right class for backwards
|
||||
// compatibility reasons.
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
AtomikosJtaPlatform.class,
|
||||
"Atomikos",
|
||||
"org.hibernate.service.jta.platform.internal.AtomikosJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
BorlandEnterpriseServerJtaPlatform.class,
|
||||
"Borland",
|
||||
"org.hibernate.service.jta.platform.internal.BorlandEnterpriseServerJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
BitronixJtaPlatform.class,
|
||||
"Bitronix",
|
||||
"org.hibernate.service.jta.platform.internal.BitronixJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
JBossAppServerJtaPlatform.class,
|
||||
"JBossAS",
|
||||
"org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
JBossStandAloneJtaPlatform.class,
|
||||
"JBossTS",
|
||||
"org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
JOnASJtaPlatform.class,
|
||||
"JOnAS",
|
||||
"org.hibernate.service.jta.platform.internal.JOnASJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
JOTMJtaPlatform.class,
|
||||
"JOTM",
|
||||
"org.hibernate.service.jta.platform.internal.JOTMJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
JRun4JtaPlatform.class,
|
||||
"JRun4",
|
||||
"org.hibernate.service.jta.platform.internal.JRun4JtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
OC4JJtaPlatform.class,
|
||||
"OC4J",
|
||||
"org.hibernate.service.jta.platform.internal.OC4JJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
OrionJtaPlatform.class,
|
||||
"Orion",
|
||||
"org.hibernate.service.jta.platform.internal.OrionJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
ResinJtaPlatform.class,
|
||||
"Resin",
|
||||
"org.hibernate.service.jta.platform.internal.ResinJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
SapNetWeaverJtaPlatform.class,
|
||||
"SapNetWeaver",
|
||||
"org.hibernate.service.jta.platform.internal.SapNetWeaverJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
SunOneJtaPlatform.class,
|
||||
"SunOne",
|
||||
"org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
WeblogicJtaPlatform.class,
|
||||
"Weblogic",
|
||||
"org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
WebSphereLibertyJtaPlatform.class,
|
||||
"WebSphereLiberty",
|
||||
"org.hibernate.engine.transaction.jta.platform.internal.WebSphereLibertyJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
WebSphereJtaPlatform.class,
|
||||
"WebSphere",
|
||||
"org.hibernate.service.jta.platform.internal.WebSphereJtaPlatform"
|
||||
);
|
||||
|
||||
testJtaPlatformResolves(
|
||||
strategySelector,
|
||||
WebSphereExtendedJtaPlatform.class,
|
||||
"WebSphereExtended",
|
||||
"org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform"
|
||||
);
|
||||
}
|
||||
|
||||
private static void testJtaPlatformResolves(final DefaultJtaPlatformSelector strategySelector, final Class expectedType, final String shortname, final String longname) {
|
||||
expectResolution(strategySelector, expectedType, shortname);
|
||||
expectResolution(strategySelector, expectedType, longname);
|
||||
}
|
||||
|
||||
private static void expectResolution(final DefaultJtaPlatformSelector strategySelector, final Class expectedType, final String name) {
|
||||
Class<? extends JtaPlatform> aClass = strategySelector.resolve( name );
|
||||
Assert.assertNotNull( aClass );
|
||||
Assert.assertEquals( expectedType, aClass );
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue