HHH-7667 - Investigate expanding bytecode enhancement support
(cherry picked from commit 30b3bd1564
)
This commit is contained in:
parent
60836cda1b
commit
8c96a4a2c6
|
@ -23,34 +23,58 @@
|
|||
*/
|
||||
package org.hibernate.bytecode.enhance.spi;
|
||||
|
||||
import javassist.CtClass;
|
||||
import javassist.CtField;
|
||||
|
||||
/**
|
||||
* todo : not sure its a great idea to expose Javassist classes this way.
|
||||
* maybe wrap them in our own contracts?
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EnhancementContext {
|
||||
/**
|
||||
* Does the given class name represent a entity class?
|
||||
* Obtain access to the ClassLoader that can be used to load Class references. In JPA SPI terms, this
|
||||
* should be a "temporary class loader" as defined by
|
||||
* {@link javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader()}
|
||||
*/
|
||||
public ClassLoader getLoadingClassLoader();
|
||||
|
||||
/**
|
||||
* Does the given class descriptor represent a entity class?
|
||||
*
|
||||
* @param className The name of the class to check.
|
||||
* @param classDescriptor The descriptor of the class to check.
|
||||
*
|
||||
* @return {@code true} if the class is an entity; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isEntityClass(String className);
|
||||
public boolean isEntityClass(CtClass classDescriptor);
|
||||
|
||||
/**
|
||||
* Does the given class name represent an embeddable/component class?
|
||||
*
|
||||
* @param className The name of the class to check.
|
||||
* @param classDescriptor The descriptor of the class to check.
|
||||
*
|
||||
* @return {@code true} if the class is an embeddable/component; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isCompositeClass(String className);
|
||||
public boolean isCompositeClass(CtClass classDescriptor);
|
||||
|
||||
/**
|
||||
* Should we in-line dirty checking for persistent attributes for this class?
|
||||
*
|
||||
* @param classDescriptor The descriptor of the class to check.
|
||||
*
|
||||
* @return {@code true} indicates that dirty checking should be in-lined within the entity; {@code false}
|
||||
* indicates it should not. In-lined is more easily serializable and probably more performant.
|
||||
*/
|
||||
public boolean doDirtyCheckingInline(CtClass classDescriptor);
|
||||
|
||||
public boolean hasLazyLoadableAttributes(CtClass classDescriptor);
|
||||
|
||||
// todo : may be better to invert these 2 such that the context is asked for an ordered list of persistent fields for an entity/composite
|
||||
|
||||
/**
|
||||
* Does the field represent persistent state? Persistent fields will be "enhanced".
|
||||
* <p/>
|
||||
* todo : not sure its a great idea to expose Javassist classes this way.
|
||||
// may be better to perform basic checks in the caller (non-static, etc) and call out with just the
|
||||
// Class name and field name...
|
||||
|
||||
|
@ -59,4 +83,16 @@ public interface EnhancementContext {
|
|||
* @return {@code true} if the field is ; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isPersistentField(CtField ctField);
|
||||
|
||||
/**
|
||||
* For fields which are persistent (according to {@link #isPersistentField}), determine the corresponding ordering
|
||||
* maintained within the Hibernate metamodel.
|
||||
|
||||
* @param persistentFields The persistent field references.
|
||||
*
|
||||
* @return The ordered references.
|
||||
*/
|
||||
public CtField[] order(CtField[] persistentFields);
|
||||
|
||||
public boolean isLazyLoadable(CtField field);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -81,7 +81,7 @@ public class EntityEntryContext {
|
|||
final boolean alreadyAssociated;
|
||||
if ( ManagedEntity.class.isInstance( entity ) ) {
|
||||
managedEntity = (ManagedEntity) entity;
|
||||
alreadyAssociated = managedEntity.hibernate_getEntityEntry() != null;
|
||||
alreadyAssociated = managedEntity.$$_hibernate_getEntityEntry() != null;
|
||||
}
|
||||
else {
|
||||
ManagedEntity wrapper = null;
|
||||
|
@ -105,7 +105,7 @@ public class EntityEntryContext {
|
|||
}
|
||||
|
||||
// associate the EntityEntry with the entity
|
||||
managedEntity.hibernate_setEntityEntry( entityEntry );
|
||||
managedEntity.$$_hibernate_setEntityEntry( entityEntry );
|
||||
|
||||
if ( alreadyAssociated ) {
|
||||
// if the entity was already associated with the context, skip the linking step.
|
||||
|
@ -120,8 +120,8 @@ public class EntityEntryContext {
|
|||
count = 1;
|
||||
}
|
||||
else {
|
||||
tail.hibernate_setNextManagedEntity( managedEntity );
|
||||
managedEntity.hibernate_setPreviousManagedEntity( tail );
|
||||
tail.$$_hibernate_setNextManagedEntity( managedEntity );
|
||||
managedEntity.$$_hibernate_setPreviousManagedEntity( tail );
|
||||
tail = managedEntity;
|
||||
count++;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ public class EntityEntryContext {
|
|||
|
||||
return managedEntity == null
|
||||
? null
|
||||
: managedEntity.hibernate_getEntityEntry();
|
||||
: managedEntity.$$_hibernate_getEntityEntry();
|
||||
}
|
||||
|
||||
public EntityEntry removeEntityEntry(Object entity) {
|
||||
|
@ -167,10 +167,10 @@ public class EntityEntryContext {
|
|||
}
|
||||
|
||||
// prepare for re-linking...
|
||||
ManagedEntity previous = managedEntity.hibernate_getPreviousManagedEntity();
|
||||
ManagedEntity next = managedEntity.hibernate_getNextManagedEntity();
|
||||
managedEntity.hibernate_setPreviousManagedEntity( null );
|
||||
managedEntity.hibernate_setNextManagedEntity( null );
|
||||
ManagedEntity previous = managedEntity.$$_hibernate_getPreviousManagedEntity();
|
||||
ManagedEntity next = managedEntity.$$_hibernate_getNextManagedEntity();
|
||||
managedEntity.$$_hibernate_setPreviousManagedEntity( null );
|
||||
managedEntity.$$_hibernate_setNextManagedEntity( null );
|
||||
|
||||
count--;
|
||||
|
||||
|
@ -190,7 +190,7 @@ public class EntityEntryContext {
|
|||
head = next;
|
||||
}
|
||||
else {
|
||||
previous.hibernate_setNextManagedEntity( next );
|
||||
previous.$$_hibernate_setNextManagedEntity( next );
|
||||
}
|
||||
|
||||
if ( next == null ) {
|
||||
|
@ -199,12 +199,12 @@ public class EntityEntryContext {
|
|||
tail = previous;
|
||||
}
|
||||
else {
|
||||
next.hibernate_setPreviousManagedEntity( previous );
|
||||
next.$$_hibernate_setPreviousManagedEntity( previous );
|
||||
}
|
||||
}
|
||||
|
||||
EntityEntry theEntityEntry = managedEntity.hibernate_getEntityEntry();
|
||||
managedEntity.hibernate_setEntityEntry( null );
|
||||
EntityEntry theEntityEntry = managedEntity.$$_hibernate_getEntityEntry();
|
||||
managedEntity.$$_hibernate_setEntityEntry( null );
|
||||
return theEntityEntry;
|
||||
}
|
||||
|
||||
|
@ -215,10 +215,10 @@ public class EntityEntryContext {
|
|||
ManagedEntity managedEntity = head;
|
||||
while ( managedEntity != null ) {
|
||||
reentrantSafeEntries[i++] = new EntityEntryCrossRefImpl(
|
||||
managedEntity.hibernate_getEntityInstance(),
|
||||
managedEntity.hibernate_getEntityEntry()
|
||||
managedEntity.$$_hibernate_getEntityInstance(),
|
||||
managedEntity.$$_hibernate_getEntityEntry()
|
||||
);
|
||||
managedEntity = managedEntity.hibernate_getNextManagedEntity();
|
||||
managedEntity = managedEntity.$$_hibernate_getNextManagedEntity();
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
|
@ -230,11 +230,11 @@ public class EntityEntryContext {
|
|||
|
||||
ManagedEntity node = head;
|
||||
while ( node != null ) {
|
||||
final ManagedEntity nextNode = node.hibernate_getNextManagedEntity();
|
||||
final ManagedEntity nextNode = node.$$_hibernate_getNextManagedEntity();
|
||||
|
||||
node.hibernate_setEntityEntry( null );
|
||||
node.hibernate_setPreviousManagedEntity( null );
|
||||
node.hibernate_setNextManagedEntity( null );
|
||||
node.$$_hibernate_setEntityEntry( null );
|
||||
node.$$_hibernate_setPreviousManagedEntity( null );
|
||||
node.$$_hibernate_setNextManagedEntity( null );
|
||||
|
||||
node = nextNode;
|
||||
}
|
||||
|
@ -257,9 +257,9 @@ public class EntityEntryContext {
|
|||
|
||||
ManagedEntity node = head;
|
||||
while ( node != null ) {
|
||||
node.hibernate_getEntityEntry().setLockMode( LockMode.NONE );
|
||||
node.$$_hibernate_getEntityEntry().setLockMode( LockMode.NONE );
|
||||
|
||||
node = node.hibernate_getNextManagedEntity();
|
||||
node = node.$$_hibernate_getNextManagedEntity();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,11 +273,11 @@ public class EntityEntryContext {
|
|||
ManagedEntity managedEntity = head;
|
||||
while ( managedEntity != null ) {
|
||||
// so we know whether or not to build a ManagedEntityImpl on deserialize
|
||||
oos.writeBoolean( managedEntity == managedEntity.hibernate_getEntityInstance() );
|
||||
oos.writeObject( managedEntity.hibernate_getEntityInstance() );
|
||||
managedEntity.hibernate_getEntityEntry().serialize( oos );
|
||||
oos.writeBoolean( managedEntity == managedEntity.$$_hibernate_getEntityInstance() );
|
||||
oos.writeObject( managedEntity.$$_hibernate_getEntityInstance() );
|
||||
managedEntity.$$_hibernate_getEntityEntry().serialize( oos );
|
||||
|
||||
managedEntity = managedEntity.hibernate_getNextManagedEntity();
|
||||
managedEntity = managedEntity.$$_hibernate_getNextManagedEntity();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,14 +310,14 @@ public class EntityEntryContext {
|
|||
}
|
||||
context.nonEnhancedEntityXref.put( entity, managedEntity );
|
||||
}
|
||||
managedEntity.hibernate_setEntityEntry( entry );
|
||||
managedEntity.$$_hibernate_setEntityEntry( entry );
|
||||
|
||||
if ( previous == null ) {
|
||||
context.head = managedEntity;
|
||||
}
|
||||
else {
|
||||
previous.hibernate_setNextManagedEntity( managedEntity );
|
||||
managedEntity.hibernate_setPreviousManagedEntity( previous );
|
||||
previous.$$_hibernate_setNextManagedEntity( managedEntity );
|
||||
managedEntity.$$_hibernate_setPreviousManagedEntity( previous );
|
||||
}
|
||||
|
||||
previous = managedEntity;
|
||||
|
@ -343,37 +343,37 @@ public class EntityEntryContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object hibernate_getEntityInstance() {
|
||||
public Object $$_hibernate_getEntityInstance() {
|
||||
return entityInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityEntry hibernate_getEntityEntry() {
|
||||
public EntityEntry $$_hibernate_getEntityEntry() {
|
||||
return entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hibernate_setEntityEntry(EntityEntry entityEntry) {
|
||||
public void $$_hibernate_setEntityEntry(EntityEntry entityEntry) {
|
||||
this.entityEntry = entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedEntity hibernate_getNextManagedEntity() {
|
||||
public ManagedEntity $$_hibernate_getNextManagedEntity() {
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hibernate_setNextManagedEntity(ManagedEntity next) {
|
||||
public void $$_hibernate_setNextManagedEntity(ManagedEntity next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedEntity hibernate_getPreviousManagedEntity() {
|
||||
public ManagedEntity $$_hibernate_getPreviousManagedEntity() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hibernate_setPreviousManagedEntity(ManagedEntity previous) {
|
||||
public void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous) {
|
||||
this.previous = previous;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,14 +27,14 @@ package org.hibernate.engine.spi;
|
|||
* Specialized {@link Managed} contract for entity classes. Essentially provides access to information
|
||||
* about an instance's association to a Session/EntityManager. Specific information includes:<ul>
|
||||
* <li>
|
||||
* the association's {@link EntityEntry} (by way of {@link #hibernate_getEntityEntry()} and
|
||||
* {@link #hibernate_setEntityEntry}). EntityEntry describes states, snapshots, etc.
|
||||
* the association's {@link EntityEntry} (by way of {@link #$$_hibernate_getEntityEntry} and
|
||||
* {@link #$$_hibernate_setEntityEntry}). EntityEntry describes states, snapshots, etc.
|
||||
* </li>
|
||||
* <li>
|
||||
* link information. ManagedEntity instances are part of a "linked list", thus link information
|
||||
* describes the next and previous entries/nodes in that ordering. See
|
||||
* {@link #hibernate_getNextManagedEntity}, {@link #hibernate_setNextManagedEntity},
|
||||
* {@link #hibernate_getPreviousManagedEntity()}, {@link #hibernate_setPreviousManagedEntity}
|
||||
* {@link #$$_hibernate_getNextManagedEntity}, {@link #$$_hibernate_setNextManagedEntity},
|
||||
* {@link #$$_hibernate_getPreviousManagedEntity}, {@link #$$_hibernate_setPreviousManagedEntity}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
|
@ -46,16 +46,16 @@ public interface ManagedEntity extends Managed {
|
|||
*
|
||||
* @return The entity instance.
|
||||
*/
|
||||
public Object hibernate_getEntityInstance();
|
||||
public Object $$_hibernate_getEntityInstance();
|
||||
|
||||
/**
|
||||
* Provides access to the associated EntityEntry.
|
||||
*
|
||||
* @return The EntityEntry associated with this entity instance.
|
||||
*
|
||||
* @see #hibernate_setEntityEntry
|
||||
* @see #$$_hibernate_setEntityEntry
|
||||
*/
|
||||
public EntityEntry hibernate_getEntityEntry();
|
||||
public EntityEntry $$_hibernate_getEntityEntry();
|
||||
|
||||
/**
|
||||
* Injects the EntityEntry associated with this entity instance. The EntityEntry represents state associated
|
||||
|
@ -63,13 +63,37 @@ public interface ManagedEntity extends Managed {
|
|||
*
|
||||
* @param entityEntry The EntityEntry associated with this entity instance.
|
||||
*/
|
||||
public void hibernate_setEntityEntry(EntityEntry entityEntry);
|
||||
public void $$_hibernate_setEntityEntry(EntityEntry entityEntry);
|
||||
|
||||
public ManagedEntity hibernate_getPreviousManagedEntity();
|
||||
/**
|
||||
* Part of entry linking; obtain reference to the previous entry. Can be {@code null}, which should indicate
|
||||
* this is the head node.
|
||||
*
|
||||
* @return The previous entry
|
||||
*/
|
||||
public ManagedEntity $$_hibernate_getPreviousManagedEntity();
|
||||
|
||||
public void hibernate_setPreviousManagedEntity(ManagedEntity previous);
|
||||
/**
|
||||
* Part of entry linking; sets the previous entry. Again, can be {@code null}, which should indicate
|
||||
* this is (now) the head node.
|
||||
*
|
||||
* @param previous The previous entry
|
||||
*/
|
||||
public void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous);
|
||||
|
||||
public ManagedEntity hibernate_getNextManagedEntity();
|
||||
/**
|
||||
* Part of entry linking; obtain reference to the next entry. Can be {@code null}, which should indicate
|
||||
* this is the tail node.
|
||||
*
|
||||
* @return The next entry
|
||||
*/
|
||||
public ManagedEntity $$_hibernate_getNextManagedEntity();
|
||||
|
||||
public void hibernate_setNextManagedEntity(ManagedEntity next);
|
||||
/**
|
||||
* Part of entry linking; sets the next entry. Again, can be {@code null}, which should indicate
|
||||
* this is (now) the tail node.
|
||||
*
|
||||
* @param next The next entry
|
||||
*/
|
||||
public void $$_hibernate_setNextManagedEntity(ManagedEntity next);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface PersistentAttributeInterceptable {
|
||||
public PersistentAttributeInterceptor $$_hibernate_getInterceptor();
|
||||
public void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface PersistentAttributeInterceptor {
|
||||
|
||||
public boolean readBoolean(Object obj, String name, boolean oldValue);
|
||||
|
||||
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue);
|
||||
|
||||
public byte readByte(Object obj, String name, byte oldValue);
|
||||
|
||||
public byte writeByte(Object obj, String name, byte oldValue, byte newValue);
|
||||
|
||||
public char readChar(Object obj, String name, char oldValue);
|
||||
|
||||
public char writeChar(Object obj, String name, char oldValue, char newValue);
|
||||
|
||||
public short readShort(Object obj, String name, short oldValue);
|
||||
|
||||
public short writeShort(Object obj, String name, short oldValue, short newValue);
|
||||
|
||||
public int readInt(Object obj, String name, int oldValue);
|
||||
|
||||
public int writeInt(Object obj, String name, int oldValue, int newValue);
|
||||
|
||||
public float readFloat(Object obj, String name, float oldValue);
|
||||
|
||||
public float writeFloat(Object obj, String name, float oldValue, float newValue);
|
||||
|
||||
public double readDouble(Object obj, String name, double oldValue);
|
||||
|
||||
public double writeDouble(Object obj, String name, double oldValue, double newValue);
|
||||
|
||||
public long readLong(Object obj, String name, long oldValue);
|
||||
|
||||
public long writeLong(Object obj, String name, long oldValue, long newValue);
|
||||
|
||||
public Object readObject(Object obj, String name, Object oldValue);
|
||||
|
||||
public Object writeObject(Object obj, String name, Object oldValue, Object newValue);
|
||||
|
||||
}
|
|
@ -28,6 +28,7 @@ import javax.persistence.Transient;
|
|||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -35,9 +36,6 @@ import java.util.List;
|
|||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtField;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.bytecode.AnnotationsAttribute;
|
||||
import javassist.bytecode.annotation.Annotation;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Project;
|
||||
|
@ -58,61 +56,25 @@ import org.hibernate.bytecode.enhance.spi.Enhancer;
|
|||
*
|
||||
* @see org.hibernate.engine.spi.Managed
|
||||
*/
|
||||
public class EnhancementTask extends Task {
|
||||
public class EnhancementTask extends Task implements EnhancementContext {
|
||||
private List<FileSet> filesets = new ArrayList<FileSet>();
|
||||
|
||||
// Enhancer also builds CtClass instances. Might make sense to share these (ClassPool).
|
||||
private final ClassPool classPool = new ClassPool( false );
|
||||
private final Enhancer enhancer = new Enhancer( this );
|
||||
|
||||
public void addFileset(FileSet set) {
|
||||
this.filesets.add( set );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws BuildException {
|
||||
EnhancementContext enhancementContext = new EnhancementContext() {
|
||||
@Override
|
||||
public boolean isEntityClass(String className) {
|
||||
// currently we only call enhance on the classes with @Entity, so here we always return true
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompositeClass(String className) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistentField(CtField ctField) {
|
||||
// current check is to look for @Transient
|
||||
return ! ctField.hasAnnotation( Transient.class );
|
||||
}
|
||||
};
|
||||
log( "Starting Hibernate EnhancementTask execution", Project.MSG_INFO );
|
||||
|
||||
// we use the CtClass stuff here just as a simple vehicle for obtaining low level information about
|
||||
// the class(es) contained in a file while still maintaining easy access to the underlying byte[]
|
||||
//
|
||||
// Enhancer also builds CtClass instances. Might make sense to share these (ClassPool).
|
||||
final ClassPool classPool = new ClassPool( false );
|
||||
final List<CtClass> ctClassList = collectCtClasses( classPool );
|
||||
|
||||
final Enhancer enhancer = new Enhancer( enhancementContext );
|
||||
for ( CtClass ctClass : ctClassList ) {
|
||||
try {
|
||||
enhancer.enhance( ctClass.getName(), ctClass.toBytecode() );
|
||||
}
|
||||
catch (Exception e) {
|
||||
log(
|
||||
"Unable to enhance class : " + ctClass.getName(),
|
||||
e,
|
||||
Project.MSG_WARN
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private List<CtClass> collectCtClasses(ClassPool classPool) {
|
||||
final List<CtClass> ctClassList = new ArrayList<CtClass>();
|
||||
|
||||
final Project project = getProject();
|
||||
|
||||
for ( FileSet fileSet : filesets ) {
|
||||
final File fileSetBaseDir = fileSet.getDir( project );
|
||||
final DirectoryScanner directoryScanner = fileSet.getDirectoryScanner( project );
|
||||
|
@ -121,40 +83,110 @@ public class EnhancementTask extends Task {
|
|||
if ( ! javaClassFile.exists() ) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final CtClass ctClass = classPool.makeClass( new FileInputStream( javaClassFile ) );
|
||||
collectCtClasses( ctClassList, ctClass );
|
||||
}
|
||||
catch (FileNotFoundException ignore) {
|
||||
// should not ever happen because of explicit check above
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildException(
|
||||
String.format(
|
||||
"Error processing included file [%s : %s]",
|
||||
fileSetBaseDir.getAbsolutePath(),
|
||||
relativeIncludedFileName
|
||||
),
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
processClassFile( javaClassFile );
|
||||
}
|
||||
}
|
||||
|
||||
return ctClassList;
|
||||
}
|
||||
|
||||
private void collectCtClasses(List<CtClass> ctClassList, CtClass ctClass) {
|
||||
if ( ctClass.hasAnnotation( Entity.class ) ) {
|
||||
ctClassList.add( ctClass );
|
||||
}
|
||||
|
||||
private void processClassFile(File javaClassFile) {
|
||||
try {
|
||||
for ( CtClass nestedCtClass : ctClass.getNestedClasses() ) {
|
||||
collectCtClasses( ctClassList, nestedCtClass );
|
||||
final CtClass ctClass = classPool.makeClass( new FileInputStream( javaClassFile ) );
|
||||
if ( ! shouldInclude( ctClass ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final byte[] enhancedBytecode;
|
||||
try {
|
||||
enhancedBytecode = enhancer.enhance( ctClass.getName(), ctClass.toBytecode() );
|
||||
}
|
||||
catch (Exception e) {
|
||||
log( "Unable to enhance class [" + ctClass.getName() + "]", e, Project.MSG_WARN );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( javaClassFile.delete() ) {
|
||||
if ( ! javaClassFile.createNewFile() ) {
|
||||
log( "Unable to recreate class file [" + ctClass.getName() + "]", Project.MSG_INFO );
|
||||
}
|
||||
}
|
||||
else {
|
||||
log( "Unable to delete class file [" + ctClass.getName() + "]", Project.MSG_INFO );
|
||||
}
|
||||
|
||||
FileOutputStream outputStream = new FileOutputStream( javaClassFile, false );
|
||||
try {
|
||||
outputStream.write( enhancedBytecode );
|
||||
outputStream.flush();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
outputStream.close();
|
||||
}
|
||||
catch ( IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NotFoundException ignore) {
|
||||
catch (FileNotFoundException ignore) {
|
||||
// should not ever happen because of explicit checks
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildException(
|
||||
String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldInclude(CtClass ctClass) {
|
||||
// we currently only handle entity enhancement
|
||||
return ! ctClass.hasAnnotation( Entity.class );
|
||||
}
|
||||
|
||||
|
||||
// EnhancementContext impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
public ClassLoader getLoadingClassLoader() {
|
||||
return getClass().getClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEntityClass(CtClass classDescriptor) {
|
||||
// currently we only call enhance on the classes with @Entity, so here we always return true
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompositeClass(CtClass classDescriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doDirtyCheckingInline(CtClass classDescriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLazyLoadableAttributes(CtClass classDescriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazyLoadable(CtField field) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistentField(CtField ctField) {
|
||||
// current check is to look for @Transient
|
||||
return ! ctField.hasAnnotation( Transient.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CtField[] order(CtField[] persistentFields) {
|
||||
// for now...
|
||||
return persistentFields;
|
||||
// eventually needs to consult the Hibernate metamodel for proper ordering
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,35 +23,29 @@
|
|||
*/
|
||||
package org.hibernate.test.bytecode.enhancement;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtField;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
|
||||
import org.hibernate.bytecode.enhance.spi.Enhancer;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.ManagedEntity;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -65,19 +59,44 @@ import static org.junit.Assert.assertSame;
|
|||
public class EnhancerTest extends BaseUnitTestCase {
|
||||
private static EnhancementContext enhancementContext = new EnhancementContext() {
|
||||
@Override
|
||||
public boolean isEntityClass(String className) {
|
||||
public ClassLoader getLoadingClassLoader() {
|
||||
return getClass().getClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEntityClass(CtClass classDescriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompositeClass(String className) {
|
||||
public boolean isCompositeClass(CtClass classDescriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doDirtyCheckingInline(CtClass classDescriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLazyLoadableAttributes(CtClass classDescriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazyLoadable(CtField field) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistentField(CtField ctField) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CtField[] order(CtField[] persistentFields) {
|
||||
return persistentFields;
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
|
@ -94,9 +113,9 @@ public class EnhancerTest extends BaseUnitTestCase {
|
|||
assertFalse( "entity was not enhanced", Arrays.equals( original, enhanced ) );
|
||||
|
||||
ClassLoader cl = new ClassLoader() { };
|
||||
ClassPool cp2 = new ClassPool( false );
|
||||
cp2.appendClassPath( new LoaderClassPath( cl ) );
|
||||
CtClass enhancedCtClass = cp2.makeClass( new ByteArrayInputStream( enhanced ) );
|
||||
ClassPool cp = new ClassPool( false );
|
||||
cp.appendClassPath( new LoaderClassPath( cl ) );
|
||||
CtClass enhancedCtClass = cp.makeClass( new ByteArrayInputStream( enhanced ) );
|
||||
Class entityClass = enhancedCtClass.toClass( cl, this.getClass().getProtectionDomain() );
|
||||
Object entityInstance = entityClass.newInstance();
|
||||
|
||||
|
@ -124,6 +143,29 @@ public class EnhancerTest extends BaseUnitTestCase {
|
|||
Method nextSetter = entityClass.getMethod( Enhancer.PREVIOUS_SETTER_NAME, ManagedEntity.class );
|
||||
nextSetter.invoke( entityInstance, entityInstance );
|
||||
assertSame( entityInstance, nextGetter.invoke( entityInstance ) );
|
||||
|
||||
// add an attribute interceptor...
|
||||
Method interceptorGetter = entityClass.getMethod( Enhancer.INTERCEPTOR_GETTER_NAME );
|
||||
Method interceptorSetter = entityClass.getMethod( Enhancer.INTERCEPTOR_SETTER_NAME, PersistentAttributeInterceptor.class );
|
||||
|
||||
assertNull( interceptorGetter.invoke( entityInstance ) );
|
||||
entityClass.getMethod( "getId" ).invoke( entityInstance );
|
||||
|
||||
interceptorSetter.invoke( entityInstance, new LocalPersistentAttributeInterceptor() );
|
||||
assertNotNull( interceptorGetter.invoke( entityInstance ) );
|
||||
|
||||
// dirty checking is unfortunately just printlns for now... just verify the test output
|
||||
entityClass.getMethod( "getId" ).invoke( entityInstance );
|
||||
entityClass.getMethod( "setId", Long.class ).invoke( entityInstance, entityClass.getMethod( "getId" ).invoke( entityInstance ) );
|
||||
entityClass.getMethod( "setId", Long.class ).invoke( entityInstance, 1L );
|
||||
|
||||
entityClass.getMethod( "isActive" ).invoke( entityInstance );
|
||||
entityClass.getMethod( "setActive", boolean.class ).invoke( entityInstance, entityClass.getMethod( "isActive" ).invoke( entityInstance ) );
|
||||
entityClass.getMethod( "setActive", boolean.class ).invoke( entityInstance, true );
|
||||
|
||||
entityClass.getMethod( "getSomeNumber" ).invoke( entityInstance );
|
||||
entityClass.getMethod( "setSomeNumber", long.class ).invoke( entityInstance, entityClass.getMethod( "getSomeNumber" ).invoke( entityInstance ) );
|
||||
entityClass.getMethod( "setSomeNumber", long.class ).invoke( entityInstance, 1L );
|
||||
}
|
||||
|
||||
private CtClass generateCtClassForAnEntity(Class entityClassToEnhance) throws Exception {
|
||||
|
@ -153,4 +195,114 @@ public class EnhancerTest extends BaseUnitTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
private class LocalPersistentAttributeInterceptor implements PersistentAttributeInterceptor {
|
||||
@Override
|
||||
public boolean readBoolean(Object obj, String name, boolean oldValue) {
|
||||
System.out.println( "Reading boolean [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
|
||||
System.out.println( "Writing boolean [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte(Object obj, String name, byte oldValue) {
|
||||
System.out.println( "Reading byte [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
|
||||
System.out.println( "Writing byte [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar(Object obj, String name, char oldValue) {
|
||||
System.out.println( "Reading char [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char writeChar(Object obj, String name, char oldValue, char newValue) {
|
||||
System.out.println( "Writing char [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort(Object obj, String name, short oldValue) {
|
||||
System.out.println( "Reading short [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short writeShort(Object obj, String name, short oldValue, short newValue) {
|
||||
System.out.println( "Writing short [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt(Object obj, String name, int oldValue) {
|
||||
System.out.println( "Reading int [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writeInt(Object obj, String name, int oldValue, int newValue) {
|
||||
System.out.println( "Writing int [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat(Object obj, String name, float oldValue) {
|
||||
System.out.println( "Reading float [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
|
||||
System.out.println( "Writing float [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble(Object obj, String name, double oldValue) {
|
||||
System.out.println( "Reading double [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
|
||||
System.out.println( "Writing double [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong(Object obj, String name, long oldValue) {
|
||||
System.out.println( "Reading long [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeLong(Object obj, String name, long oldValue, long newValue) {
|
||||
System.out.println( "Writing long [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readObject(Object obj, String name, Object oldValue) {
|
||||
System.out.println( "Reading Object [" + name + "]" );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
|
||||
System.out.println( "Writing Object [" + name + "]" );
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,23 +56,23 @@ public class MostBasicEnhancementTest extends BaseCoreFunctionalTestCase {
|
|||
MyEntity myEntity = (MyEntity) s.get( MyEntity.class, 1L );
|
||||
MyEntity myEntity2 = (MyEntity) s.get( MyEntity.class, 2L );
|
||||
|
||||
assertNotNull( myEntity.hibernate_getEntityInstance() );
|
||||
assertSame( myEntity, myEntity.hibernate_getEntityInstance() );
|
||||
assertNotNull( myEntity.hibernate_getEntityEntry() );
|
||||
assertNull( myEntity.hibernate_getPreviousManagedEntity() );
|
||||
assertNotNull( myEntity.hibernate_getNextManagedEntity() );
|
||||
assertNotNull( myEntity.$$_hibernate_getEntityInstance() );
|
||||
assertSame( myEntity, myEntity.$$_hibernate_getEntityInstance() );
|
||||
assertNotNull( myEntity.$$_hibernate_getEntityEntry() );
|
||||
assertNull( myEntity.$$_hibernate_getPreviousManagedEntity() );
|
||||
assertNotNull( myEntity.$$_hibernate_getNextManagedEntity() );
|
||||
|
||||
assertNotNull( myEntity2.hibernate_getEntityInstance() );
|
||||
assertSame( myEntity2, myEntity2.hibernate_getEntityInstance() );
|
||||
assertNotNull( myEntity2.hibernate_getEntityEntry() );
|
||||
assertNotNull( myEntity2.hibernate_getPreviousManagedEntity() );
|
||||
assertNull( myEntity2.hibernate_getNextManagedEntity() );
|
||||
assertNotNull( myEntity2.$$_hibernate_getEntityInstance() );
|
||||
assertSame( myEntity2, myEntity2.$$_hibernate_getEntityInstance() );
|
||||
assertNotNull( myEntity2.$$_hibernate_getEntityEntry() );
|
||||
assertNotNull( myEntity2.$$_hibernate_getPreviousManagedEntity() );
|
||||
assertNull( myEntity2.$$_hibernate_getNextManagedEntity() );
|
||||
|
||||
s.createQuery( "delete MyEntity" ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
assertNull( myEntity.hibernate_getEntityEntry() );
|
||||
assertNull( myEntity.$$_hibernate_getEntityEntry() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,37 +70,37 @@ public class MyEntity implements ManagedEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object hibernate_getEntityInstance() {
|
||||
public Object $$_hibernate_getEntityInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityEntry hibernate_getEntityEntry() {
|
||||
public EntityEntry $$_hibernate_getEntityEntry() {
|
||||
return entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hibernate_setEntityEntry(EntityEntry entityEntry) {
|
||||
public void $$_hibernate_setEntityEntry(EntityEntry entityEntry) {
|
||||
this.entityEntry = entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedEntity hibernate_getNextManagedEntity() {
|
||||
public ManagedEntity $$_hibernate_getNextManagedEntity() {
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hibernate_setNextManagedEntity(ManagedEntity next) {
|
||||
public void $$_hibernate_setNextManagedEntity(ManagedEntity next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedEntity hibernate_getPreviousManagedEntity() {
|
||||
public ManagedEntity $$_hibernate_getPreviousManagedEntity() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hibernate_setPreviousManagedEntity(ManagedEntity previous) {
|
||||
public void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous) {
|
||||
this.previous = previous;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.bytecode.enhancement;
|
||||
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.ManagedEntity;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SampleEntity implements ManagedEntity, PersistentAttributeInterceptable {
|
||||
@Transient
|
||||
private transient EntityEntry entityEntry;
|
||||
@Transient
|
||||
private transient ManagedEntity previous;
|
||||
@Transient
|
||||
private transient ManagedEntity next;
|
||||
@Transient
|
||||
private transient PersistentAttributeInterceptor interceptor;
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return hibernate_read_id();
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
hibernate_write_id( id );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return hibernate_read_name();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
hibernate_write_name( name );
|
||||
}
|
||||
|
||||
private Long hibernate_read_id() {
|
||||
if ( $$_hibernate_getInterceptor() != null ) {
|
||||
this.id = (Long) $$_hibernate_getInterceptor().readObject( this, "id", this.id );
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private void hibernate_write_id(Long id) {
|
||||
Long localVar = id;
|
||||
if ( $$_hibernate_getInterceptor() != null ) {
|
||||
localVar = (Long) $$_hibernate_getInterceptor().writeObject( this, "id", this.id, id );
|
||||
}
|
||||
this.id = localVar;
|
||||
}
|
||||
|
||||
private String hibernate_read_name() {
|
||||
if ( $$_hibernate_getInterceptor() != null ) {
|
||||
this.name = (String) $$_hibernate_getInterceptor().readObject( this, "name", this.name );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private void hibernate_write_name(String name) {
|
||||
String localName = name;
|
||||
if ( $$_hibernate_getInterceptor() != null ) {
|
||||
localName = (String) $$_hibernate_getInterceptor().writeObject( this, "name", this.name, name );
|
||||
}
|
||||
this.name = localName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object $$_hibernate_getEntityInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityEntry $$_hibernate_getEntityEntry() {
|
||||
return entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void $$_hibernate_setEntityEntry(EntityEntry entityEntry) {
|
||||
this.entityEntry = entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedEntity $$_hibernate_getNextManagedEntity() {
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void $$_hibernate_setNextManagedEntity(ManagedEntity next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedEntity $$_hibernate_getPreviousManagedEntity() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous) {
|
||||
this.previous = previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentAttributeInterceptor $$_hibernate_getInterceptor() {
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor) {
|
||||
this.interceptor = interceptor;
|
||||
}
|
||||
}
|
|
@ -33,6 +33,8 @@ import javax.persistence.Id;
|
|||
public class SimpleEntity {
|
||||
private Long id;
|
||||
private String name;
|
||||
private boolean active;
|
||||
private long someNumber;
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
|
@ -50,4 +52,20 @@ public class SimpleEntity {
|
|||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public long getSomeNumber() {
|
||||
return someNumber;
|
||||
}
|
||||
|
||||
public void setSomeNumber(long someNumber) {
|
||||
this.someNumber = someNumber;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,48 @@
|
|||
package org.hibernate.test.bytecode.enhancement;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class SubEntity extends SuperEntity {
|
||||
private Long id;
|
||||
private String name;
|
||||
private boolean active;
|
||||
private long someNumber;
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public long getSomeNumber() {
|
||||
return someNumber;
|
||||
}
|
||||
|
||||
public void setSomeNumber(long someNumber) {
|
||||
this.someNumber = someNumber;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue