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

This commit is contained in:
Andrea Boriero 2019-12-16 12:43:47 +00:00
commit 1d4bb08ef7
20 changed files with 942 additions and 89 deletions

View File

@ -16,15 +16,44 @@ apply plugin: 'hibernate-matrix-testing'
description = 'Hibernate\'s core ORM functionality'
ext {
jaxbTargetDir = file( "${buildDir}/generated-src/jaxb/main" )
}
sourceSets.main {
java.srcDir project.jaxbTargetDir
}
sourceSets {
// resources inherently exclude sources
test {
resources {
setSrcDirs( ['src/test/java','src/test/resources'] )
}
}
testJavassist {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
}
}
}
configurations {
tests {
description = 'Configuration for the produced test jar'
}
//Configures the compile and runtime configurations for our javassist tests
//and includes the dependencies of the test task.
testJavassistCompile.extendsFrom testCompile
testJavassistRuntime.extendsFrom testRuntime
}
dependencies {
compile( libraries.jpa )
// Javassist is no longer the default enhancer but still required for other purposes, e.g. Scanning
// This can now be made provided
compile( libraries.javassist )
compile( libraries.byteBuddy )
compile( libraries.antlr )
@ -107,6 +136,10 @@ dependencies {
testCompile libraries.jboss_ejb_spec_jar
testCompile libraries.jboss_annotation_spec_jar
// Additional tests requiring Javassist
// folder in src/javassist/java
testJavassistCompile libraries.javassist
}
jar {
@ -407,4 +440,18 @@ class Antlr4GenerationTask extends DefaultTask {
args sourceFile.absolutePath
}
}
}
//Create the task that runs the integration tests found from the
//configured source directory and uses the correct classpath.
task testJavassist(type: Test) {
testClassesDirs = sourceSets.testJavassist.output.classesDirs
classpath = sourceSets.testJavassist.runtimeClasspath
//If you want to ensure that integration tests are run every time when you invoke
//this task, uncomment the following line.
//outputs.upToDateWhen { false }
}
check.dependsOn testJavassist
testJavassist.mustRunAfter test

View File

@ -14,9 +14,6 @@ import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import org.hibernate.boot.archive.scan.internal.ClassDescriptorImpl;
import org.hibernate.boot.archive.scan.internal.ScanResultCollector;
import org.hibernate.boot.archive.spi.ArchiveContext;
@ -24,12 +21,26 @@ import org.hibernate.boot.archive.spi.ArchiveEntry;
import org.hibernate.boot.archive.spi.ArchiveEntryHandler;
import org.hibernate.boot.archive.spi.ArchiveException;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
/**
* Defines handling and filtering for class file entries within an archive
*
* @author Steve Ebersole
*/
public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
private final static DotName CONVERTER = DotName.createSimple( Converter.class.getName() );
private final static DotName[] MODELS = {
DotName.createSimple( Entity.class.getName() ),
DotName.createSimple( MappedSuperclass.class.getName() ),
DotName.createSimple( Embeddable.class.getName() )
};
private final ScanResultCollector resultCollector;
public ClassFileArchiveEntryHandler(ScanResultCollector resultCollector) {
@ -38,14 +49,8 @@ public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
@Override
public void handleEntry(ArchiveEntry entry, ArchiveContext context) {
// Ultimately we'd like to leverage Jandex here as long term we want to move to
// using Jandex for annotation processing. But even then, Jandex atm does not have
// any facility for passing a stream and conditionally indexing it into an Index or
// returning existing ClassInfo objects.
//
// So not sure we can ever not do this unconditional input stream read :(
final ClassFile classFile = toClassFile( entry );
final ClassDescriptor classDescriptor = toClassDescriptor( classFile, entry );
final ClassDescriptor classDescriptor = toClassDescriptor( entry );
if ( classDescriptor.getCategorization() == ClassDescriptor.Categorization.OTHER ) {
return;
@ -54,45 +59,41 @@ public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
resultCollector.handleClass( classDescriptor, context.isRootUrl() );
}
private ClassFile toClassFile(ArchiveEntry entry) {
final InputStream inputStream = entry.getStreamAccess().accessInputStream();
final DataInputStream dataInputStream = new DataInputStream( inputStream );
try {
return new ClassFile( dataInputStream );
private ClassDescriptor toClassDescriptor(ArchiveEntry entry) {
try (InputStream inputStream = entry.getStreamAccess().accessInputStream()) {
Indexer indexer = new Indexer();
ClassInfo classInfo = indexer.index( inputStream );
Index index = indexer.complete();
return toClassDescriptor( classInfo, index, entry );
}
catch (IOException e) {
throw new ArchiveException( "Could not build ClassFile", e );
}
finally {
try {
dataInputStream.close();
}
catch (Exception ignore) {
}
try {
inputStream.close();
}
catch (IOException ignore) {
}
throw new ArchiveException( "Could not build ClassInfo", e );
}
}
private ClassDescriptor toClassDescriptor(ClassFile classFile, ArchiveEntry entry) {
private ClassDescriptor toClassDescriptor(ClassInfo classInfo, Index index, ArchiveEntry entry) {
ClassDescriptor.Categorization categorization = ClassDescriptor.Categorization.OTHER;
final AnnotationsAttribute visibleAnnotations = (AnnotationsAttribute) classFile.getAttribute( AnnotationsAttribute.visibleTag );
if ( visibleAnnotations != null ) {
if ( visibleAnnotations.getAnnotation( Entity.class.getName() ) != null
|| visibleAnnotations.getAnnotation( MappedSuperclass.class.getName() ) != null
|| visibleAnnotations.getAnnotation( Embeddable.class.getName() ) != null ) {
if ( isModel( index ) ) {
categorization = ClassDescriptor.Categorization.MODEL;
}
else if ( visibleAnnotations.getAnnotation( Converter.class.getName() ) != null ) {
else if ( isConverter( index ) ) {
categorization = ClassDescriptor.Categorization.CONVERTER;
}
return new ClassDescriptorImpl( classInfo.name().toString(), categorization, entry.getStreamAccess() );
}
return new ClassDescriptorImpl( classFile.getName(), categorization, entry.getStreamAccess() );
private boolean isConverter(Index index) {
return !index.getAnnotations( CONVERTER ).isEmpty();
}
private boolean isModel(Index index) {
for ( DotName model : MODELS ) {
if ( !index.getAnnotations( model ).isEmpty() ) {
return true;
}
}
return false;
}
}

View File

@ -26,6 +26,14 @@ import org.hibernate.engine.spi.ExtendedSelfDirtinessTracker;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
import net.bytebuddy.jar.asm.Opcodes;
class CodeTemplates {
@ -510,4 +518,26 @@ class CodeTemplates {
@interface MappedBy {
}
// mapping to get private field from superclass by calling the enhanced reader, for use when field is not visible
static class GetterMapping implements Advice.OffsetMapping {
private final FieldDescription persistentField;
GetterMapping(FieldDescription persistentField) {
this.persistentField = persistentField;
}
@Override public Target resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Advice.ArgumentHandler argumentHandler, Sort sort) {
MethodDescription.Token signature = new MethodDescription.Token( EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + persistentField.getName(), Opcodes.ACC_PUBLIC, persistentField.getType() );
MethodDescription method = new MethodDescription.Latent( instrumentedType.getSuperClass().asErasure(), signature );
return new Target.AbstractReadOnlyAdapter() {
@Override
public StackManipulation resolveRead() {
return new StackManipulation.Compound( MethodVariableAccess.loadThis(), MethodInvocation.invoke( method ).special( method.getDeclaringType().asErasure() ) );
}
};
}
}
}

View File

@ -285,7 +285,7 @@ public class EnhancerImpl implements Enhancer {
}
}
return createTransformer( managedCtClass ).applyTo( builder, false );
return createTransformer( managedCtClass ).applyTo( builder );
}
else if ( enhancementContext.isCompositeClass( managedCtClass ) ) {
log.debugf( "Enhancing [%s] as Composite", managedCtClass.getName() );
@ -318,13 +318,13 @@ public class EnhancerImpl implements Enhancer {
.intercept( implementationClearOwner );
}
return createTransformer( managedCtClass ).applyTo( builder, false );
return createTransformer( managedCtClass ).applyTo( builder );
}
else if ( enhancementContext.isMappedSuperclassClass( managedCtClass ) ) {
log.debugf( "Enhancing [%s] as MappedSuperclass", managedCtClass.getName() );
builder = builder.implement( ManagedMappedSuperclass.class );
return createTransformer( managedCtClass ).applyTo( builder, true );
return createTransformer( managedCtClass ).applyTo( builder );
}
else if ( enhancementContext.doExtendedEnhancement( managedCtClass ) ) {
log.debugf( "Extended enhancement of [%s]", managedCtClass.getName() );

View File

@ -64,8 +64,15 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() )
&& persistentField.hasAnnotation( Embedded.class ) ) {
implementation = Advice.withCustomMapping()
.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
// HHH-13759 - Call getter on superclass if field is not visible
// An embedded field won't be visible if declared private in a superclass
// annotated with @MappedSuperclass
Advice.WithCustomMapping advice = Advice.withCustomMapping();
advice = persistentField.isVisibleTo( managedCtClass )
? advice.bind( CodeTemplates.FieldValue.class, persistentField.getFieldDescription() )
: advice.bind( CodeTemplates.FieldValue.class, new CodeTemplates.GetterMapping( persistentField.getFieldDescription() ) );
implementation = advice
.bind( CodeTemplates.FieldName.class, persistentField.getName() )
.to( CodeTemplates.CompositeFieldDirtyCheckingHandler.class )
.wrap( implementation );

View File

@ -175,7 +175,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
return false;
}
DynamicType.Builder<?> applyTo(DynamicType.Builder<?> builder, boolean accessor) {
DynamicType.Builder<?> applyTo(DynamicType.Builder<?> builder) {
boolean compositeOwner = false;
builder = builder.visit( new AsmVisitorWrapper.ForDeclaredMethods().invokable( NOT_HIBERNATE_GENERATED, this ) );
@ -186,10 +186,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
enhancedField.getType().asErasure(),
Visibility.PUBLIC
)
.intercept(
accessor
? FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() )
: fieldReader( enhancedField )
.intercept( fieldReader( enhancedField )
)
.defineMethod(
EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + enhancedField.getName(),
@ -197,12 +194,10 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
Visibility.PUBLIC
)
.withParameters( enhancedField.getType().asErasure() )
.intercept( accessor
? FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() )
: fieldWriter( enhancedField ) );
.intercept( fieldWriter( enhancedField ) );
if ( !compositeOwner
&& !accessor
&& !enhancementContext.isMappedSuperclassClass( managedCtClass )
&& enhancedField.hasAnnotation( Embedded.class )
&& enhancementContext.isCompositeClass( enhancedField.getType().asErasure() )
&& enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
@ -228,6 +223,9 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
}
private Implementation fieldReader(AnnotatedFieldDescription enhancedField) {
if ( enhancementContext.isMappedSuperclassClass( managedCtClass ) ) {
return FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() );
}
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) || !enhancementContext.isLazyLoadable( enhancedField ) ) {
if ( enhancedField.getDeclaringType().asErasure().equals( managedCtClass ) ) {
return FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() );
@ -242,20 +240,29 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
}
private Implementation fieldWriter(AnnotatedFieldDescription enhancedField) {
Implementation implementation;
Implementation implementation = fieldWriterImplementation( enhancedField );
if ( !enhancementContext.isMappedSuperclassClass( managedCtClass ) ) {
implementation = InlineDirtyCheckingHandler.wrap( managedCtClass, enhancementContext, enhancedField, implementation );
implementation = BiDirectionalAssociationHandler.wrap( managedCtClass, enhancementContext, enhancedField, implementation );
}
return implementation;
}
private Implementation fieldWriterImplementation(AnnotatedFieldDescription enhancedField) {
if ( enhancementContext.isMappedSuperclassClass( managedCtClass ) ) {
return FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() );
}
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) || !enhancementContext.isLazyLoadable( enhancedField ) ) {
if ( enhancedField.getDeclaringType().asErasure().equals( managedCtClass ) ) {
implementation = FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() );
return FieldAccessor.ofField( enhancedField.getName() ).in( enhancedField.getDeclaringType().asErasure() );
}
else {
implementation = new Implementation.Simple( new FieldMethodWriter( managedCtClass, enhancedField ) );
return new Implementation.Simple( new FieldMethodWriter( managedCtClass, enhancedField ) );
}
}
else {
implementation = new Implementation.Simple( FieldWriterAppender.of( managedCtClass, enhancedField ) );
return new Implementation.Simple( FieldWriterAppender.of( managedCtClass, enhancedField ) );
}
implementation = InlineDirtyCheckingHandler.wrap( managedCtClass, enhancementContext, enhancedField, implementation );
return BiDirectionalAssociationHandler.wrap( managedCtClass, enhancementContext, enhancedField, implementation );
}
DynamicType.Builder<?> applyExtended(DynamicType.Builder<?> builder) {

View File

@ -520,26 +520,30 @@ public class PersistentAttributesEnhancer extends EnhancerImpl {
// make sure to add the CompositeOwner interface
addCompositeOwnerInterface( managedCtClass );
String readFragment = persistentField.visibleFrom( managedCtClass ) ? persistentField.getName() : "super." + EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + persistentField.getName() + "()";
// cleanup previous owner
fieldWriter.insertBefore(
String.format(
"if (%1$s != null) { ((%2$s) %1$s).%3$s(\"%1$s\"); }%n",
persistentField.getName(),
"if (%1$s != null) { ((%2$s) %1$s).%3$s(\"%4$s\"); }%n",
readFragment,
CompositeTracker.class.getName(),
EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER
EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER,
persistentField.getName()
)
);
// trigger track changes
fieldWriter.insertAfter(
String.format(
"if (%1$s != null) { ((%2$s) %1$s).%4$s(\"%1$s\", (%3$s) this); }%n" +
"%5$s(\"%1$s\");",
persistentField.getName(),
"if (%1$s != null) { ((%2$s) %1$s).%4$s(\"%6$s\", (%3$s) this); }%n" +
"%5$s(\"%6$s\");",
readFragment,
CompositeTracker.class.getName(),
CompositeOwner.class.getName(),
EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER,
EnhancerConstants.TRACKER_CHANGER_NAME
EnhancerConstants.TRACKER_CHANGER_NAME,
persistentField.getName()
)
);
}

View File

@ -15,7 +15,7 @@ import org.hibernate.service.ServiceRegistry;
/**
* An interface for factories of {@link ProxyFactory proxy factory} instances.
* <p/>
* Currently used to abstract from the tupizer whether we are using Byte Buddy or
* Currently used to abstract from the tuplizer whether we are using Byte Buddy or
* Javassist for lazy proxy generation.
*
* @author Steve Ebersole

View File

@ -10,6 +10,7 @@ import java.util.Properties;
import org.hibernate.MappingException;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.TransientObjectException;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -78,9 +79,6 @@ public class ForeignGenerator implements IdentifierGenerator, Configurable {
@Override
public Object generate(SharedSessionContractImplementor sessionImplementor, Object object) {
// needs to be a Session for the #save and #contains calls below...
final Session session = ( Session ) sessionImplementor;
final EntityPersister persister = sessionImplementor.getFactory().getMetamodel().entityPersister( entityName );
Object associatedObject = persister.getPropertyValue( object, propertyName );
if ( associatedObject == null ) {
@ -115,10 +113,20 @@ public class ForeignGenerator implements IdentifierGenerator, Configurable {
foreignValueSourceType.getAssociatedEntityName()
);
}
id = session.save( foreignValueSourceType.getAssociatedEntityName(), associatedObject );
if (sessionImplementor instanceof Session) {
id = ((Session) sessionImplementor)
.save(foreignValueSourceType.getAssociatedEntityName(), associatedObject);
}
else if (sessionImplementor instanceof StatelessSession) {
id = ((StatelessSession) sessionImplementor)
.insert(foreignValueSourceType.getAssociatedEntityName(), associatedObject);
}
else {
throw new IdentifierGenerationException("sessionImplementor is neither Session nor StatelessSession");
}
}
if ( session.contains( entityName, object ) ) {
if ( sessionImplementor instanceof Session && ((Session) sessionImplementor).contains( entityName, object ) ) {
//abort the save (the object is already saved by a circular cascade)
return IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR;
//throw new IdentifierGenerationException("save associated object first, or disable cascade for inverse association");

View File

@ -14,6 +14,8 @@ import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
@ -902,4 +904,11 @@ public class ProcedureCallImpl<R>
public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
}
@Override
@SuppressWarnings("unchecked")
public Stream getResultStream() {
return getResultList().stream();
}
}

View File

@ -0,0 +1,210 @@
/*
* 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.orm.test.bytecode.enhance.internal.bytebuddy;
import java.lang.reflect.Method;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.ENTITY_ENTRY_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.ENTITY_ENTRY_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.NEXT_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.NEXT_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.NEXT_SETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PREVIOUS_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PREVIOUS_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PREVIOUS_SETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_CLEAR_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_COMPOSITE_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_GET_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_HAS_CHANGED_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_SUSPEND_NAME;
@TestForIssue(jiraKey = "HHH-13759")
@RunWith(BytecodeEnhancerRunner.class)
@EnhancementOptions(inlineDirtyChecking = true)
public class DirtyCheckingWithEmbeddableAndMappedSuperclassTest {
@Test
public void shouldDeclareFieldsInEntityClass() {
assertThat( CardGame.class )
.hasDeclaredFields( ENTITY_ENTRY_FIELD_NAME, PREVIOUS_FIELD_NAME, NEXT_FIELD_NAME, TRACKER_FIELD_NAME );
}
@Test
public void shouldDeclareMethodsInEntityClass() {
assertThat( CardGame.class )
.hasDeclaredMethods( PERSISTENT_FIELD_READER_PREFIX + "id", PERSISTENT_FIELD_WRITER_PREFIX + "id" )
.hasDeclaredMethods( PERSISTENT_FIELD_READER_PREFIX + "name", PERSISTENT_FIELD_WRITER_PREFIX + "name" )
.hasDeclaredMethods( ENTITY_INSTANCE_GETTER_NAME, ENTITY_ENTRY_GETTER_NAME )
.hasDeclaredMethods( PREVIOUS_GETTER_NAME, PREVIOUS_SETTER_NAME, NEXT_GETTER_NAME, NEXT_SETTER_NAME )
.hasDeclaredMethods( TRACKER_HAS_CHANGED_NAME, TRACKER_CLEAR_NAME, TRACKER_SUSPEND_NAME, TRACKER_GET_NAME );
}
@Test
public void shouldDeclareFieldsInEmbeddedClass() {
assertThat( Component.class )
.hasDeclaredFields( TRACKER_COMPOSITE_FIELD_NAME );
}
@Test
public void shouldDeclareMethodsInEmbeddedClass() {
assertThat(Component.class )
.hasDeclaredMethods( PERSISTENT_FIELD_READER_PREFIX + "component", PERSISTENT_FIELD_WRITER_PREFIX + "component" )
.hasDeclaredMethods( TRACKER_COMPOSITE_SET_OWNER, TRACKER_COMPOSITE_CLEAR_OWNER );
}
@Test
public void shouldCreateTheTracker() throws Exception {
CardGame entity = new CardGame( "MTG", "Magic the Gathering" );
assertThat( entity )
.extracting( NEXT_FIELD_NAME ).isNull();
assertThat( entity )
.extracting( PREVIOUS_FIELD_NAME ).isNull();
assertThat( entity )
.extracting( ENTITY_ENTRY_FIELD_NAME ).isNull();
assertThat( entity )
.extracting( TRACKER_FIELD_NAME ).isInstanceOf( SimpleFieldTracker.class );
assertThat( entity.getFirstPlayerToken() )
.extracting( TRACKER_COMPOSITE_FIELD_NAME ).isInstanceOf( CompositeOwnerTracker.class);
assertThat( entity ).extracting( TRACKER_HAS_CHANGED_NAME ).isEqualTo( true );
assertThat( entity ).extracting( TRACKER_GET_NAME )
.isEqualTo( new String[] { "name", "firstPlayerToken" } );
assertThat( entity.getFirstPlayerToken() )
.extracting( TRACKER_COMPOSITE_FIELD_NAME + ".names" ).isEqualTo( new String[] { "firstPlayerToken" } );
}
@Test
public void shouldResetTheTracker() throws Exception {
CardGame entity = new CardGame( "7WD", "7 Wonders duel" );
Method trackerClearMethod = CardGame.class.getMethod( TRACKER_CLEAR_NAME );
trackerClearMethod.invoke( entity );
assertThat( entity ).extracting( TRACKER_HAS_CHANGED_NAME ).isEqualTo( false );
assertThat( entity ).extracting( TRACKER_GET_NAME ).isEqualTo( new String[0] );
}
@Test
public void shouldUpdateTheTracker() throws Exception {
CardGame entity = new CardGame( "SPL", "Splendor" );
Method trackerClearMethod = CardGame.class.getMethod( TRACKER_CLEAR_NAME );
trackerClearMethod.invoke( entity );
entity.setName( "Splendor: Cities of Splendor" );
assertThat( entity ).extracting( TRACKER_HAS_CHANGED_NAME ).isEqualTo( true );
assertThat( entity ).extracting( TRACKER_GET_NAME )
.isEqualTo( new String[] { "name", "firstPlayerToken" } );
trackerClearMethod.invoke( entity );
entity.setFirstPlayerToken( new Component( "FIRST PLAYER!!!!!!!!" ) );
assertThat( entity ).extracting( TRACKER_GET_NAME )
.isEqualTo( new String[] { "firstPlayerToken" } );
assertThat( entity.getFirstPlayerToken() )
.extracting( TRACKER_COMPOSITE_FIELD_NAME + ".names" ).isEqualTo( new String[] { "firstPlayerToken" } );
}
@MappedSuperclass
public static abstract class TableTopGame {
@Embedded
private Component firstPlayerToken;
public Component getFirstPlayerToken() {
return firstPlayerToken;
}
public void setFirstPlayerToken(Component firstPlayerToken) {
this.firstPlayerToken = firstPlayerToken;
}
}
@Embeddable
public static class Component {
@Column(name = "first_player_token")
private String component;
public Component() {
}
private Component(String component) {
this.component = component;
}
public String getComponent() {
return component;
}
public void setComponent(String component) {
this.component = component;
}
}
@Entity(name = "CardGame")
public static class CardGame extends TableTopGame {
@Id
private String id;
private String name;
public CardGame() {
}
private CardGame(String id, String name) {
this.id = id;
this.name = name;
setFirstPlayerToken( createEmbeddedValue( name ) );
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
setFirstPlayerToken( createEmbeddedValue( name ) );
}
private Component createEmbeddedValue(String name) {
return new Component( name + " first player token");
}
}
}

View File

@ -0,0 +1,162 @@
/*
* 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.orm.test.bytecode.enhance.internal.bytebuddy;
import java.lang.reflect.Method;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.ENTITY_ENTRY_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.ENTITY_ENTRY_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.NEXT_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.NEXT_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.NEXT_SETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PREVIOUS_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PREVIOUS_GETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.PREVIOUS_SETTER_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_CLEAR_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_FIELD_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_GET_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_HAS_CHANGED_NAME;
import static org.hibernate.bytecode.enhance.spi.EnhancerConstants.TRACKER_SUSPEND_NAME;
@TestForIssue(jiraKey = "HHH-13759")
@RunWith(BytecodeEnhancerRunner.class)
@EnhancementOptions(inlineDirtyChecking = true)
public class DirtyCheckingWithMappedsuperclassTest {
@Test
public void shouldDeclareFieldsInEntityClass() {
assertThat( CardGame.class )
.hasDeclaredFields( ENTITY_ENTRY_FIELD_NAME, PREVIOUS_FIELD_NAME, NEXT_FIELD_NAME, TRACKER_FIELD_NAME );
}
@Test
public void shouldDeclareMethodsInEntityClass() {
assertThat( CardGame.class )
.hasDeclaredMethods( PERSISTENT_FIELD_READER_PREFIX + "id", PERSISTENT_FIELD_WRITER_PREFIX + "id" )
.hasDeclaredMethods( PERSISTENT_FIELD_READER_PREFIX + "name", PERSISTENT_FIELD_WRITER_PREFIX + "name" )
.hasDeclaredMethods( PERSISTENT_FIELD_READER_PREFIX + "code", PERSISTENT_FIELD_WRITER_PREFIX + "code" )
.hasDeclaredMethods( ENTITY_INSTANCE_GETTER_NAME, ENTITY_ENTRY_GETTER_NAME )
.hasDeclaredMethods( PREVIOUS_GETTER_NAME, PREVIOUS_SETTER_NAME, NEXT_GETTER_NAME, NEXT_SETTER_NAME )
.hasDeclaredMethods( TRACKER_HAS_CHANGED_NAME, TRACKER_CLEAR_NAME, TRACKER_SUSPEND_NAME, TRACKER_GET_NAME );
}
@Test
public void shouldCreateTheTracker() throws Exception {
CardGame entity = new CardGame( "MTG", "Magic the Gathering" );
assertThat( entity )
.extracting( NEXT_FIELD_NAME ).isNull();
assertThat( entity )
.extracting( PREVIOUS_FIELD_NAME ).isNull();
assertThat( entity )
.extracting( ENTITY_ENTRY_FIELD_NAME ).isNull();
assertThat( entity )
.extracting( TRACKER_FIELD_NAME ).isInstanceOf( SimpleFieldTracker.class );
assertThat( entity ).extracting( TRACKER_HAS_CHANGED_NAME ).isEqualTo( true );
assertThat( entity ).extracting( TRACKER_GET_NAME ).isEqualTo( new String[] { "name", "code" } );
}
@Test
public void shouldResetTheTracker() throws Exception {
CardGame entity = new CardGame( "7WD", "7 Wonders duel" );
Method trackerClearMethod = CardGame.class.getMethod( TRACKER_CLEAR_NAME );
trackerClearMethod.invoke( entity );
assertThat( entity ).extracting( TRACKER_HAS_CHANGED_NAME ).isEqualTo( false );
assertThat( entity ).extracting( TRACKER_GET_NAME ).isEqualTo( new String[0] );
}
@Test
public void shouldUpdateTheTracker() throws Exception {
CardGame entity = new CardGame( "SPL", "Splendor" );
assertThat( entity.getCode() ).isEqualTo( "XsplX" );
Method trackerClearMethod = CardGame.class.getMethod( TRACKER_CLEAR_NAME );
trackerClearMethod.invoke( entity );
entity.setName( "Splendor: Cities of Splendor" );
assertThat( entity.getCode() )
.as( "Field 'code' should have not change" ).isEqualTo( "XsplX" );
assertThat( entity ).extracting( TRACKER_HAS_CHANGED_NAME ).isEqualTo( true );
assertThat( entity ).extracting( TRACKER_GET_NAME ).isEqualTo( new String[] { "name" } );
entity.setName( "Cities of Splendor" );
assertThat( entity ).extracting( TRACKER_GET_NAME ).isEqualTo( new String[] { "name", "code" } );
}
@MappedSuperclass
public static abstract class TableTopGame {
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
@Entity(name = "CardGame")
public static class CardGame extends TableTopGame {
@Id
private String id;
private String name;
public CardGame() {
}
private CardGame(String id, String name) {
this.id = id;
this.name = name;
setCode( createCode( name ) );
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
setCode( createCode( name ) );
}
private String createCode(String name) {
return "X" + name.substring( 0, 3 ).toLowerCase() + "X";
}
}
}

View File

@ -0,0 +1,39 @@
package org.hibernate.procedure.internal;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Nathan Xu
*/
public class ProcedureCallImplTest extends BaseEntityManagerFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-13644" )
@RequiresDialect( H2Dialect.class )
public void testNoNullPointerExceptionThrown() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
em.createNativeQuery("CREATE ALIAS GET_RANDOM_VALUE FOR \"java.lang.Math.random\";").executeUpdate();
Query query = em.createStoredProcedureQuery("GET_RANDOM_VALUE");
Stream stream = query.getResultStream();
Assert.assertEquals(1, stream.count());
em.getTransaction().commit();
em.close();
}
}

View File

@ -0,0 +1,148 @@
/*
* 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.bytecode.enhancement.lazy.proxy;
import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertThat;
/**
* @author Andrea Boriero
*/
@RunWith(BytecodeEnhancerRunner.class)
@EnhancementOptions(lazyLoading = true, inlineDirtyChecking = true)
public class MappedSuperclassWithEmbeddableTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
super.configureStandardServiceRegistryBuilder( ssrb );
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
ssrb.applySetting( AvailableSettings.FORMAT_SQL, "false" );
ssrb.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" );
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Before
public void prepare() {
doInHibernate( this::sessionFactory, s -> {
TestEntity testEntity = new TestEntity( "2", "test" );
s.persist( testEntity );
} );
}
@After
public void tearDown() {
doInHibernate( this::sessionFactory, s -> {
s.createQuery( "delete from TestEntity" ).executeUpdate();
} );
}
@Test
public void testIt() {
doInHibernate( this::sessionFactory, s -> {
TestEntity testEntity = s.get( TestEntity.class, "2" );
assertThat( testEntity, notNullValue() );
} );
}
@MappedSuperclass
public static abstract class BaseEntity {
@Embedded
private EmbeddedValue superField;
public EmbeddedValue getSuperField() {
return superField;
}
public void setSuperField(EmbeddedValue superField) {
this.superField = superField;
}
}
@Embeddable
public static class EmbeddedValue implements Serializable {
@Column(name = "super_field")
private String superField;
public EmbeddedValue() {
}
private EmbeddedValue(String superField) {
this.superField = superField;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
EmbeddedValue that = (EmbeddedValue) o;
return superField.equals( that.superField );
}
@Override
public int hashCode() {
return Objects.hash( superField );
}
}
@Entity(name = "TestEntity")
public static class TestEntity extends BaseEntity {
@Id
private String id;
private String name;
public TestEntity() {
}
private TestEntity(String id, String name) {
this.id = id;
this.name = name;
EmbeddedValue value = new EmbeddedValue( "SUPER " + name );
setSuperField( value );
}
public String id() {
return id;
}
public String name() {
return name;
}
}
}

View File

@ -0,0 +1,70 @@
package org.hibernate.test.id;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import org.hibernate.Transaction;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
/**
* @author Nathan Xu
*/
public class ForeignGeneratorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Product.class,
ProductDetails.class
};
}
@Test
@TestForIssue( jiraKey = "HHH-13456")
public void testForeignGeneratorInStatelessSession() {
inStatelessSession(statelessSession -> {
Transaction tx = statelessSession.beginTransaction();
Product product = new Product();
ProductDetails productDetails = new ProductDetails( product );
statelessSession.insert( productDetails );
tx.commit();
});
}
@Entity(name = "Product")
public static class Product {
@Id
@GeneratedValue
private Long id;
}
@Entity(name = "ProductDetails")
public static class ProductDetails {
@Id
@GeneratedValue
private Long id;
@OneToOne
@MapsId
private Product product;
public ProductDetails() {
}
public ProductDetails( Product product ) {
this.product = product;
}
}
}

View File

@ -6,18 +6,20 @@
*/
package org.hibernate.test.bytecode.enhancement.javassist;
import javassist.CtClass;
import org.hibernate.bytecode.enhance.internal.javassist.EnhancerImpl;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import javassist.CtClass;
import org.hibernate.bytecode.enhance.internal.javassist.EnhancerImpl;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;

View File

@ -26,7 +26,7 @@
<module name="org.jboss.jandex"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.vfs"/>
<module name="org.javassist" export="true"/>
<module name="org.javassist" export="true" optional="true"/>
<module name="org.hibernate.commons-annotations"/>
<module name="org.hibernate.orm.jipijapa-hibernate5" services="import" slot="${slot}"/>
<module name="net.bytebuddy" slot="${bytebuddySlot}" />

View File

@ -0,0 +1,107 @@
/*
* 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.wildfly.integrationtest;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.Session;
import org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl;
import org.hibernate.bytecode.spi.BasicProxyFactory;
import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.bytecode.spi.ProxyFactoryFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.wildfly.model.Kryptonite;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.Asset;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.descriptor.api.Descriptors;
import org.jboss.shrinkwrap.descriptor.api.persistence21.PersistenceDescriptor;
import org.jboss.shrinkwrap.descriptor.api.persistence21.PersistenceUnitTransactionType;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
/**
* The purpose of this test is to check that it's still possible to use Javassist as byte code provider with WildFly.
*/
@RunWith(Arquillian.class)
public class JavassistHibernateModulesOnWildflyTest {
private static final String ORM_VERSION = Session.class.getPackage().getImplementationVersion();
private static final String ORM_MINOR_VERSION = ORM_VERSION.substring( 0, ORM_VERSION.indexOf( ".", ORM_VERSION.indexOf( "." ) + 1) );
@Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create( WebArchive.class )
.addClass( Kryptonite.class )
.addAsWebInfResource( EmptyAsset.INSTANCE, "beans.xml" )
.addAsResource( persistenceXml(), "META-INF/persistence.xml" );
}
private static Asset persistenceXml() {
PersistenceDescriptor persistenceXml = Descriptors.create( PersistenceDescriptor.class )
.version( "2.1" )
.createPersistenceUnit()
.name( "primary" )
.transactionType( PersistenceUnitTransactionType._JTA )
.jtaDataSource( "java:jboss/datasources/ExampleDS" )
.getOrCreateProperties()
// We want to use the ORM from this build instead of the one coming with WildFly
.createProperty().name( "jboss.as.jpa.providerModule" ).value( "org.hibernate:" + ORM_MINOR_VERSION ).up()
.createProperty().name( "hibernate.hbm2ddl.auto" ).value( "create-drop" ).up()
.createProperty().name( "hibernate.allow_update_outside_transaction" ).value( "true" ).up()
.up().up();
return new StringAsset( persistenceXml.exportAsString() );
}
@PersistenceContext
private EntityManager entityManager;
@Test
public void shouldUseHibernateOrm52() {
Session session = entityManager.unwrap( Session.class );
Kryptonite kryptonite1 = new Kryptonite();
kryptonite1.id = 1L;
kryptonite1.description = "Some Kryptonite";
session.persist( kryptonite1 );
// EntityManager methods exposed through Session only as of 5.2
Kryptonite loaded = session.find( Kryptonite.class, 1L );
assertThat( loaded.description, equalTo( "Some Kryptonite" ) );
}
@Test
public void shouldBeAbleToCreateProxyWithJavassist() {
Properties properties = new Properties();
properties.setProperty( AvailableSettings.BYTECODE_PROVIDER, Environment.BYTECODE_PROVIDER_NAME_JAVASSIST );
// hibernate.bytecode.provider is a system property. I don't want to apply it
// to the arquillian.xml because it will change the other tests as well.
// I guess this is a more explicit way anyway to test that Javassist is available.
BytecodeProvider provider = Environment.buildBytecodeProvider( properties );
assertThat( provider.getClass(), equalTo( BytecodeProviderImpl.class ) );
ProxyFactoryFactory factory = provider.getProxyFactoryFactory();
BasicProxyFactory basicProxyFactory = factory.buildBasicProxyFactory( Kryptonite.class, null );
Object proxy = basicProxyFactory.getProxy();
assertThat( proxy, notNullValue() );
}
}

View File

@ -6,9 +6,6 @@
*/
package org.hibernate.testing.bytecode.enhancement;
import javassist.CtClass;
import javassist.CtField;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.bytecode.enhance.spi.UnloadedField;

View File

@ -21,6 +21,7 @@ import javax.persistence.SharedCacheMode;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
@ -518,4 +519,8 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase {
protected void inSession(Consumer<SessionImplementor> action) {
TransactionUtil2.inSession( sessionFactory(), action );
}
protected void inStatelessSession(Consumer<StatelessSession> action) {
TransactionUtil2.inStatelessSession( sessionFactory(), action );
}
}