You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(22) |
Nov
(308) |
Dec
(131) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(369) |
Feb
(171) |
Mar
(236) |
Apr
(187) |
May
(218) |
Jun
(217) |
Jul
(127) |
Aug
(448) |
Sep
(270) |
Oct
(231) |
Nov
(422) |
Dec
(255) |
2004 |
Jan
(111) |
Feb
(73) |
Mar
(338) |
Apr
(351) |
May
(349) |
Jun
(495) |
Jul
(394) |
Aug
(1048) |
Sep
(499) |
Oct
(142) |
Nov
(269) |
Dec
(638) |
2005 |
Jan
(825) |
Feb
(1272) |
Mar
(593) |
Apr
(690) |
May
(950) |
Jun
(958) |
Jul
(767) |
Aug
(839) |
Sep
(525) |
Oct
(449) |
Nov
(585) |
Dec
(455) |
2006 |
Jan
(603) |
Feb
(656) |
Mar
(195) |
Apr
(114) |
May
(136) |
Jun
(100) |
Jul
(128) |
Aug
(68) |
Sep
(7) |
Oct
(1) |
Nov
(1) |
Dec
(8) |
2007 |
Jan
(4) |
Feb
(3) |
Mar
(8) |
Apr
(16) |
May
(5) |
Jun
(4) |
Jul
(6) |
Aug
(23) |
Sep
(15) |
Oct
(5) |
Nov
(7) |
Dec
(5) |
2008 |
Jan
(5) |
Feb
(1) |
Mar
(1) |
Apr
(5) |
May
(1) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
(1) |
Jul
(1) |
Aug
(1) |
Sep
|
Oct
(2) |
Nov
(3) |
Dec
(2) |
2013 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(1) |
Jul
|
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2017 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <hib...@li...> - 2006-05-04 22:39:08
|
Author: epbernard Date: 2006-05-04 18:39:06 -0400 (Thu, 04 May 2006) New Revision: 9884 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/instrument/InterceptFieldClassFileTransformer.java Log: EJB-172 delegate transformation to the underlying Hibernate bytecode provider Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/instrument/InterceptFieldClassFileTransformer.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/instrument/InterceptFieldClassFileTransformer.java 2006-05-04 22:36:54 UTC (rev 9883) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/instrument/InterceptFieldClassFileTransformer.java 2006-05-04 22:39:06 UTC (rev 9884) @@ -1,29 +1,13 @@ //$Id$ package org.hibernate.ejb.instrument; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; -import java.util.Arrays; import java.util.List; -import net.sf.cglib.core.ClassNameReader; -import net.sf.cglib.core.DebuggingClassWriter; -import net.sf.cglib.transform.ClassReaderGenerator; -import net.sf.cglib.transform.ClassTransformer; -import net.sf.cglib.transform.TransformingClassGenerator; -import net.sf.cglib.transform.impl.InterceptFieldEnabled; -import net.sf.cglib.transform.impl.InterceptFieldFilter; -import net.sf.cglib.transform.impl.InterceptFieldTransformer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Type; -import org.objectweb.asm.attrs.Attributes; +import org.hibernate.cfg.Environment; /** * Enhance the classes allowing them to implements InterceptFieldEnabled @@ -33,92 +17,25 @@ */ public class InterceptFieldClassFileTransformer implements javax.persistence.spi.ClassTransformer { Log log = LogFactory.getLog( InterceptFieldClassFileTransformer.class.getName() ); - private List<String> entities; + private org.hibernate.bytecode.ClassTransformer classTransformer; public InterceptFieldClassFileTransformer(List<String> entities) { - this.entities = entities; + classTransformer = Environment.getBytecodeProvider().getEntityClassTransformer( + null, entities.toArray( new String[ entities.size() ] ) + ); } public byte[] transform( - ClassLoader loader, String className, Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer + ClassLoader loader, String className, Class<?> classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer ) throws IllegalClassFormatException { - ClassReader reader; try { - reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) ); + return classTransformer.transform( loader, className, classBeingRedefined, + protectionDomain, classfileBuffer ); } - catch (IOException e) { - log.error( "Unable to read class", e ); - throw new IllegalClassFormatException( "Unable to read class: " + e.getMessage() ); + catch (Exception e) { + throw new IllegalClassFormatException( e.getMessage() ); } - -// if ( className.startsWith( "net/sf/cglib") -// || className.startsWith( "org/hibernate/ejb/instrument") -// || className.startsWith( "org/hibernate/proxy") -// || className.startsWith( "org/hibernate/intercept") ) { -// return classfileBuffer; -// } - - if ( ! entities.contains( className.replace( "/", "." ) ) ) return classfileBuffer; - - String name[] = ClassNameReader.getClassInfo( reader ); - ClassWriter w = new DebuggingClassWriter( true ); - ClassTransformer t = getClassTransformer( name ); - if ( t != null ) { - if ( log.isDebugEnabled() ) { - log.info( "Enhancing " + className ); - } - ByteArrayOutputStream out; - byte[] result; - try { - reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) ); - new TransformingClassGenerator( - new ClassReaderGenerator( - reader, - attributes(), skipDebug() - ), t - ).generateClass( w ); - out = new ByteArrayOutputStream(); - out.write( w.toByteArray() ); - result = out.toByteArray(); - out.close(); - } - catch (Exception e) { - log.error( "Unable to transform class", e ); - throw new IllegalClassFormatException( "Unable to transform class: " + e.getMessage() ); - } - return result; - } - return classfileBuffer; } - - private Attribute[] attributes() { - return Attributes.getDefaultAttributes(); - } - - private boolean skipDebug() { - return false; - } - - private ClassTransformer getClassTransformer(String[] classInfo) { - - if ( Arrays.asList( classInfo ).contains( InterceptFieldEnabled.class.getName() ) ) { - return null; - } - else { - return new InterceptFieldTransformer( - new InterceptFieldFilter() { - public boolean acceptRead(Type owner, String name) { - return true; - } - - public boolean acceptWrite(Type owner, String name) { - return true; - } - } - ); - } - - } } |
Author: epbernard Date: 2006-05-04 18:36:54 -0400 (Thu, 04 May 2006) New Revision: 9883 Added: trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java Modified: trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java trunk/Hibernate3/test/org/hibernate/test/AllTests.java trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java Log: HHH-1719 add a bytecode entry for class transformation, also provide a ClassTransformer friendly ClassLoader (in the test suite), also add a JavassistInstrumentationTest Added: trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/AbstractClassTransformerImpl.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -0,0 +1,60 @@ +//$Id: $ +package org.hibernate.bytecode; + +import java.security.ProtectionDomain; +import java.util.HashSet; +import java.util.Set; + +/** + * @author Emmanuel Bernard + */ +public abstract class AbstractClassTransformerImpl implements ClassTransformer { + + final private Set<String> entities; + final private String[] packages; + + + public AbstractClassTransformerImpl(String[] packages, String[] classes) { + this.packages = packages; + if (classes == null) { + this.entities = null; + } + else { + this.entities = new HashSet<String>(); + for ( String clazz : classes ) { + entities.add( clazz ); + } + } + } + + public byte[] + transform( + ClassLoader loader, String className, Class<?> classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer + ) { + boolean enhance = false; + String safeClassName = className.replace( "/", "." ); + if ( entities == null && packages == null ) { + enhance = true; + } + if ( ! enhance && entities != null && entities.contains( safeClassName ) ) { + enhance = true; + } + if ( ! enhance && packages != null ) { + for ( String packageName : packages ) { + if ( safeClassName.startsWith( packageName ) ) { + enhance = true; + break; + } + } + } + if ( ! enhance ) return classfileBuffer; + + return doTransform( loader, className, classBeingRedefined, protectionDomain, classfileBuffer ); + } + + protected abstract byte[] doTransform( + ClassLoader loader, String className, Class<?> classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer + ); +} Modified: trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/BytecodeProvider.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -47,11 +47,30 @@ * * @param parent The parent classloader * @param classpath The classpath to be searched - * @param packages can be null; use to limnit the packages to be loaded + * @param packages can be null; use to limit the packages to be loaded * via this classloader (and transformed). * @return The appropriate ClassLoader. */ public ClassLoader generateDynamicFieldInterceptionClassLoader(ClassLoader parent, String[] classpath, String[] packages); + /** + * Generate a ClassTransformer capable of performing dynamic bytecode manipulation + * on classes as they are loaded for the purpose of field-level interception. + * The returned ClassTransformer can be combined to an appropriate ClassLoader + * is used for run-time bytecode manipulation as + * opposed to the more common build-time manipulation, since here we get + * into SecurityManager issues and such. + * <p/> + * + * @param packages can be null; use to limit the packages to be transformed + * via this classtransformer. + * @param classes can be null; use to limit the classes to be transformed + * via this class transformer. + * @return The appropriate ClassTransformer. + */ + public ClassTransformer getEntityClassTransformer( + String[] packages, String[] classes + ); + public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader); } Added: trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/ClassTransformer.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -0,0 +1,34 @@ +//$Id: $ +package org.hibernate.bytecode; + +import java.security.ProtectionDomain; + +/** + * A persistence provider provides an instance of this interface + * to the PersistenceUnitInfo.addTransformer method. + * The supplied transformer instance will get called to transform + * entity class files when they are loaded and redefined. The transformation + * occurs before the class is defined by the JVM + * + * + * @author <a href="mailto:bi...@jb...">Bill Burke</a> + * @author Emmanuel Bernard + */ +public interface ClassTransformer +{ + /** + * Invoked when a class is being loaded or redefined to add hooks for persistence bytecode manipulation + * + * @param loader the defining class loaderof the class being transformed. It may be null if using bootstrap loader + * @param classname The name of the class being transformed + * @param classBeingRedefined If an already loaded class is being redefined, then pass this as a parameter + * @param protectionDomain ProtectionDomain of the class being (re)-defined + * @param classfileBuffer The input byte buffer in class file format + * @return A well-formed class file that can be loaded + */ + byte[] transform(ClassLoader loader, + String classname, + Class<?> classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer); +} Modified: trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/cglib/BytecodeProviderImpl.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -1,24 +1,24 @@ package org.hibernate.bytecode.cglib; +import java.lang.reflect.Modifier; + +import net.sf.cglib.beans.BulkBean; +import net.sf.cglib.beans.BulkBeanException; +import net.sf.cglib.reflect.FastClass; +import net.sf.cglib.transform.ClassFilter; +import net.sf.cglib.transform.ClassTransformer; +import net.sf.cglib.transform.ClassTransformerFactory; +import net.sf.cglib.transform.TransformingClassLoader; +import net.sf.cglib.transform.impl.InterceptFieldFilter; +import net.sf.cglib.transform.impl.InterceptFieldTransformer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.hibernate.bytecode.BytecodeProvider; import org.hibernate.bytecode.ProxyFactoryFactory; import org.hibernate.bytecode.ReflectionOptimizer; import org.hibernate.util.StringHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.objectweb.asm.Type; -import net.sf.cglib.reflect.FastClass; -import net.sf.cglib.beans.BulkBean; -import net.sf.cglib.beans.BulkBeanException; -import net.sf.cglib.transform.TransformingClassLoader; -import net.sf.cglib.transform.ClassFilter; -import net.sf.cglib.transform.ClassTransformerFactory; -import net.sf.cglib.transform.ClassTransformer; -import net.sf.cglib.transform.impl.InterceptFieldTransformer; -import net.sf.cglib.transform.impl.InterceptFieldFilter; -import java.lang.reflect.Modifier; - /** * Bytecode provider implementation for CGLIB. * @@ -108,6 +108,12 @@ ); } + public org.hibernate.bytecode.ClassTransformer getEntityClassTransformer( + String[] packages, String[] classes + ) { + return new CglibClassTransformer( packages, classes ); + } + public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader) { } Added: trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/cglib/CglibClassTransformer.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -0,0 +1,115 @@ +//$Id: $ +package org.hibernate.bytecode.cglib; + +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ByteArrayOutputStream; + +import net.sf.cglib.transform.ClassTransformer; +import net.sf.cglib.transform.TransformingClassGenerator; +import net.sf.cglib.transform.ClassReaderGenerator; +import net.sf.cglib.transform.impl.InterceptFieldEnabled; +import net.sf.cglib.transform.impl.InterceptFieldFilter; +import net.sf.cglib.transform.impl.InterceptFieldTransformer; +import net.sf.cglib.core.ClassNameReader; +import net.sf.cglib.core.DebuggingClassWriter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hibernate.bytecode.AbstractClassTransformerImpl; +import org.hibernate.HibernateException; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.attrs.Attributes; + +/** + * Enhance the classes allowing them to implements InterceptFieldEnabled + * This interface is then used by Hibernate for some optimizations. + * + * @author Emmanuel Bernard + */ +public class CglibClassTransformer extends AbstractClassTransformerImpl { + + private static Log log = LogFactory.getLog( CglibClassTransformer.class.getName() ); + + public CglibClassTransformer(String[] packages, String[] classes) { + super(packages, classes); + } + + protected byte[] doTransform( + ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, + byte[] classfileBuffer + ) { + ClassReader reader; + try { + reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) ); + } + catch (IOException e) { + log.error( "Unable to read class", e ); + throw new HibernateException( "Unable to read class: " + e.getMessage() ); + } + + String name[] = ClassNameReader.getClassInfo( reader ); + ClassWriter w = new DebuggingClassWriter( true ); + ClassTransformer t = getClassTransformer( name ); + if ( t != null ) { + if ( log.isDebugEnabled() ) { + log.debug( "Enhancing " + className ); + } + ByteArrayOutputStream out; + byte[] result; + try { + reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) ); + new TransformingClassGenerator( + new ClassReaderGenerator( + reader, + attributes(), skipDebug() + ), t + ).generateClass( w ); + out = new ByteArrayOutputStream(); + out.write( w.toByteArray() ); + result = out.toByteArray(); + out.close(); + } + catch (Exception e) { + log.error( "Unable to transform class", e ); + throw new HibernateException( "Unable to transform class: " + e.getMessage() ); + } + return result; + } + return classfileBuffer; + } + + + private Attribute[] attributes() { + return Attributes.getDefaultAttributes(); + } + + private boolean skipDebug() { + return false; + } + + private ClassTransformer getClassTransformer(String[] classInfo) { + + if ( Arrays.asList( classInfo ).contains( InterceptFieldEnabled.class.getName() ) ) { + return null; + } + else { + return new InterceptFieldTransformer( + new InterceptFieldFilter() { + public boolean acceptRead(Type owner, String name) { + return true; + } + + public boolean acceptWrite(Type owner, String name) { + return true; + } + } + ); + } + + } +} Modified: trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/javassist/BytecodeProviderImpl.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -1,14 +1,15 @@ package org.hibernate.bytecode.javassist; +import java.lang.reflect.Modifier; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.hibernate.bytecode.BytecodeProvider; +import org.hibernate.bytecode.ClassTransformer; import org.hibernate.bytecode.ProxyFactoryFactory; import org.hibernate.bytecode.ReflectionOptimizer; import org.hibernate.util.StringHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import java.lang.reflect.Modifier; - /** * Bytecode provider implementation for Javassist. * @@ -78,6 +79,12 @@ return new TransformingClassLoader( parent, classpath ); } + public ClassTransformer getEntityClassTransformer( + String[] packages, String[] classes + ) { + return new JavassistClassTransformer( packages, classes ); + } + public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader) { if ( ! TransformingClassLoader.class.isAssignableFrom( classLoader.getClass() ) ) { return; Added: trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/src/org/hibernate/bytecode/javassist/JavassistClassTransformer.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -0,0 +1,104 @@ +//$Id: $ +package org.hibernate.bytecode.javassist; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.security.ProtectionDomain; + +import javassist.bytecode.ClassFile; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hibernate.HibernateException; +import org.hibernate.bytecode.AbstractClassTransformerImpl; +import org.hibernate.tool.instrument.javassist.FieldFilter; +import org.hibernate.tool.instrument.javassist.FieldHandled; +import org.hibernate.tool.instrument.javassist.FieldTransformer; + +/** + * Enhance the classes allowing them to implements InterceptFieldEnabled + * This interface is then used by Hibernate for some optimizations. + * + * @author Emmanuel Bernard + */ +public class JavassistClassTransformer extends AbstractClassTransformerImpl { + + private static Log log = LogFactory.getLog( JavassistClassTransformer.class.getName() ); + + public JavassistClassTransformer(String[] packages, String[] classes) { + super(packages, classes); + } + + protected byte[] doTransform( + ClassLoader loader, String className, Class<?> classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer + ) { + ClassFile classfile = null; + try { + // WARNING: classfile only + classfile = new ClassFile( new DataInputStream( new ByteArrayInputStream( classfileBuffer ) ) ); + } + catch (IOException e) { + log.error( "Unable to build enhancement metamodel for " + className ); + return classfileBuffer; + } + FieldTransformer transformer = getFieldTransformer( classfile ); + if ( transformer != null ) { + if ( log.isDebugEnabled() ) { + log.debug( "Enhancing " + className ); + } + DataOutputStream out = null; + try { + transformer.transform( classfile ); + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + out = new DataOutputStream( byteStream ); + classfile.write( out ); + return byteStream.toByteArray(); + } + catch (Exception e) { + log.error( "Unable to transform class", e ); + throw new HibernateException( "Unable to transform class: " + e.getMessage() ); + } + finally { + try { + if ( out != null ) out.close(); + } + catch (IOException e) { + //swallow + } + } + } + return classfileBuffer; + } + + protected FieldTransformer getFieldTransformer(ClassFile classfile) { + if ( alreadyInstrumented( classfile ) ) { + return null; + } + else { + return new FieldTransformer( + new FieldFilter() { + public boolean handleRead(String desc, String name) { + return true; + } + + public boolean handleWrite(String desc, String name) { + return true; + } + } + ); + } + } + + private boolean alreadyInstrumented(ClassFile classfile) { + String[] intfs = classfile.getInterfaces(); + for ( int i = 0; i < intfs.length; i++ ) { + if ( FieldHandled.class.getName().equals( intfs[i] ) ) { + return true; + } + } + return false; + } +} Modified: trunk/Hibernate3/test/org/hibernate/test/AllTests.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/AllTests.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/test/org/hibernate/test/AllTests.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -47,6 +47,7 @@ import org.hibernate.test.immutable.ImmutableTest; import org.hibernate.test.instrument.buildtime.InstrumentTest; import org.hibernate.test.instrument.runtime.CGLIBInstrumentationTest; +import org.hibernate.test.instrument.runtime.JavassistInstrumentationTest; import org.hibernate.test.interceptor.InterceptorTest; import org.hibernate.test.interfaceproxy.InterfaceProxyTest; import org.hibernate.test.iterate.IterateTest; @@ -282,6 +283,7 @@ suite.addTest( InstrumentCacheTest2.suite() ); } suite.addTest( CGLIBInstrumentationTest.suite() ); + suite.addTest( JavassistInstrumentationTest.suite() ); suite.addTest( SybaseTimestampVersioningTest.suite() ); suite.addTest( DbVersionTest.suite() ); suite.addTest( TimestampGeneratedValuesWithCachingTest.suite() ); Modified: trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -1,7 +1,6 @@ package org.hibernate.test.instrument.runtime; import java.lang.reflect.InvocationTargetException; -import java.net.URL; import org.hibernate.HibernateException; import org.hibernate.bytecode.BytecodeProvider; @@ -15,16 +14,17 @@ private BytecodeProvider provider; protected ClassLoader buildIsolatedClassLoader(ClassLoader parent) { - String myFileName = AbstractTransformingClassLoaderInstrumentTestCase.class.getName().replace( '.', '/' ) + ".class"; - URL fileURL = this.getClass().getClassLoader().getResource( myFileName ); - String filePath = fileURL.getPath(); - String classPath = filePath.substring( 0, filePath.length() - myFileName.length() ); +// String myFileName = AbstractTransformingClassLoaderInstrumentTestCase.class.getName().replace( '.', '/' ) + ".class"; +// URL fileURL = this.getClass().getClassLoader().getResource( myFileName ); +// String filePath = fileURL.getPath(); +// String classPath = filePath.substring( 0, filePath.length() - myFileName.length() ); provider = buildBytecodeProvider(); - return provider.generateDynamicFieldInterceptionClassLoader( + return new InstrumentedClassLoader( parent, - new String[] { classPath }, - new String[] { "org.hibernate.test.instrument" } - ); + provider.getEntityClassTransformer( + new String[] { "org.hibernate.test.instrument" }, + null) ); + } protected void releaseIsolatedClassLoader(ClassLoader isolatedLoader) { Added: trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/InstrumentedClassLoader.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -0,0 +1,81 @@ +//$Id: $ +package org.hibernate.test.instrument.runtime; + +import java.io.IOException; +import java.io.InputStream; + +import org.hibernate.HibernateException; +import org.hibernate.bytecode.ClassTransformer; + +/** + * @author Emmanuel Bernard + */ +public class InstrumentedClassLoader extends ClassLoader { + + private ClassTransformer classTransformer; + + public InstrumentedClassLoader(ClassLoader parent, ClassTransformer classTransformer) { + super( parent ); + this.classTransformer = classTransformer; + } + + @Override + public Class<?> loadClass(String name) throws ClassNotFoundException { + if ( name.startsWith( "java" ) ) return getParent().loadClass( name ); + Class c = findLoadedClass( name ); + if ( c != null ) return c; + InputStream is = this.getResourceAsStream( name.replace( ".", "/" ) + ".class" ); + if ( is == null ) throw new ClassNotFoundException( name ); + byte[] buffer = new byte[409600]; + byte[] originalClass = new byte[0]; + int r = 0; + try { + r = is.read( buffer ); + } + catch (IOException e) { + throw new ClassNotFoundException( name + " not found", e ); + } + while ( r >= buffer.length ) { + byte[] temp = new byte[ originalClass.length + buffer.length ]; + System.arraycopy( originalClass, 0, temp, 0, originalClass.length ); + System.arraycopy( buffer, 0, temp, originalClass.length, buffer.length ); + originalClass = temp; + } + if ( r != -1 ) { + byte[] temp = new byte[ originalClass.length + r ]; + System.arraycopy( originalClass, 0, temp, 0, originalClass.length ); + System.arraycopy( buffer, 0, temp, originalClass.length, r ); + originalClass = temp; + } + try { + is.close(); + } + catch (IOException e) { + throw new ClassNotFoundException( name + " not found", e ); + } + if (classTransformer != null) { + byte[] transformed = new byte[0]; + try { + transformed = classTransformer.transform( + getParent(), + name, + null, + null, + originalClass + ); + if ( originalClass == transformed) { + return getParent().loadClass(name); + } + else { + return defineClass( name, transformed, 0, transformed.length ); + } + } + catch (HibernateException e) { + throw new ClassNotFoundException( name + " not found", e ); + } + } + else { + return getParent().loadClass(name); + } + } +} Added: trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2006-05-04 20:46:47 UTC (rev 9882) +++ trunk/Hibernate3/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2006-05-04 22:36:54 UTC (rev 9883) @@ -0,0 +1,20 @@ +//$Id: $ +package org.hibernate.test.instrument.runtime; + +import org.hibernate.bytecode.BytecodeProvider; +import org.hibernate.bytecode.javassist.BytecodeProviderImpl; +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * @author Steve Ebersole + */ +public class JavassistInstrumentationTest extends AbstractTransformingClassLoaderInstrumentTestCase { + protected BytecodeProvider buildBytecodeProvider() { + return new BytecodeProviderImpl(); + } + + public static Test suite() { + return new TestSuite( JavassistInstrumentationTest.class ); + } +} |
From: <hib...@li...> - 2006-05-04 20:46:49
|
Author: epbernard Date: 2006-05-04 16:46:47 -0400 (Thu, 04 May 2006) New Revision: 9882 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employee.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employer.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java Log: ANN-339 use colelction.setManyToManyOrderBy Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-05-04 19:41:49 UTC (rev 9881) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-05-04 20:46:47 UTC (rev 9882) @@ -803,9 +803,15 @@ } } } - if ( ! isCollectionOfEntities && StringHelper.isNotEmpty( hqlOrderBy ) ) { - //@ManyToMany can't handle order by on the target table - collValue.setOrderBy( hqlOrderBy ); + if ( StringHelper.isNotEmpty( hqlOrderBy ) ) { + if ( ! isCollectionOfEntities ) { + collValue.setOrderBy( hqlOrderBy ); + } + else { + collValue.setManyToManyOrdering( + buildOrderByClauseFromHql( hqlOrderBy, collectionEntity, collValue.getRole() ) + ); + } } boolean mappedBy = ! AnnotationBinder.isDefault( joinColumns[0].getMappedBy() ); if ( mappedBy ) { Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employee.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employee.java 2006-05-04 19:41:49 UTC (rev 9881) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employee.java 2006-05-04 20:46:47 UTC (rev 9882) @@ -8,6 +8,7 @@ import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; +import javax.persistence.Column; import org.hibernate.annotations.Cascade; @@ -20,7 +21,17 @@ public class Employee implements Serializable { private Integer id; private Collection<Employer> employers; + private String name; + @Column(name="fld_name") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + @Id @GeneratedValue public Integer getId() { Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employer.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employer.java 2006-05-04 19:41:49 UTC (rev 9881) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/Employer.java 2006-05-04 20:46:47 UTC (rev 9882) @@ -10,6 +10,7 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; +import javax.persistence.OrderBy; import org.hibernate.annotations.Cascade; @@ -33,6 +34,7 @@ inverseJoinColumns = {@JoinColumn(name = "EMPEE_ID")} ) @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE) + @OrderBy("name") public Collection getEmployees() { return employees; } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java 2006-05-04 19:41:49 UTC (rev 9881) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java 2006-05-04 20:46:47 UTC (rev 9882) @@ -218,6 +218,44 @@ s.close(); } + public void testOrderBy() throws Exception { + Session s; + Transaction tx; + s = openSession(); + tx = s.beginTransaction(); + Employer er = new Employer(); + Employee ee = new Employee(); + ee.setName( "Emmanuel" ); + Employee ee2 = new Employee(); + ee2.setName( "Alice" ); + s.persist( ee ); + s.persist( ee2 ); + Set erColl = new HashSet(); + Collection eeColl = new ArrayList(); + Collection eeColl2 = new ArrayList(); + erColl.add( ee ); + erColl.add( ee2 ); + eeColl.add( er ); + eeColl2.add( er ); + er.setEmployees( erColl ); + ee.setEmployers( eeColl ); + ee2.setEmployers( eeColl2 ); + //s.persist(ee); + + s.flush(); + s.clear(); + + er = (Employer) s.get( Employer.class, er.getId() ); + assertNotNull( er ); + assertNotNull( er.getEmployees() ); + assertEquals( 2, er.getEmployees().size() ); + Employee eeFromDb = (Employee) er.getEmployees().iterator().next(); + assertEquals( ee2.getName(), eeFromDb.getName() ); + tx.rollback(); + s.close(); + + } + public void testRemoveInBetween() throws Exception { Session s; Transaction tx; |
From: <hib...@li...> - 2006-05-04 19:41:52
|
Author: epbernard Date: 2006-05-04 15:41:49 -0400 (Thu, 04 May 2006) New Revision: 9881 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java Log: EJB-173 protect session.getTransaction() from session close Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2006-05-04 19:17:48 UTC (rev 9880) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2006-05-04 19:41:49 UTC (rev 9881) @@ -493,8 +493,11 @@ session.clear(); } } - JoinableCMTTransaction joinable = (JoinableCMTTransaction) session.getTransaction(); - joinable.resetStatus(); + if ( session.isOpen() ) { + //only reset if the session is opened since you can't get the Transaction otherwise + JoinableCMTTransaction joinable = (JoinableCMTTransaction) session.getTransaction(); + joinable.resetStatus(); + } } catch (HibernateException e) { throwPersistenceException( e ); Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java 2006-05-04 19:17:48 UTC (rev 9880) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java 2006-05-04 19:41:49 UTC (rev 9881) @@ -10,6 +10,7 @@ import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.cfg.Environment; import org.hibernate.engine.SessionImplementor; /** @@ -64,8 +65,15 @@ public void afterCompletion(int i) { //TODO should I check for isOpen() ? if ( session != null ) { - log.debug( "Closing session after transaction completion" ); - session.close(); + if ( session.isOpen() ) { + log.debug( "Closing entity manager after transaction completion" ); + session.close(); + } + else { + log.warn( "Entity Manager closed by someone else (" + + Environment.AUTO_CLOSE_SESSION + + " must not be used)"); + } } //TODO session == null should not happen } |
From: <hib...@li...> - 2006-05-04 19:17:52
|
Author: epbernard Date: 2006-05-04 15:17:48 -0400 (Thu, 04 May 2006) New Revision: 9880 Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/QueryTest.java Log: EJB-59 Test for aggregation return type Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/QueryTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/QueryTest.java 2006-05-04 19:07:57 UTC (rev 9879) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/QueryTest.java 2006-05-04 19:17:48 UTC (rev 9880) @@ -35,6 +35,20 @@ em.close(); } + public void testAggregationReturnType() throws Exception { + EntityManager em = factory.createEntityManager(); + em.getTransaction().begin(); + Item item = new Item( "Mouse", "Micro$oft mouse" ); + em.persist( item ); + item = new Item( "Computer", "Apple II" ); + em.persist( item ); + Query q = em.createQuery( "select count(i) from Item i where i.name like :itemName" ); + q.setParameter( "itemName", "%" ); + assertTrue( q.getSingleResult() instanceof Long); + em.getTransaction().rollback(); + em.close(); + } + public void testParameterList() throws Exception { final Item item = new Item( "Mouse", "Micro$oft mouse" ); final Item item2 = new Item( "Computer", "Dll computer" ); |
Author: max...@jb... Date: 2006-05-04 15:07:57 -0400 (Thu, 04 May 2006) New Revision: 9879 Modified: trunk/Hibernate3/src/org/hibernate/hql/classic/SelectParser.java trunk/Hibernate3/test/org/hibernate/test/extralazy/ExtraLazyTest.java trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java trunk/Hibernate3/test/org/hibernate/test/joinfetch/JoinFetchTest.java trunk/Hibernate3/test/org/hibernate/test/legacy/FooBarTest.java trunk/Hibernate3/test/org/hibernate/test/legacy/Result.java trunk/Hibernate3/test/org/hibernate/test/legacy/SQLFunctionsTest.java trunk/Hibernate3/test/org/hibernate/test/map/MapIndexFormulaTest.java Log: HHH-1538 fixes to the testsuite + fix stupid hardcoded logic in old query translator for count(*) Added HQLTest.testAggregationReturnType to test for the above statements. Consequence: COUNT changed from Hibernate.INTEGER to Hibernate.LONG MAX/MIN no changes AVG changed from being dependent on the field to only return Hibernate.DOUBLE SUM changed from always just return the type of the field to return according to the above rules. Stuff that falls besides these rules simply just return the underlying field/column type. e..g SUM(timestamp) will return timestamp; but will/should fail on the db Modified: trunk/Hibernate3/src/org/hibernate/hql/classic/SelectParser.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/hql/classic/SelectParser.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/src/org/hibernate/hql/classic/SelectParser.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -121,7 +121,7 @@ else if ( COUNT_MODIFIERS.contains( lctoken ) ) { if ( !ready || !aggregate ) throw new QueryException( token + " only allowed inside aggregate function in SELECT" ); q.appendScalarSelectToken( token ); - if ( "*".equals( token ) ) q.addSelectScalar( Hibernate.INTEGER ); //special case + if ( "*".equals( token ) ) q.addSelectScalar( Hibernate.LONG ); //special case } else if ( getFunction( lctoken, q ) != null && token.equals( q.unalias( token ) ) ) { // the name of an SQL function Modified: trunk/Hibernate3/test/org/hibernate/test/extralazy/ExtraLazyTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/extralazy/ExtraLazyTest.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/extralazy/ExtraLazyTest.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -167,7 +167,7 @@ assertEquals(smap.size(), 1); gavin = (User) g.getUsers().put("gavin", turin); s.delete(gavin); - assertEquals( s.createQuery("select count(*) from SessionAttribute").uniqueResult(), new Integer(0) ); + assertEquals( s.createQuery("select count(*) from SessionAttribute").uniqueResult(), new Long(0) ); t.commit(); s.close(); @@ -178,10 +178,10 @@ turin = (User) g.getUsers().get("turin"); smap = turin.getSession(); assertEquals(smap.size(), 0); - assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Integer(1) ); + assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Long(1) ); s.delete(g); s.delete(turin); - assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Integer(0) ); + assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Long(0) ); t.commit(); s.close(); } Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -648,7 +648,7 @@ h.setName( new Name("Gavin", 'A', "King") ); h.setNickName("Oney"); s.persist(h); - Float sum = (Float) s.createQuery("select sum(h.bodyWeight) from Human h").uniqueResult(); + Double sum = (Double) s.createQuery("select sum(h.bodyWeight) from Human h").uniqueResult(); Double avg = (Double) s.createQuery("select avg(h.height) from Human h").uniqueResult(); assertEquals(sum.floatValue(), 74.0, 0.01); assertEquals(avg.doubleValue(), 120.5, 0.01); Modified: trunk/Hibernate3/test/org/hibernate/test/joinfetch/JoinFetchTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/joinfetch/JoinFetchTest.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/joinfetch/JoinFetchTest.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -194,8 +194,8 @@ .uniqueResult(); assertFalse( Hibernate.isInitialized( hb.getUsers() ) ); //gavin = (User) s.createFilter( hb.getUsers(), "where index(this) = 'gavin'" ).uniqueResult(); - Integer size = (Integer) s.createFilter( hb.getUsers(), "select count(*)" ).uniqueResult(); - assertEquals( new Integer(2), size ); + Long size = (Long) s.createFilter( hb.getUsers(), "select count(*)" ).uniqueResult(); + assertEquals( new Long(2), size ); assertFalse( Hibernate.isInitialized( hb.getUsers() ) ); s.delete(hb); t.commit(); Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/FooBarTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/legacy/FooBarTest.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/legacy/FooBarTest.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -516,19 +516,19 @@ assertTrue( "query many-to-one", list.size()==1 ); Iterator rs = s.iterate("select count(distinct foo.foo) from Foo foo"); - assertTrue( "count", ( (Integer) rs.next() ).intValue()==2 ); + assertTrue( "count", ( (Long) rs.next() ).longValue()==2 ); assertTrue( !rs.hasNext() ); rs = s.iterate("select count(foo.foo.boolean) from Foo foo"); - assertTrue( "count", ( (Integer) rs.next() ).intValue()==2 ); + assertTrue( "count", ( (Long) rs.next() ).longValue()==2 ); assertTrue( !rs.hasNext() ); rs = s.iterate("select count(*), foo.int from Foo foo group by foo.int"); - assertTrue( "count(*) group by", ( (Object[]) rs.next() )[0].equals( new Integer(3) ) ); + assertTrue( "count(*) group by", ( (Object[]) rs.next() )[0].equals( new Long(3) ) ); assertTrue( !rs.hasNext() ); rs = s.iterate("select sum(foo.foo.int) from Foo foo"); - assertTrue( "sum", ( (Integer) rs.next() ).intValue()==4 ); + assertTrue( "sum", ( (Long) rs.next() ).longValue()==4 ); assertTrue( !rs.hasNext() ); rs = s.iterate("select count(foo) from Foo foo where foo.id=?", foo.getKey(), Hibernate.STRING); - assertTrue( "id query count", ( (Integer) rs.next() ).intValue()==1 ); + assertTrue( "id query count", ( (Long) rs.next() ).longValue()==1 ); assertTrue( !rs.hasNext() ); list = s.find( "from Foo foo where foo.boolean = ?", new Boolean(true), Hibernate.BOOLEAN ); @@ -573,9 +573,9 @@ while ( rs.hasNext() ) { count++; Object[] row = (Object[]) rs.next(); - assertTrue( row[0] instanceof Float ); + assertTrue( row[0] instanceof Double ); assertTrue( row[1] instanceof String ); - assertTrue( row[2] instanceof Integer ); + assertTrue( row[2] instanceof Long ); } assertTrue(count!=0); list = s.find("select foo.long, foo.component, foo, foo.foo from Foo foo"); @@ -2238,8 +2238,8 @@ public void testPersistCollections() throws Exception { Session s = openSession(); Transaction txn = s.beginTransaction(); - assertTrue( ( (Integer) s.iterate("select count(*) from Bar").next() ).intValue()==0 ); - assertTrue( s.iterate("select count(*) from Bar b").next().equals( new Integer(0) ) ); + assertTrue( ( (Long) s.iterate("select count(*) from Bar").next() ).longValue()==0 ); + assertTrue( s.iterate("select count(*) from Bar b").next().equals( new Long(0) ) ); assertFalse( s.iterate("from Glarch g").hasNext() ); Baz baz = new Baz(); @@ -2259,7 +2259,7 @@ s = openSession(); txn = s.beginTransaction(); - assertTrue( ( (Integer) s.iterate("select count(*) from Bar").next() ).intValue()==1 ); + assertTrue( ( (Long) s.iterate("select count(*) from Bar").next() ).longValue()==1 ); baz = (Baz) ( (Object[]) s.find("select baz, baz from Baz baz").get(0) )[1]; assertTrue( baz.getCascadingBars().size()==1 ); //System.out.println( s.print(baz) ); @@ -2296,7 +2296,7 @@ s = openSession(); txn = s.beginTransaction(); - assertTrue( ( (Integer) s.iterate("select count(*) from Bar").next() ).intValue()==1 ); + assertTrue( ( (Long) s.iterate("select count(*) from Bar").next() ).longValue()==1 ); baz = (Baz) s.find("select baz from Baz baz order by baz").get(0); assertTrue( "collection of custom types - added element", baz.getCustoms().size()==4 && baz.getCustoms().get(0)!=null ); assertTrue ( "component of component in collection", baz.getComponents()[1].getSubcomponent()!=null ); @@ -2328,7 +2328,7 @@ s = openSession(); txn = s.beginTransaction(); - assertTrue( ( (Integer) s.iterate("select count(*) from Bar").next() ).intValue()==1 ); + assertTrue( ( (Long) s.iterate("select count(*) from Bar").next() ).longValue()==1 ); baz = (Baz) s.load(Baz.class, baz.getCode()); assertTrue( baz.getCascadingBars().size()==1 ); Bar bar = new Bar(); @@ -2363,7 +2363,7 @@ Session s2 = openSession(); Transaction txn2 = s2.beginTransaction(); - assertTrue( ( (Integer) s2.iterate("select count(*) from Bar").next() ).intValue()==3 ); + assertTrue( ( (Long) s2.iterate("select count(*) from Bar").next() ).longValue()==3 ); Baz baz2 = (Baz) s2.find("select baz from Baz baz order by baz").get(0); Object o = baz2.getFooComponentToFoo().get( new FooComponent("name", 123, null, null) ); assertTrue( @@ -2407,7 +2407,7 @@ s = openSession(); txn = s.beginTransaction(); - assertTrue( ( (Integer) s.iterate("select count(*) from Bar").next() ).intValue()==3 ); + assertTrue( ( (Long) s.iterate("select count(*) from Bar").next() ).longValue()==3 ); baz = (Baz) s.find("select baz from Baz baz order by baz").get(0); assertTrue( baz.getTopGlarchez().size()==2 ); assertTrue( baz.getCascadingBars().size()==1 ); @@ -2421,7 +2421,7 @@ s2.reconnect(); txn2 = s2.beginTransaction(); baz = (Baz) s2.load(Baz.class, baz.getCode()); - assertTrue( ( (Integer) s2.iterate("select count(*) from Bar").next() ).intValue()==3 ); + assertTrue( ( (Long) s2.iterate("select count(*) from Bar").next() ).longValue()==3 ); s2.delete(baz); s2.delete( baz.getTopGlarchez().get( new Character('G') ) ); s2.delete( baz.getTopGlarchez().get( new Character('H') ) ); @@ -3344,8 +3344,8 @@ Iterator rs = s.iterate("select count(distinct child.id), count(distinct parent.id) from Foo parent, Foo child where parent.foo = child"); Object[] row = (Object[]) rs.next(); - assertTrue( "multi-column count", ( (Integer) row[0] ).intValue()==1 ); - assertTrue( "multi-column count", ( (Integer) row[1] ).intValue()==1 ); + assertTrue( "multi-column count", ( (Long) row[0] ).intValue()==1 ); + assertTrue( "multi-column count", ( (Long) row[1] ).intValue()==1 ); assertTrue( !rs.hasNext() ); rs = s.iterate("select child.id, parent.id, child.long from Foo parent, Foo child where parent.foo = child"); Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/Result.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/legacy/Result.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/legacy/Result.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -4,7 +4,7 @@ public class Result { private String name; private long amount; - private int count; + private long count; /** * Returns the amount. * @return long @@ -17,7 +17,7 @@ * Returns the count. * @return int */ - public int getCount() { + public long getCount() { return count; } @@ -41,7 +41,7 @@ * Sets the count. * @param count The count to set */ - public void setCount(int count) { + public void setCount(long count) { this.count = count; } @@ -58,4 +58,10 @@ amount = a; count = c; } + + public Result(String n, long a, long c) { + name = n; + amount = a; + count = c; + } } Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/SQLFunctionsTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/legacy/SQLFunctionsTest.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/legacy/SQLFunctionsTest.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -379,7 +379,7 @@ Iterator iter = s.iterate("select sum(s.count) from Simple s group by s.count having sum(s.count) > 10"); assertTrue( iter.hasNext() ); - assertTrue( new Integer(12).equals( iter.next() ) ); + assertEquals( new Long(12), iter.next() ); assertTrue( !iter.hasNext() ); if ( ! (getDialect() instanceof MySQLDialect) ) { iter = s.iterate("select s.count from Simple s group by s.count having s.count = 12"); Modified: trunk/Hibernate3/test/org/hibernate/test/map/MapIndexFormulaTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/map/MapIndexFormulaTest.java 2006-05-04 18:50:40 UTC (rev 9878) +++ trunk/Hibernate3/test/org/hibernate/test/map/MapIndexFormulaTest.java 2006-05-04 19:07:57 UTC (rev 9879) @@ -53,7 +53,7 @@ assertEquals(smap.size(), 1); gavin = (User) g.getUsers().put("gavin", turin); s.delete(gavin); - assertEquals( s.createQuery("select count(*) from SessionAttribute").uniqueResult(), new Integer(0) ); + assertEquals( s.createQuery("select count(*) from SessionAttribute").uniqueResult(), new Long(0) ); t.commit(); s.close(); @@ -64,10 +64,10 @@ turin = (User) g.getUsers().get("turin"); smap = turin.getSession(); assertEquals(smap.size(), 0); - assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Integer(1) ); + assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Long(1) ); s.delete(g); s.delete(turin); - assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Integer(0) ); + assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Long(0) ); t.commit(); s.close(); } |
From: <hib...@li...> - 2006-05-04 18:50:42
|
Author: epbernard Date: 2006-05-04 14:50:40 -0400 (Thu, 04 May 2006) New Revision: 9878 Modified: trunk/HibernateExt/ejb/src/test-resources/cfgxmlpar/org/hibernate/ejb/test/pack/cfgxmlpar/hibernate.cfg.xml trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java Log: EJB-116 add test to check that sf overrides default event listeners but let the persistence.xml have priority Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java 2006-05-04 18:04:44 UTC (rev 9877) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java 2006-05-04 18:50:40 UTC (rev 9878) @@ -10,17 +10,19 @@ import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.ejb.test.pack.cfgxmlpar.Morito; import org.hibernate.ejb.test.pack.defaultpar.ApplicationServer; +import org.hibernate.ejb.test.pack.defaultpar.IncrementListener; import org.hibernate.ejb.test.pack.defaultpar.Lighter; +import org.hibernate.ejb.test.pack.defaultpar.Money; import org.hibernate.ejb.test.pack.defaultpar.Mouse; +import org.hibernate.ejb.test.pack.defaultpar.OtherIncrementListener; import org.hibernate.ejb.test.pack.defaultpar.Version; -import org.hibernate.ejb.test.pack.defaultpar.IncrementListener; -import org.hibernate.ejb.test.pack.defaultpar.OtherIncrementListener; -import org.hibernate.ejb.test.pack.defaultpar.Money; import org.hibernate.ejb.test.pack.excludehbmpar.Caipirinha; import org.hibernate.ejb.test.pack.explodedpar.Carpet; import org.hibernate.ejb.test.pack.explodedpar.Elephant; import org.hibernate.ejb.test.pack.externaljar.Scooter; import org.hibernate.stat.Statistics; +import org.hibernate.validator.InvalidStateException; +import org.hibernate.JDBCException; //$Id$ @@ -172,6 +174,30 @@ emf.close(); } + public void testListenersOverridingCfgXmlPar() throws Exception { + EntityManagerFactory emf = Persistence.createEntityManagerFactory( "cfgxmlpar", new HashMap() ); + EntityManager em = emf.createEntityManager(); + Cat cat = new Cat(); + cat.setName( "123"); //validator catch that + em.getTransaction().begin(); + try { + em.persist( cat ); + em.flush(); + } + catch (InvalidStateException e) { + fail("Shouldn't call the ValidatorEvent listener"); + } + catch (PersistenceException e) { + if ( ! (e.getCause() instanceof JDBCException ) ) { + fail("Unexpected exception: " + e); + } + } + em.getTransaction().rollback(); + + em.close(); + emf.close(); + } + //EM TRANSACTION // public void testEntityManager() { // Modified: trunk/HibernateExt/ejb/src/test-resources/cfgxmlpar/org/hibernate/ejb/test/pack/cfgxmlpar/hibernate.cfg.xml =================================================================== --- trunk/HibernateExt/ejb/src/test-resources/cfgxmlpar/org/hibernate/ejb/test/pack/cfgxmlpar/hibernate.cfg.xml 2006-05-04 18:04:44 UTC (rev 9877) +++ trunk/HibernateExt/ejb/src/test-resources/cfgxmlpar/org/hibernate/ejb/test/pack/cfgxmlpar/hibernate.cfg.xml 2006-05-04 18:50:40 UTC (rev 9878) @@ -22,5 +22,6 @@ <mapping class="org.hibernate.ejb.test.Distributor"/> <class-cache class="org.hibernate.ejb.test.Item" usage="read-write"/> <collection-cache collection="org.hibernate.ejb.test.Item.distributors" usage="read-write" region="RegionName"/> + <event type="pre-insert"/> </session-factory> </hibernate-configuration> \ No newline at end of file |
From: <hib...@li...> - 2006-05-04 18:07:00
|
Author: epbernard Date: 2006-05-04 14:04:44 -0400 (Thu, 04 May 2006) New Revision: 9877 Modified: trunk/Hibernate3/src/org/hibernate/cfg/Configuration.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/connection/PersistenceUnitInfoImpl.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java Log: EJB-84 Modified: trunk/Hibernate3/src/org/hibernate/cfg/Configuration.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/Configuration.java 2006-05-04 16:41:12 UTC (rev 9876) +++ trunk/Hibernate3/src/org/hibernate/cfg/Configuration.java 2006-05-04 18:04:44 UTC (rev 9877) @@ -139,7 +139,7 @@ private EntityResolver entityResolver; private EntityNotFoundDelegate entityNotFoundDelegate; - private transient XMLHelper xmlHelper; + protected transient XMLHelper xmlHelper; protected transient Map typeDefs; protected NamingStrategy namingStrategy; Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-04 16:41:12 UTC (rev 9876) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-04 18:04:44 UTC (rev 9877) @@ -1,6 +1,7 @@ //$Id$ package org.hibernate.ejb; +import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.File; import java.io.IOException; @@ -21,9 +22,9 @@ import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityNotFoundException; import javax.persistence.MappedSuperclass; import javax.persistence.PersistenceException; -import javax.persistence.EntityNotFoundException; import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; @@ -32,12 +33,15 @@ import javassist.bytecode.ClassFile; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.MappingException; +import org.hibernate.ObjectNotFoundException; import org.hibernate.SessionFactory; -import org.hibernate.ObjectNotFoundException; -import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.reflection.java.xml.XMLContext; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; @@ -56,13 +60,16 @@ import org.hibernate.event.EventListeners; import org.hibernate.mapping.AuxiliaryDatabaseObject; import org.hibernate.mapping.PersistentClass; +import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.secure.JACCConfiguration; import org.hibernate.transaction.JDBCTransactionFactory; import org.hibernate.util.CollectionHelper; import org.hibernate.util.ReflectHelper; import org.hibernate.util.StringHelper; +import org.hibernate.util.XMLHelper; import org.jboss.util.file.ArchiveBrowser; import org.xml.sax.EntityResolver; +import org.xml.sax.SAXException; /** * @author Emmanuel Bernard @@ -305,6 +312,9 @@ new Properties(); ConfigurationHelper.overrideProperties( properties, integration ); + //fill up entities with the on found in xml files + addXMLEntities( xmlFiles, info, entities ); + //FIXME send the appropriate entites. if ( "true".equalsIgnoreCase( properties.getProperty( HibernatePersistence.USE_CLASS_ENHANCER ) ) ) { info.addTransformer( new InterceptFieldClassFileTransformer( entities ) ); @@ -348,6 +358,78 @@ return entityManagerFactory; } + private void addXMLEntities(List<String> xmlFiles, PersistenceUnitInfo info, List<String> entities) { + //TODO handle inputstream related hbm files + ClassLoader newTempClassLoader = info.getNewTempClassLoader(); + if (newTempClassLoader == null) { + log.warn( "Persistence provider caller does not implements the EJB3 spec correctly. PersistenceUnitInfo.getNewTempClassLoader() is null." ); + return; + } + XMLHelper xmlHelper = new XMLHelper(); + List errors = new ArrayList(); + SAXReader saxReader = xmlHelper.createSAXReader( "XML InputStream", errors, cfg.getEntityResolver() ); + try { + saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true ); + } + catch (SAXException e) { + saxReader.setValidation( false ); + } + + for ( String xmlFile : xmlFiles ) { + + InputStream resourceAsStream = newTempClassLoader.getResourceAsStream( xmlFile ); + if (resourceAsStream == null) continue; + BufferedInputStream is = new BufferedInputStream( resourceAsStream ); + try { + errors.clear(); + org.dom4j.Document doc = saxReader.read( is ); + if ( errors.size() != 0 ) { + throw new MappingException( "invalid mapping", (Throwable) errors.get( 0 ) ); + } + Element rootElement = doc.getRootElement(); + if ( rootElement != null && "entity-mappings".equals( rootElement.getName() ) ) { + Element element = rootElement.element( "package" ); + String defaultPackage = element != null ? element.getTextTrim() : null; + List<Element> elements = rootElement.elements( "entity" ); + for (Element subelement : elements ) { + String classname = XMLContext.buildSafeClassName( subelement.attributeValue( "class" ), defaultPackage ); + if ( ! entities.contains( classname ) ) { + entities.add( classname ); + } + } + elements = rootElement.elements( "mapped-superclass" ); + for (Element subelement : elements ) { + String classname = XMLContext.buildSafeClassName( subelement.attributeValue( "class" ), defaultPackage ); + if ( ! entities.contains( classname ) ) { + entities.add( classname ); + } + } + elements = rootElement.elements( "embeddable" ); + for (Element subelement : elements ) { + String classname = XMLContext.buildSafeClassName( subelement.attributeValue( "class" ), defaultPackage ); + if ( ! entities.contains( classname ) ) { + entities.add( classname ); + } + } + } + else if ( rootElement != null && "hibernate-mappings".equals( rootElement.getName() ) ) { + //TODO + } + } + catch (DocumentException e) { + throw new MappingException( "Could not parse mapping document in input stream", e ); + } + finally { + try { + is.close(); + } + catch (IOException ioe) { + log.warn( "Could not close input stream", ioe ); + } + } + } + } + private void defineTransactionType(Object overridenTxType, Map workingVars) { if ( overridenTxType == null ) { // if ( transactionType == null ) { @@ -508,7 +590,7 @@ } boolean isEmbeddableSuperclass = visible.getAnnotation( MappedSuperclass.class.getName() ) != null; if ( isEmbeddableSuperclass ) { - log.info( "found EJB3 @EmbeddableSuperclass: " + cf.getName() ); + log.info( "found EJB3 @MappedSuperclass: " + cf.getName() ); entities.add( cf.getName() ); } } Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/connection/PersistenceUnitInfoImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/connection/PersistenceUnitInfoImpl.java 2006-05-04 16:41:12 UTC (rev 9876) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/connection/PersistenceUnitInfoImpl.java 2006-05-04 18:04:44 UTC (rev 9877) @@ -89,6 +89,6 @@ } public ClassLoader getNewTempClassLoader() { - return null; + return Thread.currentThread().getContextClassLoader(); } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java 2006-05-04 16:41:12 UTC (rev 9876) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java 2006-05-04 18:04:44 UTC (rev 9877) @@ -39,7 +39,6 @@ import org.hibernate.util.JoinedIterator; import org.hibernate.util.ReflectHelper; import org.hibernate.util.StringHelper; -import org.hibernate.util.XMLHelper; import org.hibernate.validator.ClassValidator; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -78,7 +77,6 @@ private List<Document> hbmDocuments; //user ordering matters, hence the list private String precedence = null; private boolean inSecondPass = false; - protected XMLHelper xmlHelper; private ReflectionManager reflectionManager; private boolean isDefaultProcessed = false; @@ -227,7 +225,6 @@ namingStrategy = EJB3NamingStrategy.INSTANCE; setEntityResolver( new EJB3DTDEntityResolver() ); reflectionManager = new JavaXFactory(); - xmlHelper = new XMLHelper(); } @Override Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java 2006-05-04 16:41:12 UTC (rev 9876) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java 2006-05-04 18:04:44 UTC (rev 9877) @@ -134,7 +134,7 @@ return localAddedClasses; } - private static String buildSafeClassName(String className, String defaultPackageName) { + public static String buildSafeClassName(String className, String defaultPackageName) { if ( className.indexOf( '.' ) < 0 && defaultPackageName != null ) { className = StringHelper.qualify( defaultPackageName, className ); } |
From: <hib...@li...> - 2006-05-04 16:41:17
|
Author: epbernard Date: 2006-05-04 12:41:12 -0400 (Thu, 04 May 2006) New Revision: 9876 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java Log: typo Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java 2006-05-04 16:23:44 UTC (rev 9875) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java 2006-05-04 16:41:12 UTC (rev 9876) @@ -50,7 +50,7 @@ String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName ) { String header = propertyName != null ? StringHelper.unqualify( propertyName ) : propertyTableName; - if ( header == null ) throw new AssertionFailure( "NammingStrategy not properly filled" ); + if ( header == null ) throw new AssertionFailure( "NamingStrategy not properly filled" ); return columnName( header + "_" + referencedColumnName ); } |
From: <hib...@li...> - 2006-05-04 16:26:12
|
Author: ste...@jb... Date: 2006-05-04 12:23:44 -0400 (Thu, 04 May 2006) New Revision: 9875 Added: trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/ trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/Group.java trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/OrderedManyToManyTest.java trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/User.java trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/UserGroup.hbm.xml Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java trunk/Hibernate3/src/org/hibernate/hibernate-mapping-3.0.dtd trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java trunk/Hibernate3/src/org/hibernate/loader/JoinWalker.java trunk/Hibernate3/src/org/hibernate/loader/collection/BasicCollectionJoinWalker.java trunk/Hibernate3/src/org/hibernate/mapping/Collection.java trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java trunk/Hibernate3/src/org/hibernate/persister/collection/QueryableCollection.java Log: HHH-1414 : many-to-many and order-by Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -2411,7 +2411,7 @@ false, mappings ); - bindManyToManyFilters( collection, subnode, mappings ); + bindManyToManySubelements( collection, subnode, mappings ); } else if ( "composite-element".equals( name ) ) { Component element = new Component( collection ); @@ -2457,7 +2457,7 @@ } } - private static void bindManyToManyFilters( + private static void bindManyToManySubelements( Collection collection, Element manyToManyNode, Mappings model) throws MappingException { @@ -2466,6 +2466,11 @@ String whereCondition = where == null ? null : where.getValue(); collection.setManyToManyWhere( whereCondition ); + // Bind the order-by + Attribute order = manyToManyNode.attribute( "order-by" ); + String orderFragment = order == null ? null : order.getValue(); + collection.setManyToManyOrdering( orderFragment ); + // Bind the filters Iterator filters = manyToManyNode.elementIterator( "filter" ); if ( ( filters.hasNext() || whereCondition != null ) && Modified: trunk/Hibernate3/src/org/hibernate/hibernate-mapping-3.0.dtd =================================================================== --- trunk/Hibernate3/src/org/hibernate/hibernate-mapping-3.0.dtd 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/hibernate-mapping-3.0.dtd 2006-05-04 16:23:44 UTC (rev 9875) @@ -765,6 +765,7 @@ <!ATTLIST many-to-many foreign-key CDATA #IMPLIED> <!ATTLIST many-to-many unique (true|false) "false"> <!ATTLIST many-to-many where CDATA #IMPLIED> + <!ATTLIST many-to-many order-by CDATA #IMPLIED> <!ATTLIST many-to-many property-ref CDATA #IMPLIED> <!-- A composite element allows a collection to hold instances of an arbitrary Modified: trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -558,6 +558,11 @@ .getSQLOrderByString( fromElement.getCollectionTableAlias() ); qn.getOrderByClause().addOrderFragment( orderByFragment ); } + if ( fromElement.getQueryableCollection().hasManyToManyOrdering() ) { + String orderByFragment = fromElement.getQueryableCollection() + .getManyToManyOrderByString( fromElement.getTableAlias() ); + qn.getOrderByClause().addOrderFragment( orderByFragment ); + } } } } Modified: trunk/Hibernate3/src/org/hibernate/loader/JoinWalker.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/JoinWalker.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/loader/JoinWalker.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -717,14 +717,19 @@ } protected String orderBy(final List associations, final String orderBy) { - String fullOrderBy = orderBy(associations); - if ( fullOrderBy.length()== 0 ) { - fullOrderBy = orderBy; + return mergeOrderings( orderBy( associations ), orderBy ); + } + + protected static String mergeOrderings(String ordering1, String ordering2) { + if ( ordering1.length() == 0 ) { + return ordering2; } - else if ( orderBy.length()!=0 ) { - fullOrderBy = fullOrderBy + ", " + orderBy; + else if ( ordering2.length() == 0 ) { + return ordering1; } - return fullOrderBy; + else { + return ordering1 + ", " + ordering2; + } } /** @@ -791,15 +796,32 @@ throws MappingException { StringBuffer buf = new StringBuffer(); Iterator iter = associations.iterator(); + OuterJoinableAssociation last = null; while ( iter.hasNext() ) { OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next(); - if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN && oj.getJoinable().isCollection() ) { - final QueryableCollection queryableCollection = (QueryableCollection) oj.getJoinable(); - if ( queryableCollection.hasOrdering() ) { - final String orderByString = queryableCollection.getSQLOrderByString( oj.getRHSAlias() ); - buf.append( orderByString ).append(", "); + if ( oj.getJoinType() == JoinFragment.LEFT_OUTER_JOIN ) { // why does this matter? + if ( oj.getJoinable().isCollection() ) { + final QueryableCollection queryableCollection = (QueryableCollection) oj.getJoinable(); + if ( queryableCollection.hasOrdering() ) { + final String orderByString = queryableCollection.getSQLOrderByString( oj.getRHSAlias() ); + buf.append( orderByString ).append(", "); + } } + else { + // it might still need to apply a collection ordering based on a + // many-to-many defined order-by... + if ( last != null && last.getJoinable().isCollection() ) { + final QueryableCollection queryableCollection = (QueryableCollection) last.getJoinable(); + if ( queryableCollection.isManyToMany() && last.isManyToManyWith( oj ) ) { + if ( queryableCollection.hasManyToManyOrdering() ) { + final String orderByString = queryableCollection.getManyToManyOrderByString( oj.getRHSAlias() ); + buf.append( orderByString ).append(", "); + } + } + } + } } + last = oj; } if ( buf.length()>0 ) buf.setLength( buf.length()-2 ); return buf.toString(); Modified: trunk/Hibernate3/src/org/hibernate/loader/collection/BasicCollectionJoinWalker.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/collection/BasicCollectionJoinWalker.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/loader/collection/BasicCollectionJoinWalker.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -81,6 +81,8 @@ subquery, batchSize ); + + String manyToManyOrderBy = ""; String filter = collectionPersister.filterFragment( alias, getEnabledFilters() ); if ( collectionPersister.isManyToMany() ) { // from the collection of associations, locate OJA for the @@ -98,6 +100,7 @@ oja.getRHSAlias(), getEnabledFilters() ); + manyToManyOrderBy += collectionPersister.getManyToManyOrderByString( oja.getRHSAlias() ); } } } @@ -116,7 +119,7 @@ ojf.toWhereFragmentString() ); - select.setOrderByClause( orderBy(associations, collectionPersister.getSQLOrderByString(alias) ) ); + select.setOrderByClause( orderBy( associations, mergeOrderings( collectionPersister.getSQLOrderByString(alias), manyToManyOrderBy ) ) ); if ( getFactory().getSettings().isCommentsEnabled() ) { select.setComment( "load collection " + collectionPersister.getRole() ); Modified: trunk/Hibernate3/src/org/hibernate/mapping/Collection.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/mapping/Collection.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/mapping/Collection.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -40,6 +40,7 @@ private String orderBy; private String where; private String manyToManyWhere; + private String manyToManyOrderBy; private PersistentClass owner; private String referencedPropertyName; private String nodeName; @@ -67,7 +68,7 @@ private boolean customDeleteCallable; private boolean customDeleteAllCallable; - private String loaderName; + private String loaderName; protected Collection(PersistentClass owner) { this.owner = owner; @@ -210,6 +211,14 @@ this.manyToManyWhere = manyToManyWhere; } + public String getManyToManyOrdering() { + return manyToManyOrderBy; + } + + public void setManyToManyOrdering(String orderFragment) { + this.manyToManyOrderBy = orderFragment; + } + public boolean isIdentified() { return false; } @@ -573,5 +582,4 @@ public String getComparatorClassName() { return comparatorClassName; } - } \ No newline at end of file Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -171,6 +171,9 @@ private final String manyToManyWhereString; private final String manyToManyWhereTemplate; + private final String manyToManyOrderByString; + private final String manyToManyOrderByTemplate; + // custom sql private final boolean insertCallable; private final boolean updateCallable; @@ -249,7 +252,9 @@ hasOrphanDelete = collection.hasOrphanDelete(); int batch = collection.getBatchSize(); - if (batch==-1) batch = factory.getSettings().getDefaultBatchFetchSize(); + if ( batch == -1 ) { + batch = factory.getSettings().getDefaultBatchFetchSize(); + } batchSize = batch; isVersioned = collection.isOptimisticLocked(); @@ -313,7 +318,9 @@ elementColumnNames[j] = col.getQuotedName(dialect); elementColumnIsSettable[j] = true; elementColumnIsInPrimaryKey[j] = !col.isNullable(); - if ( !col.isNullable() ) hasNotNullableColumns = true; + if ( !col.isNullable() ) { + hasNotNullableColumns = true; + } isPureFormula = false; } j++; @@ -323,7 +330,9 @@ //workaround, for backward compatibility of sets with no //not-null columns, assume all columns are used in the //row locator SQL - if ( !hasNotNullableColumns ) Arrays.fill(elementColumnIsInPrimaryKey, true); + if ( !hasNotNullableColumns ) { + Arrays.fill( elementColumnIsInPrimaryKey, true ); + } // INDEX AND ROW SELECT @@ -496,6 +505,10 @@ manyToManyWhereTemplate = manyToManyWhereString == null ? null : Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect() ); + manyToManyOrderByString = collection.getManyToManyOrdering(); + manyToManyOrderByTemplate = manyToManyOrderByString == null + ? null + : Template.renderOrderByStringTemplate( manyToManyOrderByString, factory.getDialect() ); initCollectionPropertyMap(); } @@ -509,10 +522,18 @@ protected void logStaticSQL() { if ( log.isDebugEnabled() ) { log.debug( "Static SQL for collection: " + getRole() ); - if ( getSQLInsertRowString() != null ) log.debug( " Row insert: " + getSQLInsertRowString() ); - if ( getSQLUpdateRowString() != null ) log.debug( " Row update: " + getSQLUpdateRowString() ); - if ( getSQLDeleteRowString() != null ) log.debug( " Row delete: " + getSQLDeleteRowString() ); - if ( getSQLDeleteString() != null ) log.debug( " One-shot delete: " + getSQLDeleteString() ); + if ( getSQLInsertRowString() != null ) { + log.debug( " Row insert: " + getSQLInsertRowString() ); + } + if ( getSQLUpdateRowString() != null ) { + log.debug( " Row update: " + getSQLUpdateRowString() ); + } + if ( getSQLDeleteRowString() != null ) { + log.debug( " Row delete: " + getSQLDeleteRowString() ); + } + if ( getSQLDeleteString() != null ) { + log.debug( " One-shot delete: " + getSQLDeleteString() ); + } } } @@ -539,9 +560,11 @@ } private CollectionInitializer getSubselectInitializer(Serializable key, SessionImplementor session) { + + if ( !isSubselectLoadable() ) { + return null; + } - if ( !isSubselectLoadable() ) return null; - final PersistenceContext persistenceContext = session.getPersistenceContext(); SubselectFetch subselect = persistenceContext.getBatchFetchQueue() @@ -592,6 +615,14 @@ StringHelper.replace( sqlOrderByStringTemplate, Template.TEMPLATE, alias ) : ""; } + public String getManyToManyOrderByString(String alias) { + if ( isManyToMany() && manyToManyOrderByString != null ) { + return StringHelper.replace( manyToManyOrderByTemplate, Template.TEMPLATE, alias ); + } + else { + return ""; + } + } public FetchMode getFetchMode() { return fetchMode; } @@ -600,6 +631,10 @@ return hasOrder; } + public boolean hasManyToManyOrdering() { + return isManyToMany() && manyToManyOrderByTemplate != null; + } + public boolean hasWhere() { return hasWhere; } @@ -817,7 +852,9 @@ } protected String generateDetectRowByIndexString() { - if ( !hasIndex() ) return null; + if ( !hasIndex() ) { + return null; + } return new SimpleSelect(dialect) .setTableName( getTableName() ) .addCondition( getKeyColumnNames(), "=?" ) @@ -828,7 +865,9 @@ } protected String generateSelectRowByIndexString() { - if ( !hasIndex() ) return null; + if ( !hasIndex() ) { + return null; + } return new SimpleSelect(dialect) .setTableName( getTableName() ) .addCondition( getKeyColumnNames(), "=?" ) @@ -881,7 +920,9 @@ } protected void appendIdentifierColumns(SelectFragment frag, String alias) { - if ( hasIdentifier ) frag.addColumn( alias, identifierColumnName, identifierColumnAlias ); + if ( hasIdentifier ) { + frag.addColumn( alias, identifierColumnName, identifierColumnAlias ); + } } public String[] getIndexColumnNames() { @@ -974,7 +1015,9 @@ throw sqle; } - if ( log.isDebugEnabled() ) log.debug( "done deleting collection" ); + if ( log.isDebugEnabled() ) { + log.debug( "done deleting collection" ); + } } catch ( SQLException sqle ) { throw JDBCExceptionHelper.convert( @@ -1042,7 +1085,9 @@ } i++; } - if ( log.isDebugEnabled() ) log.debug( "done inserting collection: " + count + " rows inserted" ); + if ( log.isDebugEnabled() ) { + log.debug( "done inserting collection: " + count + " rows inserted" ); + } } catch ( SQLException sqle ) { session.getBatcher().abortBatch( sqle ); @@ -1051,7 +1096,9 @@ } else { - if ( log.isDebugEnabled() ) log.debug( "collection was empty" ); + if ( log.isDebugEnabled() ) { + log.debug( "collection was empty" ); + } } } catch ( SQLException sqle ) { @@ -1130,10 +1177,14 @@ throw sqle; } - if ( log.isDebugEnabled() ) log.debug( "done deleting collection rows: " + count + " deleted" ); + if ( log.isDebugEnabled() ) { + log.debug( "done deleting collection rows: " + count + " deleted" ); + } } else { - if ( log.isDebugEnabled() ) log.debug( "no rows to delete" ); + if ( log.isDebugEnabled() ) { + log.debug( "no rows to delete" ); + } } } catch ( SQLException sqle ) { @@ -1205,7 +1256,9 @@ } i++; } - if ( log.isDebugEnabled() ) log.debug( "done inserting rows: " + count + " inserted" ); + if ( log.isDebugEnabled() ) { + log.debug( "done inserting rows: " + count + " inserted" ); + } } catch ( SQLException sqle ) { session.getBatcher().abortBatch( sqle ); @@ -1251,7 +1304,9 @@ } public Type toType(String propertyName) throws QueryException { - if ( "index".equals( propertyName ) ) return indexType; + if ( "index".equals( propertyName ) ) { + return indexType; + } return elementPropertyMapping.toType( propertyName ); } @@ -1304,7 +1359,9 @@ } public EntityPersister getElementPersister() { - if ( elementPersister == null ) throw new AssertionFailure( "not an association" ); + if ( elementPersister == null ) { + throw new AssertionFailure( "not an association" ); + } return ( Loadable ) elementPersister; } @@ -1428,8 +1485,10 @@ public String[] getCollectionPropertyColumnAliases(String propertyName, String suffix) { String rawAliases[] = (String[]) collectionPropertyColumnAliases.get(propertyName); - - if(rawAliases==null) return null; + + if ( rawAliases == null ) { + return null; + } String result[] = new String[rawAliases.length]; for ( int i=0; i<rawAliases.length; i++ ) { Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -203,6 +203,9 @@ * that happens in memory, as in the case of a sorted collection.) */ public boolean hasOrdering(); + + public boolean hasManyToManyOrdering(); + /** * Get the "space" that holds the persistent state */ Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/QueryableCollection.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/persister/collection/QueryableCollection.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/src/org/hibernate/persister/collection/QueryableCollection.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -46,7 +46,16 @@ * Get the order by SQL */ public abstract String getSQLOrderByString(String alias); + /** + * Get the order-by to be applied at the target table of a many to many + * + * @param alias The alias for the many-to-many target table + * @return appropriate order-by fragment or empty string. + */ + public abstract String getManyToManyOrderByString(String alias); + + /** * Does this collection role have a where clause filter? */ public abstract boolean hasWhere(); Added: trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/Group.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/Group.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/Group.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -0,0 +1,69 @@ +package org.hibernate.test.manytomany.ordered; + +import java.io.Serializable; +import java.util.List; +import java.util.ArrayList; + +public class Group implements Serializable { + + private Long id; + private String org; + private String name; + private String description; + + private List users = new ArrayList(); + + public Group() { + } + + public Group(String name, String org) { + this.org = org; + this.name = name; + } + + 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 String getOrg() { + return org; + } + + public void setOrg(String org) { + this.org = org; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public void addUser(User user) { + if ( user.getGroups().add( this ) ) { + getUsers().add( user ); + } + } +} Added: trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/OrderedManyToManyTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/OrderedManyToManyTest.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/OrderedManyToManyTest.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -0,0 +1,137 @@ +package org.hibernate.test.manytomany.ordered; + +import org.hibernate.test.TestCase; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.Hibernate; +import org.hibernate.FetchMode; +import org.hibernate.Criteria; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.util.List; + +/** + * @author Gavin King + */ +public class OrderedManyToManyTest extends TestCase { + + public OrderedManyToManyTest(String str) { + super(str); + } + + public void testManyToManyOrdering() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + User gavin = new User( "gavin", "jboss" ); + User steve = new User( "steve", "jboss" ); + User max = new User( "max", "jboss" ); + User emmanuel = new User( "emmanuel", "jboss" ); + s.persist( gavin ); + s.persist( steve ); + s.persist( max ); + s.persist( emmanuel ); + Group hibernate = new Group( "hibernate", "jboss" ); + hibernate.addUser( gavin ); + hibernate.addUser( steve ); + hibernate.addUser( max ); + hibernate.addUser( emmanuel ); + s.persist( hibernate ); + t.commit(); + s.close(); + + // delayed collection load... + s = openSession(); + t = s.beginTransaction(); + hibernate = ( Group ) s.get( Group.class, hibernate.getId() ); + assertFalse( Hibernate.isInitialized( hibernate.getUsers() ) ); + assertEquals( 4, hibernate.getUsers().size() ); + assertOrdering( hibernate.getUsers() ); + t.commit(); + s.close(); + + // HQL (non eager) + s = openSession(); + t = s.beginTransaction(); + hibernate = ( Group ) s.createQuery( "from Group" ).uniqueResult(); + assertFalse( Hibernate.isInitialized( hibernate.getUsers() ) ); + assertEquals( 4, hibernate.getUsers().size() ); + assertOrdering( hibernate.getUsers() ); + t.commit(); + s.close(); + + // HQL (eager) + s = openSession(); + t = s.beginTransaction(); + hibernate = ( Group ) s.createQuery( "from Group g inner join fetch g.users" ).uniqueResult(); + assertTrue( Hibernate.isInitialized( hibernate.getUsers() ) ); + assertEquals( 4, hibernate.getUsers().size() ); + assertOrdering( hibernate.getUsers() ); + t.commit(); + s.close(); + + // criteria load (forced eager fetch) + s = openSession(); + t = s.beginTransaction(); + Criteria criteria = s.createCriteria( Group.class ); + criteria.setFetchMode( "users", FetchMode.JOIN ); + hibernate = ( Group ) criteria.uniqueResult(); + assertTrue( Hibernate.isInitialized( hibernate.getUsers() ) ); + assertEquals( 4, hibernate.getUsers().size() ); + assertOrdering( hibernate.getUsers() ); + t.commit(); + s.close(); + + // criteria load (forced non eager fetch) + s = openSession(); + t = s.beginTransaction(); + criteria = s.createCriteria( Group.class ); + criteria.setFetchMode( "users", FetchMode.SELECT ); + hibernate = ( Group ) criteria.uniqueResult(); + assertFalse( Hibernate.isInitialized( hibernate.getUsers() ) ); + assertEquals( 4, hibernate.getUsers().size() ); + assertOrdering( hibernate.getUsers() ); + t.commit(); + s.close(); + + // clean up + s = openSession(); + t = s.beginTransaction(); + s.delete( gavin ); + s.delete( steve ); + s.delete( max ); + s.delete( emmanuel ); + s.delete( hibernate ); + t.commit(); + s.close(); + } + + private void assertOrdering(List users) { + User user = extractUser( users, 0 ); + assertTrue( "many-to-many ordering not applied", user.getName().equals( "emmanuel" ) ); + user = extractUser( users, 1 ); + assertTrue( "many-to-many ordering not applied", user.getName().equals( "gavin" ) ); + user = extractUser( users, 2 ); + assertTrue( "many-to-many ordering not applied", user.getName().equals( "max" ) ); + user = extractUser( users, 3 ); + assertTrue( "many-to-many ordering not applied", user.getName().equals( "steve" ) ); + } + + private User extractUser(List users, int position) { + return ( User ) users.get( position ); + } + protected String[] getMappings() { + return new String[] { "manytomany/ordered/UserGroup.hbm.xml" }; + } + + public static Test suite() { + return new TestSuite( OrderedManyToManyTest.class); + } + + protected void configure(Configuration cfg) { + cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "false"); + } + +} Added: trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/User.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/User.java 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/User.java 2006-05-04 16:23:44 UTC (rev 9875) @@ -0,0 +1,54 @@ +package org.hibernate.test.manytomany.ordered; + +import java.io.Serializable; +import java.util.Set; +import java.util.HashSet; + +public class User implements Serializable { + + private Long id; + private String org; + private String name; + private Set groups = new HashSet(); + + public User() { + } + + public User(String name, String org) { + this.org = org; + this.name = name; + } + + 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 String getOrg() { + return org; + } + + public void setOrg(String org) { + this.org = org; + } + + public Set getGroups() { + return groups; + } + + public void setGroups(Set groups) { + this.groups = groups; + } + +} Added: trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/UserGroup.hbm.xml =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/UserGroup.hbm.xml 2006-05-04 15:10:22 UTC (rev 9874) +++ trunk/Hibernate3/test/org/hibernate/test/manytomany/ordered/UserGroup.hbm.xml 2006-05-04 16:23:44 UTC (rev 9875) @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD 3.0//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> + +<!-- + + This mapping demonstrates how to map a many-to-many + association with a shared attribute in the primary keys + of the associated entities. + +--> + +<hibernate-mapping + package="org.hibernate.test.manytomany.ordered"> + + + <class name="User" table="`User`"> + <id name="id" column="ID" type="long"> + <generator class="native"/> + </id> + <property name="name" column="NAME"/> + <property name="org" column="ORG"/> + <set name="groups" table="UserGroup"> + <key column="USER_ID"/> + <many-to-many column="GROUP_ID" class="Group"/> + </set> + </class> + + <class name="Group" table="`Group`"> + <id name="id" column="ID"> + <generator class="native"/> + </id> + <property name="name"/> + <property name="description"/> + <bag name="users" table="UserGroup" inverse="true"> + <key column="GROUP_ID"/> + <many-to-many column="USER_ID" class="User" order-by="NAME"/> + </bag> + </class> + +</hibernate-mapping> |
From: <hib...@li...> - 2006-05-04 15:10:33
|
Author: epbernard Date: 2006-05-04 11:10:22 -0400 (Thu, 04 May 2006) New Revision: 9874 Modified: trunk/Hibernate3/src/org/hibernate/cfg/DefaultNamingStrategy.java trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java trunk/Hibernate3/src/org/hibernate/cfg/ImprovedNamingStrategy.java trunk/Hibernate3/src/org/hibernate/cfg/NamingStrategy.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/DefaultComponentSafeNamingStrategy.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/AlternativeNamingStrategy.java Log: HHH-1477 NamingStrategy support EntityA_EntityB ANN-195 does not change the EJB3 NS however Modified: trunk/Hibernate3/src/org/hibernate/cfg/DefaultNamingStrategy.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/DefaultNamingStrategy.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/Hibernate3/src/org/hibernate/cfg/DefaultNamingStrategy.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -46,7 +46,10 @@ /** * Return the unqualified property name, not the best strategy but a backward compatible one */ - public String collectionTableName(String ownerEntityTable, String associatedEntityTable, String propertyName) { + public String collectionTableName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ) { //use a degenerated strategy for backward compatibility return StringHelper.unqualify(propertyName); } @@ -61,7 +64,9 @@ /** * Return the property name or propertyTableName */ - public String foreignKeyColumnName(String propertyName, String propertyTableName, String referencedColumnName) { + public String foreignKeyColumnName( + String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName + ) { String header = propertyName != null ? StringHelper.unqualify( propertyName ) : propertyTableName; if (header == null) throw new AssertionFailure("NammingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -1365,7 +1365,13 @@ //TODO mappings.getLogicalTableName(ownerTable) String logicalOwnerTableName = ownerTable.getName(); //FIXME we don't have the associated entity table name here, has to be done in a second pass - tableName = mappings.getNamingStrategy().collectionTableName( logicalOwnerTableName ,null, path); + tableName = mappings.getNamingStrategy().collectionTableName( + collection.getOwner().getEntityName(), + logicalOwnerTableName , + null, + null, + path + ); } Attribute schemaNode = node.attribute( "schema" ); String schema = schemaNode == null ? Modified: trunk/Hibernate3/src/org/hibernate/cfg/ImprovedNamingStrategy.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/ImprovedNamingStrategy.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/Hibernate3/src/org/hibernate/cfg/ImprovedNamingStrategy.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -60,7 +60,10 @@ return buf.toString().toLowerCase(); } - public String collectionTableName(String ownerEntityTable, String associatedEntityTable, String propertyName) { + public String collectionTableName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ) { return tableName( ownerEntityTable + '_' + propertyToColumnName(propertyName) ); } @@ -74,7 +77,9 @@ /** * Return the property name or propertyTableName */ - public String foreignKeyColumnName(String propertyName, String propertyTableName, String referencedColumnName) { + public String foreignKeyColumnName( + String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName + ) { String header = propertyName != null ? StringHelper.unqualify( propertyName ) : propertyTableName; if (header == null) throw new AssertionFailure("NammingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility Modified: trunk/Hibernate3/src/org/hibernate/cfg/NamingStrategy.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/NamingStrategy.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/Hibernate3/src/org/hibernate/cfg/NamingStrategy.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -8,7 +8,7 @@ * naming standards for database objects. * * #propertyToTableName(String, String) should be replaced by - * {@link #collectionTableName(String, String, String)} + * {@link #collectionTableName(String,String,String,String,String)} * * @see DefaultNamingStrategy * @see ImprovedNamingStrategy @@ -43,11 +43,16 @@ /** * Return a collection table name ie an association having a join table * + * @param ownerEntity * @param ownerEntityTable owner side table name + * @param associatedEntity * @param associatedEntityTable reverse side table name if any * @param propertyName collection role */ - public String collectionTableName(String ownerEntityTable, String associatedEntityTable, String propertyName); + public String collectionTableName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ); /** * Return the join key column name ie a FK column used in a JOINED strategy or for a secondary table * @@ -58,10 +63,13 @@ /** * Return the foreign key column name for the given parameters * @param propertyName the property name involved + * @param propertyEntityName * @param propertyTableName the property table name involved (logical one) * @param referencedColumnName the referenced column name involved (logical one) */ - public String foreignKeyColumnName(String propertyName, String propertyTableName, String referencedColumnName); + public String foreignKeyColumnName( + String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName + ); /** * Return the logical column name used to refer to a column in the metadata * (like index, unique constraints etc) Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/DefaultComponentSafeNamingStrategy.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/DefaultComponentSafeNamingStrategy.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/DefaultComponentSafeNamingStrategy.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -20,7 +20,10 @@ } @Override - public String collectionTableName(String ownerEntityTable, String associatedEntityTable, String propertyName) { + public String collectionTableName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ) { return tableName( new StringBuilder( ownerEntityTable ).append( "_" ) .append( @@ -32,7 +35,9 @@ } - public String foreignKeyColumnName(String propertyName, String propertyTableName, String referencedColumnName) { + public String foreignKeyColumnName( + String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName + ) { String header = propertyName != null ? addUnderscores( propertyName ) : propertyTableName; if ( header == null ) throw new AssertionFailure( "NamingStrategy not properly filled" ); return columnName( header + "_" + referencedColumnName ); Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/EJB3NamingStrategy.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -28,7 +28,10 @@ return columnName; } - public String collectionTableName(String ownerEntityTable, String associatedEntityTable, String propertyName) { + public String collectionTableName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ) { return tableName( new StringBuilder( ownerEntityTable ).append( "_" ) .append( @@ -43,7 +46,9 @@ return columnName( joinedColumn ); } - public String foreignKeyColumnName(String propertyName, String propertyTableName, String referencedColumnName) { + public String foreignKeyColumnName( + String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName + ) { String header = propertyName != null ? StringHelper.unqualify( propertyName ) : propertyTableName; if ( header == null ) throw new AssertionFailure( "NammingStrategy not properly filled" ); return columnName( header + "_" + referencedColumnName ); Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -34,6 +34,7 @@ private String mappedByPropertyName; //table name on the mapped by side if any private String mappedByTableName; + private String mappedByEntityName; //FIXME hacky solution to get the information at proeprty ref resolution public String getManyToManyOwnerSideEntityName() { @@ -262,17 +263,19 @@ } } - public void linkValueUsingDefaultColumnNaming(Column referencedColumn, Table referencedTable, SimpleValue value) { + public void linkValueUsingDefaultColumnNaming( + Column referencedColumn, PersistentClass referencedEntity, SimpleValue value + ) { String columnName; String logicalReferencedColumn = getMappings().getLogicalColumnName( - referencedColumn.getName(), referencedTable + referencedColumn.getName(), referencedEntity.getTable() ); boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null; boolean ownerSide = getPropertyName() != null; if ( mappedBySide ) { columnName = getMappings().getNamingStrategy().foreignKeyColumnName( mappedByPropertyName, - mappedByTableName, + mappedByEntityName, mappedByTableName, logicalReferencedColumn ); //columnName = ( defaultColumnHeader == null ? getPropertyName() : defaultColumnHeader ) + "_" + logicalReferencedColumn; @@ -280,7 +283,7 @@ else if ( ownerSide ) { columnName = getMappings().getNamingStrategy().foreignKeyColumnName( getPropertyName(), - getMappings().getLogicalTableName( referencedTable ), + referencedEntity.getEntityName(), getMappings().getLogicalTableName( referencedEntity.getTable() ), logicalReferencedColumn ); } @@ -288,7 +291,7 @@ //is an intra-entity hierarchy table join so copy the name by default columnName = getMappings().getNamingStrategy().joinKeyColumnName( logicalReferencedColumn, - getMappings().getLogicalTableName( referencedTable ) + getMappings().getLogicalTableName( referencedEntity.getTable() ) ); } //yuk side effect on an implicit column @@ -419,28 +422,6 @@ } } - public void setDefaultColumnName() { - String columnName = null; - boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null; - boolean ownerSide = getPropertyName() != null; - if ( mappedBySide ) { - columnName = getMappings().getNamingStrategy().foreignKeyColumnName( - mappedByPropertyName, - mappedByTableName, - referencedColumn - ); - //columnName = ( defaultColumnHeader == null ? getPropertyName() : defaultColumnHeader ) + "_" + logicalReferencedColumn; - } - else if ( ownerSide ) { - columnName = getMappings().getNamingStrategy().foreignKeyColumnName( - getPropertyName(), - null, //getMappings().getLogicalTableName( referencedTable ), - referencedColumn - ); - } - getMappingColumn().setName( columnName ); - } - public void setMappedByPropertyName(String mappedByPropertyName) { this.mappedByPropertyName = mappedByPropertyName; } @@ -494,4 +475,10 @@ } return joinColumns; } + + public void setMappedBy(String entityName, String logicalTableName, String mappedByProperty) { + this.mappedByEntityName = entityName; + this.mappedByTableName = logicalTableName; + this.mappedByPropertyName = mappedByProperty; + } } \ No newline at end of file Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -11,10 +11,10 @@ import javax.persistence.AttributeOverrides; import javax.persistence.Embeddable; import javax.persistence.FetchType; +import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.MapKey; import javax.persistence.OneToMany; -import javax.persistence.JoinTable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -216,7 +216,7 @@ else { throw new AnnotationException( "Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: " - + StringHelper.qualify( entityName, property.getName() ) + + StringHelper.qualify( entityName, property.getName() ) ); } } @@ -787,7 +787,7 @@ } //check for user error if ( ! isCollectionOfEntities ) { - if ( property.isAnnotationPresent( ManyToMany.class ) || property.isAnnotationPresent( OneToMany.class )) { + if ( property.isAnnotationPresent( ManyToMany.class ) || property.isAnnotationPresent( OneToMany.class ) ) { String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName(); throw new AnnotationException( "Use of @OneToMany or @ManyToMany targeting an unmapped class: " + path + "[" + collType + "]" @@ -795,9 +795,9 @@ } else { JoinTable joinTableAnn = property.getAnnotation( JoinTable.class ); - if (joinTableAnn != null && joinTableAnn.inverseJoinColumns().length > 0) { + if ( joinTableAnn != null && joinTableAnn.inverseJoinColumns().length > 0 ) { String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName(); - throw new AnnotationException( + throw new AnnotationException( "Use of @JoinTable.inverseJoinColumns targeting an unmapped class: " + path + "[" + collType + "]" ); } @@ -856,16 +856,20 @@ String mappedByProperty = mappings.getFromMappedBy( collValue.getOwnerEntityName(), column.getPropertyName() ); - column.setMappedByPropertyName( mappedByProperty ); Table ownerTable = collValue.getOwner().getTable(); - column.setMappedByTableName( mappings.getLogicalTableName( ownerTable ) ); + column.setMappedBy( + collValue.getOwner().getEntityName(), mappings.getLogicalTableName( ownerTable ), + mappedByProperty + ); // String header = ( mappedByProperty == null ) ? mappings.getLogicalTableName( ownerTable ) : mappedByProperty; // column.setDefaultColumnHeader( header ); } if ( StringHelper.isEmpty( associationTableBinder.getName() ) ) { //default value associationTableBinder.setDefaultName( + collValue.getOwner().getEntityName(), mappings.getLogicalTableName( collValue.getOwner().getTable() ), + collectionEntity != null ? collectionEntity.getEntityName() : null, collectionEntity != null ? mappings.getLogicalTableName( collectionEntity.getTable() ) : null, joinColumns[0].getPropertyName() ); Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -46,6 +46,8 @@ private String ownerEntityTable; private String associatedEntityTable; private String propertyName; + private String ownerEntity; + private String associatedEntity; public void setSchema(String schema) { this.schema = schema; @@ -83,6 +85,7 @@ this.mappings = mappings; } + // only bind association table currently public Table bind() { //logicalName only accurate for assoc table... String logicalName = mappings.getNamingStrategy() @@ -90,7 +93,9 @@ String extendedName = name != null ? mappings.getNamingStrategy().tableName( name ) : mappings.getNamingStrategy() - .collectionTableName( ownerEntityTable, associatedEntityTable, propertyName ); + .collectionTableName( + ownerEntity, ownerEntityTable, associatedEntity, associatedEntityTable, propertyName + ); return fillTable( schema, catalog, extendedName, logicalName, isAbstract, uniqueConstraints, constraints, @@ -198,7 +203,7 @@ while ( idColumns.hasNext() ) { Column column = (Column) idColumns.next(); columns[0].overrideSqlTypeIfNecessary( column ); - columns[0].linkValueUsingDefaultColumnNaming( column, referencedEntity.getTable(), value ); + columns[0].linkValueUsingDefaultColumnNaming( column, referencedEntity, value ); } } else { @@ -277,7 +282,7 @@ //proper join column if ( joinCol.isNameDeferred() ) { joinCol.linkValueUsingDefaultColumnNaming( - col, referencedEntity.getTable(), value + col, referencedEntity, value ); } else { @@ -311,7 +316,7 @@ Column synthCol = (Column) columnIterator.next(); if ( joinCol.isNameDeferred() ) { //this has to be the default value - joinCol.linkValueUsingDefaultColumnNaming( synthCol, referencedEntity.getTable(), value ); + joinCol.linkValueUsingDefaultColumnNaming( synthCol, referencedEntity, value ); } else { joinCol.linkWithValue( value ); @@ -347,8 +352,13 @@ return result; } - public void setDefaultName(String ownerEntityTable, String associatedEntityTable, String propertyName) { + public void setDefaultName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ) { + this.ownerEntity = ownerEntity; this.ownerEntityTable = ownerEntityTable; + this.associatedEntity = associatedEntity; this.associatedEntityTable = associatedEntityTable; this.propertyName = propertyName; this.name = null; Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/AlternativeNamingStrategy.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/AlternativeNamingStrategy.java 2006-05-04 13:42:48 UTC (rev 9873) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/AlternativeNamingStrategy.java 2006-05-04 15:10:22 UTC (rev 9874) @@ -35,7 +35,10 @@ return StringHelper.isNotEmpty( columnName ) ? columnName : propertyName; } - public String collectionTableName(String ownerEntityTable, String associatedEntityTable, String propertyName) { + public String collectionTableName( + String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable, + String propertyName + ) { return tableName( new StringBuilder( ownerEntityTable ).append( "_" ) .append( |
From: <hib...@li...> - 2006-05-04 13:42:57
|
Author: max...@jb... Date: 2006-05-04 09:42:48 -0400 (Thu, 04 May 2006) New Revision: 9873 Modified: trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java trunk/Hibernate3/test/org/hibernate/test/hql/Human.java Log: HHH-1538 aggregations functions in EJBQL queries does not return the appropriate types Added HQLTest.testAggregationReturnType to test for the above statements. Consequence: COUNT changed from Hibernate.INTEGER to Hibernate.LONG MAX/MIN no changes AVG changed from being dependent on the field to only return Hibernate.DOUBLE SUM changed from always just return the type of the field to return according to the above rules. Stuff that falls besides these rules simply just return the underlying field/column type. e..g SUM(timestamp) will return timestamp; but will/should fail on the db Modified: trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java 2006-05-04 13:42:48 UTC (rev 9873) @@ -65,7 +65,7 @@ static { STANDARD_AGGREGATE_FUNCTIONS.put( "count", new StandardSQLFunction("count") { public Type getReturnType(Type columnType, Mapping mapping) { - return Hibernate.INTEGER; + return Hibernate.LONG; } } ); @@ -80,18 +80,40 @@ } if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in avg()" ); int sqlType = sqlTypes[0]; - if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) { + /*pre H3.2 behavior if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) { return Hibernate.FLOAT; } else { return columnType; - } + }*/ + return Hibernate.DOUBLE; } } ); STANDARD_AGGREGATE_FUNCTIONS.put( "max", new StandardSQLFunction("max") ); STANDARD_AGGREGATE_FUNCTIONS.put( "min", new StandardSQLFunction("min") ); - STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") ); + STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") { + public Type getReturnType(Type columnType, Mapping mapping) { + //pre H3.2 behavior: super.getReturnType(ct, m); + int[] sqlTypes; + try { + sqlTypes = columnType.sqlTypes( mapping ); + } + catch ( MappingException me ) { + throw new QueryException( me ); + } + if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in sum()" ); + int sqlType = sqlTypes[0]; + if ( sqlType == Types.FLOAT || sqlType == Types.DOUBLE ) { + return Hibernate.DOUBLE; + } else if ( sqlType == Types.INTEGER || sqlType == Types.SMALLINT ) { + return Hibernate.LONG; + } + else { + return columnType; + } + } + }); } private final TypeNames typeNames = new TypeNames(); Modified: trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml 2006-05-04 13:42:48 UTC (rev 9873) @@ -48,6 +48,12 @@ </component> <property name="nickName"/> <property name="height"/> + + <property name="intValue"/> + <property name="floatValue"/> + <property name="bigDecimalValue"/> + <property name="bigIntegerValue"/> + <bag name="friends"> <key column="human1"/> <many-to-many column="human2" class="Human"/> Modified: trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-05-04 13:42:48 UTC (rev 9873) @@ -618,6 +618,7 @@ assertTranslation( "select count(*) from Human h group by year(sysdate)" ); } + public void testPolymorphism() throws Exception { HashMap replacements = new HashMap(); replacements.put( "false", "0" ); @@ -804,6 +805,64 @@ assertTranslation( "select count(all an.id) from Animal an" ); } + public void testAggregationReturnType() { + // EJB3: COUNT returns Long + QueryTranslatorImpl translator = createNewQueryTranslator( "select count(*) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + // MAX, MIN return the type of the state-field to which they are applied. + translator = createNewQueryTranslator( "select max(h.height) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select max(h.id) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + // AVG returns Double. + translator = createNewQueryTranslator( "select avg(h.height) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select avg(h.id) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select avg(h.bigIntegerValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + // SUM returns Long when applied to state-fields of integral types (other than BigInteger); + translator = createNewQueryTranslator( "select sum(h.id) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select sum(h.intValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + // SUM returns Double when applied to state-fields of floating point types; + translator = createNewQueryTranslator( "select sum(h.height) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select sum(h.floatValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + // SUM returns BigInteger when applied to state-fields of type BigInteger + translator = createNewQueryTranslator( "select sum(h.bigIntegerValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.BIG_INTEGER, translator.getReturnTypes()[0] ); + + // SUM and BigDecimal when applied to state-fields of type BigDecimal. + translator = createNewQueryTranslator( "select sum(h.bigDecimalValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.BIG_DECIMAL, translator.getReturnTypes()[0] ); + + } + public void testSelectProperty() throws Exception { assertTranslation( "select an.bodyWeight, mo.bodyWeight from Animal an inner join an.mother mo where an.bodyWeight < mo.bodyWeight" ); } Modified: trunk/Hibernate3/test/org/hibernate/test/hql/Human.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/Human.java 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/test/org/hibernate/test/hql/Human.java 2006-05-04 13:42:48 UTC (rev 9873) @@ -1,6 +1,8 @@ //$Id$ package org.hibernate.test.hql; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Collection; import java.util.Map; import java.util.Set; @@ -15,6 +17,12 @@ private Collection pets; private Map family; private double height; + + private BigInteger bigIntegerValue; + private BigDecimal bigDecimalValue; + private int intValue; + private float floatValue; + private Set nickNames; private Map addresses; @@ -81,4 +89,38 @@ public void setAddresses(Map addresses) { this.addresses = addresses; } + + public BigDecimal getBigDecimalValue() { + return bigDecimalValue; + } + + public void setBigDecimalValue(BigDecimal bigDecimalValue) { + this.bigDecimalValue = bigDecimalValue; + } + + public BigInteger getBigIntegerValue() { + return bigIntegerValue; + } + + public void setBigIntegerValue(BigInteger bigIntegerValue) { + this.bigIntegerValue = bigIntegerValue; + } + + public float getFloatValue() { + return floatValue; + } + + public void setFloatValue(float floatValue) { + this.floatValue = floatValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + } |
From: <hib...@li...> - 2006-05-04 13:16:18
|
Author: ste...@jb... Date: 2006-05-04 09:15:59 -0400 (Thu, 04 May 2006) New Revision: 9872 Modified: trunk/Hibernate3/test/org/hibernate/test/ternary/TernaryTest.java Log: test data cleanup Modified: trunk/Hibernate3/test/org/hibernate/test/ternary/TernaryTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ternary/TernaryTest.java 2006-05-04 11:58:42 UTC (rev 9871) +++ trunk/Hibernate3/test/org/hibernate/test/ternary/TernaryTest.java 2006-05-04 13:15:59 UTC (rev 9872) @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.HashMap; import junit.framework.Test; import junit.framework.TestSuite; @@ -83,7 +84,17 @@ total += map.size(); } assertTrue(total==3); + l = s.createQuery("from Employee e left join e.managerBySite m left join m.managerBySite m2").list(); + + // clean up... + l = s.createQuery("from Employee e left join fetch e.managerBySite").list(); + Iterator itr = l.iterator(); + while ( itr.hasNext() ) { + Employee emp = ( Employee ) itr.next(); + emp.setManagerBySite( new HashMap() ); + s.delete( emp ); + } t.commit(); s.close(); } |
From: <hib...@li...> - 2006-05-04 11:58:49
|
Author: ste...@jb... Date: 2006-05-04 07:58:42 -0400 (Thu, 04 May 2006) New Revision: 9871 Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java Log: HHH-1413 : multiple bag fetches Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-05-04 11:57:58 UTC (rev 9870) +++ trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-05-04 11:58:42 UTC (rev 9871) @@ -84,6 +84,20 @@ cfg.setProperty( Environment.GENERATE_STATISTICS, "true" ); } + public void testMultipleBagFetchesFail() { + Session s = openSession(); + s.beginTransaction(); + try { + s.createQuery( "from Human h join fetch h.friends f join fetch f.friends fof" ).list(); + fail( "failure expected" ); + } + catch( HibernateException e ) { + assertTrue( "unexpected failure reason : " + e, e.getMessage().indexOf( "multiple bags" ) > 0 ); + } + s.getTransaction().commit(); + s.close(); + } + public void testCollectionJoinsInSubselect() { // HHH-1248 : initially FromElementFactory treated any explicit join // as an implied join so that theta-style joins would always be used. |
From: <hib...@li...> - 2006-05-04 11:58:07
|
Author: ste...@jb... Date: 2006-05-04 07:57:58 -0400 (Thu, 04 May 2006) New Revision: 9870 Modified: trunk/Hibernate3/src/org/hibernate/loader/BasicLoader.java Log: HHH-1413 : multiple bag fetches Modified: trunk/Hibernate3/src/org/hibernate/loader/BasicLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/BasicLoader.java 2006-05-04 03:17:03 UTC (rev 9869) +++ trunk/Hibernate3/src/org/hibernate/loader/BasicLoader.java 2006-05-04 11:57:58 UTC (rev 9870) @@ -4,6 +4,8 @@ import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.type.BagType; +import org.hibernate.HibernateException; /** * Uses the default mapping from property to result set column @@ -22,7 +24,7 @@ public BasicLoader(SessionFactoryImplementor factory) { super(factory); } - + protected final EntityAliases[] getEntityAliases() { return descriptors; } @@ -43,12 +45,16 @@ } CollectionPersister[] collectionPersisters = getCollectionPersisters(); + int bagCount = 0; if ( collectionPersisters != null ) { String[] collectionSuffixes = getCollectionSuffixes(); collectionDescriptors = new CollectionAliases[collectionPersisters.length]; for ( int i = 0; i < collectionPersisters.length; i++ ) { - collectionDescriptors[i] = new GeneratedCollectionAliases( - collectionPersisters[i], + if ( isBag( collectionPersisters[i] ) ) { + bagCount++; + } + collectionDescriptors[i] = new GeneratedCollectionAliases( + collectionPersisters[i], collectionSuffixes[i] ); } @@ -56,8 +62,15 @@ else { collectionDescriptors = null; } + if ( bagCount > 1 ) { + throw new HibernateException( "cannot simultaneously fetch multiple bags" ); + } } - + + private boolean isBag(CollectionPersister collectionPersister) { + return collectionPersister.getCollectionType().getClass().isAssignableFrom( BagType.class ); + } + /** * Utility method that generates 0_, 1_ suffixes. Subclasses don't * necessarily need to use this algorithm, but it is intended that |
From: <hib...@li...> - 2006-05-04 03:17:13
|
Author: epbernard Date: 2006-05-03 23:17:03 -0400 (Wed, 03 May 2006) New Revision: 9869 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/Television.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/VideoSystem.java Log: EJB-101 avoid overriden method call Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java 2006-05-04 02:40:24 UTC (rev 9868) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java 2006-05-04 03:17:03 UTC (rev 9869) @@ -49,6 +49,7 @@ public static Callback[] resolveCallback(XClass beanClass, Class annotation, ReflectionManager reflectionManager) { List<Callback> callbacks = new ArrayList<Callback>(); + List<String> callbacksMethodNames = new ArrayList<String>(); //used to track overriden methods List<Class> orderedListeners = new ArrayList<Class>(); XClass currentClazz = beanClass; boolean stopListeners = false; @@ -75,7 +76,12 @@ if ( ! method.isAccessible() ) { method.setAccessible( true ); } - callbacks.add( 0, callback ); //superclass first + final String methodName = method.getName(); + if ( ! callbacksMethodNames.contains( methodName) ) { + //overriden method, remove the superclass overriden method + callbacks.add( 0, callback ); //superclass first + callbacksMethodNames.add( 0, methodName ); + } } else { throw new PersistenceException( Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java 2006-05-04 02:40:24 UTC (rev 9868) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java 2006-05-04 03:17:03 UTC (rev 9869) @@ -21,8 +21,6 @@ super(); } - ; - public EJB3PersistEventListener(EntityCallbackHandler callbackHandler) { super(); this.callbackHandler = callbackHandler; Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java 2006-05-04 02:40:24 UTC (rev 9868) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java 2006-05-04 03:17:03 UTC (rev 9869) @@ -120,10 +120,10 @@ em.getTransaction().begin(); Television tv = new Television(); em.persist( tv ); - em.flush(); tv.setName( "Myaio" ); tv.init(); em.flush(); + assertEquals( 1, tv.counter ); em.getTransaction().rollback(); assertEquals( 5, tv.communication ); assertTrue( tv.isLast ); Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/Television.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/Television.java 2006-05-04 02:40:24 UTC (rev 9868) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/Television.java 2006-05-04 03:17:03 UTC (rev 9869) @@ -8,6 +8,7 @@ import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PreUpdate; +import javax.persistence.PrePersist; /** * @author Emmanuel Bernard @@ -53,4 +54,11 @@ isLast = true; communication++; } + + @PrePersist + public void prepareEntity() { + //override a super method annotated with the same + // event for it not to be called + counter++; + } } Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/VideoSystem.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/VideoSystem.java 2006-05-04 02:40:24 UTC (rev 9868) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/VideoSystem.java 2006-05-04 03:17:03 UTC (rev 9869) @@ -5,6 +5,7 @@ import javax.persistence.ExcludeSuperclassListeners; import javax.persistence.MappedSuperclass; import javax.persistence.PreUpdate; +import javax.persistence.PrePersist; /** * @author Emmanuel Bernard @@ -13,10 +14,16 @@ @EntityListeners({FirstOneListener.class, IncreaseListener.class}) @MappedSuperclass public class VideoSystem extends CommunicationSystem { + public transient int counter = 0; @PreUpdate public void increase() { isFirst = false; isLast = false; communication++; } + + @PrePersist + public void prepareEntity() { + counter++; + } } |
From: <hib...@li...> - 2006-05-04 02:40:29
|
Author: epbernard Date: 2006-05-03 22:40:24 -0400 (Wed, 03 May 2006) New Revision: 9868 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/exception/ExceptionTest.java Log: EJB-9 use the ENFE delegate rmeove useless logs Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-04 02:16:10 UTC (rev 9867) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-04 02:40:24 UTC (rev 9868) @@ -23,6 +23,7 @@ import javax.persistence.EntityManagerFactory; import javax.persistence.MappedSuperclass; import javax.persistence.PersistenceException; +import javax.persistence.EntityNotFoundException; import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; @@ -35,6 +36,8 @@ import org.hibernate.Interceptor; import org.hibernate.MappingException; import org.hibernate.SessionFactory; +import org.hibernate.ObjectNotFoundException; +import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; @@ -81,6 +84,14 @@ public Ejb3Configuration() { settingsFactory = new InjectionSettingsFactory(); cfg = new AnnotationConfiguration( settingsFactory ); + cfg.setEntityNotFoundDelegate( new EntityNotFoundDelegate() { + + public void handleEntityNotFound(String entityName, Serializable id) { + //keep the original ONFE for the sake of consistency in the way we handle Hibernate exceptions + Exception e = new ObjectNotFoundException( id, entityName ); + throw new EntityNotFoundException("Unable to find " + entityName + " with id " + id, e); + } + } ); listenerConfigurator = new EventListenerConfigurator( this ); //transactionType = PersistenceUnitTransactionType.JTA; //default as per the spec } Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java 2006-05-04 02:16:10 UTC (rev 9867) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java 2006-05-04 02:40:24 UTC (rev 9868) @@ -102,14 +102,11 @@ while ( currentClazz != null ); //handle default listeners - log.error("default listeners for: " + beanClass.getName() + annotation ); if (! stopDefaultListeners) { - log.error("notstopped" ); List<Class> defaultListeners = (List<Class>) reflectionManager.getDefaults().get( EntityListeners.class ); if (defaultListeners != null) { int defaultListenerSize = defaultListeners.size(); - log.error("defaultlistenerssize" + defaultListenerSize ); for (int i = defaultListenerSize - 1 ; i >= 0 ; i--) { orderedListeners.add( defaultListeners.get(i) ); } Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/exception/ExceptionTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/exception/ExceptionTest.java 2006-05-04 02:16:10 UTC (rev 9867) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/exception/ExceptionTest.java 2006-05-04 02:40:24 UTC (rev 9868) @@ -3,6 +3,7 @@ import javax.persistence.EntityManager; import javax.persistence.OptimisticLockException; +import javax.persistence.EntityNotFoundException; import org.hibernate.ejb.test.TestCase; @@ -44,6 +45,21 @@ } } + public void testEntityNotFoundException() throws Exception { + EntityManager em = factory.createEntityManager( ); + Music music = em.getReference( Music.class, new Integer(-1) ); + try { + music.getName(); + fail("Non existent entity should raise an exception when state is accessed"); + } + catch( EntityNotFoundException e ) { + //success + } + finally { + em.close(); + } + } + public Class[] getAnnotatedClasses() { return new Class[] { Music.class |
From: <hib...@li...> - 2006-05-04 02:16:15
|
Author: epbernard Date: 2006-05-03 22:16:10 -0400 (Wed, 03 May 2006) New Revision: 9867 Modified: trunk/Hibernate3/src/org/hibernate/cfg/Mappings.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ExtendedMappings.java Log: ANN-337 Modified: trunk/Hibernate3/src/org/hibernate/cfg/Mappings.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/Mappings.java 2006-05-03 23:20:46 UTC (rev 9866) +++ trunk/Hibernate3/src/org/hibernate/cfg/Mappings.java 2006-05-04 02:16:10 UTC (rev 9867) @@ -40,7 +40,7 @@ private final Map tables; private final Map queries; private final Map sqlqueries; - private final Map resultSetMappings; + protected final Map resultSetMappings; private final Map typeDefs; private final List secondPasses; private final Map imports; Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ExtendedMappings.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ExtendedMappings.java 2006-05-03 23:20:46 UTC (rev 9866) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ExtendedMappings.java 2006-05-04 02:16:10 UTC (rev 9867) @@ -235,12 +235,13 @@ } public void addDefaultResultSetMapping(ResultSetMappingDefinition definition) { - if ( ! defaultSqlResulSetMappingNames.contains( definition.getName() ) - && super.getResultSetMapping( definition.getName() ) != null ) { - //FIXME overrides without clashing when resultSetMAppings visibility allows it + final String name = definition.getName(); + if ( ! defaultSqlResulSetMappingNames.contains( name ) + && super.getResultSetMapping( name ) != null ) { + resultSetMappings.remove( name ); } super.addResultSetMapping(definition); - defaultSqlResulSetMappingNames.add( definition.getName() ); + defaultSqlResulSetMappingNames.add( name ); } @Override |
From: <hib...@li...> - 2006-05-03 23:20:47
|
Author: epbernard Date: 2006-05-03 19:20:46 -0400 (Wed, 03 May 2006) New Revision: 9866 Added: tags/entitymanager_last_src_compliant_with_core3.2.0.CR1/HibernateExt/ Log: Last source code compliant with core 3.2.0.CR1 Copied: tags/entitymanager_last_src_compliant_with_core3.2.0.CR1/HibernateExt (from rev 9865, trunk/HibernateExt) |
From: <hib...@li...> - 2006-05-03 23:19:38
|
Author: epbernard Date: 2006-05-03 19:19:34 -0400 (Wed, 03 May 2006) New Revision: 9865 Added: tags/entitymanager_last_src_compliant_with_core3.2.0.CR1/ Log: Last source compliant with core 3.2.0.CR1 |
From: <hib...@li...> - 2006-05-03 23:14:17
|
Author: epbernard Date: 2006-05-03 19:14:10 -0400 (Wed, 03 May 2006) New Revision: 9864 Added: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/IncrementListener.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Money.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/OtherIncrementListener.java Modified: trunk/HibernateExt/ejb/build.xml trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml trunk/HibernateExt/ejb/doc/reference/en/modules/listeners.xml trunk/HibernateExt/ejb/lib/hibernate-annotations.jar trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EventListenerConfigurator.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EntityCallbackHandler.java trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/orm.xml trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Mouse.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java Log: EJB-165 entity listeners and default entity listeners Modified: trunk/HibernateExt/ejb/build.xml =================================================================== --- trunk/HibernateExt/ejb/build.xml 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/build.xml 2006-05-03 23:14:10 UTC (rev 9864) @@ -16,7 +16,7 @@ <!-- Name of project and version, used to create filenames --> <property name="Name" value="Hibernate EntityManager"/> <property name="name" value="hibernate-entitymanager"/> - <property name="version" value="3.1.0.Beta8"/> + <property name="version" value="3.1.0.CR1"/> <property name="javadoc.packagenames" value="org.hibernate.ejb.*"/> <property name="jdbc.dir" value="jdbc"/> <property name="copy.test" value="true"/> Modified: trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml =================================================================== --- trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml 2006-05-03 23:14:10 UTC (rev 9864) @@ -85,7 +85,8 @@ <listitem> <para>(attribute) Transaction type used. Either JTA or - RESOURCE_LOCAL (default JTA).</para> + RESOURCE_LOCAL (default to JTA in a JavaEE environment and to + RESOURCE_LOCAL in a JavaSE environment).</para> </listitem> </varlistentry> @@ -359,11 +360,12 @@ <row> <entry>hibernate.ejb.discard_pc_on_close</entry> - <entry>If true, the persistence context will be discarded (think clear() - when the method is called. Otherwise the persistence context will stay alive - till the transaction completion: all objects will remain managed, and any - change will be sy,chronized with the database (default to false, - ie wait the transaction completion)</entry> + <entry>If true, the persistence context will be discarded (think + clear() when the method is called. Otherwise the persistence + context will stay alive till the transaction completion: all + objects will remain managed, and any change will be sy,chronized + with the database (default to false, ie wait the transaction + completion)</entry> </row> </tbody> </tgroup> Modified: trunk/HibernateExt/ejb/doc/reference/en/modules/listeners.xml =================================================================== --- trunk/HibernateExt/ejb/doc/reference/en/modules/listeners.xml 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/doc/reference/en/modules/listeners.xml 2006-05-03 23:14:10 UTC (rev 9864) @@ -188,4 +188,52 @@ <literal>@ExcludeSuperclassListeners</literal>, all superclasses <literal>@EntityListeners</literal> will then be ignored.</para> </section> + + <section> + <title>XML definition</title> + + <para>The EJB3 specification allows annotation overriding through EJB3 + deployment descriptor. There is also an additional feature that can be + useful: default event listeners.</para> + + <programlisting><?xml version="1.0" encoding="UTF-8"?> + +<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd" + version="1.0" + > + <persistence-unit-metadata> + <persistence-unit-defaults> + <entity-listeners> + <entity-listener class="org.hibernate.ejb.test.pack.defaultpar.IncrementListener"> + <pre-persist method-name="increment"/> + </entity-listener> + </entity-listeners> + </persistence-unit-defaults> + </persistence-unit-metadata> + <package>org.hibernate.ejb.test.pack.defaultpar</package> + <entity class="ApplicationServer"> + <entity-listeners> + <entity-listener class="OtherIncrementListener"> + <pre-persist method-name="increment"/> + </entity-listener> + </entity-listeners> + + + <pre-persist method-name="calculate"/> + </entity> +</entity-mappings></programlisting> + + <para>You can override entity listeners on a given entity. An entity + listener correspond to a given class and one or several event fire a given + method call. You can also define event on the entity itself to describe + the callbacks.</para> + + <para>Last but not least, you can define some default entity listeners + that will apply first on the entity listener stack of all the mapped + entities of a given persistence unit. If you don't want an entity to + inherit the default listeners, you can use @ExcludeDefaultListeners (or + <exclude-default-listeners/>).</para> + </section> </chapter> \ No newline at end of file Modified: trunk/HibernateExt/ejb/lib/hibernate-annotations.jar =================================================================== (Binary files differ) Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -655,7 +655,6 @@ //initialize listeners listenerConfigurator.setProperties( preparedProperties ); - listenerConfigurator.setValidator( true ); listenerConfigurator.configure(); //some spec compliance checking Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EventListenerConfigurator.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EventListenerConfigurator.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EventListenerConfigurator.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -13,6 +13,7 @@ import java.util.StringTokenizer; import org.hibernate.HibernateException; +import org.hibernate.MappingException; import org.hibernate.ejb.event.CallbackHandlerConsumer; import org.hibernate.ejb.event.EJB3AutoFlushEventListener; import org.hibernate.ejb.event.EJB3DeleteEventListener; @@ -45,6 +46,7 @@ import org.hibernate.event.PreUpdateEventListener; import org.hibernate.event.SaveOrUpdateEventListener; import org.hibernate.mapping.PersistentClass; +import org.hibernate.reflection.ReflectionManager; import org.hibernate.secure.JACCPreDeleteEventListener; import org.hibernate.secure.JACCPreInsertEventListener; import org.hibernate.secure.JACCPreLoadEventListener; @@ -58,11 +60,8 @@ public class EventListenerConfigurator { private static final Object[] READER_METHOD_ARGS = new Object[0]; - private Properties properties; private Ejb3Configuration configuration; - private boolean isValidator; private boolean isSecurity; - private String jaccContextID; public EventListenerConfigurator(Ejb3Configuration configuration) { this.configuration = configuration; @@ -127,18 +126,10 @@ ); } - public void setValidator(boolean validator) { - isValidator = validator; - } - public void setProperties(Properties properties) { - this.properties = properties; if ( properties.containsKey( HibernatePersistence.JACC_ENABLED ) ) { isSecurity = true; } - if ( properties.containsKey( HibernatePersistence.JACC_CONTEXT_ID ) ) { - jaccContextID = properties.getProperty( HibernatePersistence.JACC_CONTEXT_ID ); - } //override events if needed Enumeration<?> enumeration = properties.propertyNames(); while ( enumeration.hasMoreElements() ) { @@ -162,9 +153,18 @@ EntityCallbackHandler callbackHandler = new EntityCallbackHandler(); configuration.buildMappings(); //needed to get all the classes Iterator classes = configuration.getClassMappings(); + ReflectionManager reflectionManager = configuration.getHibernateConfiguration().getReflectionManager(); while ( classes.hasNext() ) { PersistentClass clazz = (PersistentClass) classes.next(); - callbackHandler.add( clazz.getMappedClass() ); + if ( clazz.getClassName() != null ) { + //we can have non java class persisted by hibernate + try { + callbackHandler.add( reflectionManager.classForName( clazz.getClassName(), this.getClass() ), reflectionManager ); + } + catch (ClassNotFoundException e) { + throw new MappingException("entity class not found: " + clazz.getNodeName(), e); + } + } } EventListeners listenerConfig = configuration.getEventListeners(); Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/CallbackResolver.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -17,7 +17,14 @@ import javax.persistence.ExcludeSuperclassListeners; import javax.persistence.MappedSuperclass; import javax.persistence.PersistenceException; +import javax.persistence.ExcludeDefaultListeners; +import org.hibernate.reflection.XClass; +import org.hibernate.reflection.XMethod; +import org.hibernate.reflection.ReflectionManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** * @author <a href="mailto:kab...@jb...">Kabir Khan</a> * @version $Revision$ @@ -35,101 +42,38 @@ } } } + private static Log log = LogFactory.getLog( CallbackResolver.class ); private CallbackResolver() { } - public static Callback resolveCallback(Class beanClass, Class annotation, List<Class> listeners) throws Exception { - Callback callback = null; - Method[] methods = beanClass.getDeclaredMethods(); - - for ( int i = 0; i < methods.length ; i++ ) { - if ( methods[i].getAnnotation( annotation ) != null ) { - if ( callback == null ) { - callback = new BeanCallback( methods[i] ); - Class returnType = methods[i].getReturnType(); - Class[] args = methods[i].getParameterTypes(); - if ( returnType != Void.TYPE || args.length != 0 ) { - throw new RuntimeException( - "Callback methods annotated on the bean class must return void and take no arguments: " + annotation - .getName() + " - " + methods[i] - ); - } - if ( ! methods[i].isAccessible() ) { - methods[i].setAccessible( true ); - } - } - else { - throw new RuntimeException( - "You can only annotate one callback method with " - + annotation.getName() + " in bean class: " + beanClass.getName() - ); - } - } - } - - for ( Class listener : listeners ) { - if ( listener != null ) { - try { - methods = listener.getDeclaredMethods(); - for ( int i = 0; i < methods.length ; i++ ) { - if ( methods[i].getAnnotation( annotation ) != null ) { - if ( callback == null ) { - callback = new ListenerCallback( methods[i], listener.newInstance() ); - Class returnType = methods[i].getReturnType(); - Class[] args = methods[i].getParameterTypes(); - if ( returnType != Void.TYPE || args.length != 1 ) { - throw new RuntimeException( - "Callback methods annotated in a listener bean class must return void and take one argument: " + annotation - .getName() + " - " + methods[i] - ); - } - if ( ! methods[i].isAccessible() ) { - methods[i].setAccessible( true ); - } - } - else { - throw new RuntimeException( - "You can only annotate one callback method with " - + annotation.getName() + " in bean class: " + beanClass.getName() + " and callback listener: " - + listener.getName() - ); - } - } - } - } - catch (Exception e) { - throw new RuntimeException( e.getCause() ); - } - } - } - return callback; - } - - public static Callback[] resolveCallback(Class beanClass, Class annotation) { + public static Callback[] resolveCallback(XClass beanClass, Class annotation, ReflectionManager reflectionManager) { List<Callback> callbacks = new ArrayList<Callback>(); List<Class> orderedListeners = new ArrayList<Class>(); - Class currentClazz = beanClass; + XClass currentClazz = beanClass; boolean stopListeners = false; - //TODO add exclude default listeners + boolean stopDefaultListeners = false; do { //FIXME exclude overriden callback methods Callback callback = null; - Method[] methods = currentClazz.getDeclaredMethods(); - for ( int i = 0; i < methods.length ; i++ ) { - if ( methods[i].getAnnotation( annotation ) != null ) { + List<XMethod> methods = currentClazz.getDeclaredMethods(); + final int size = methods.size(); + for ( int i = 0; i < size ; i++ ) { + final XMethod xMethod = methods.get( i ); + if ( xMethod.isAnnotationPresent( annotation ) ) { if ( callback == null ) { - callback = new BeanCallback( methods[i] ); - Class returnType = methods[i].getReturnType(); - Class[] args = methods[i].getParameterTypes(); + Method method = reflectionManager.toMethod( xMethod ); + callback = new BeanCallback( method ); + Class returnType = method.getReturnType(); + Class[] args = method.getParameterTypes(); if ( returnType != Void.TYPE || args.length != 0 ) { throw new RuntimeException( "Callback methods annotated on the bean class must return void and take no arguments: " + annotation - .getName() + " - " + methods[i] + .getName() + " - " + xMethod ); } - if ( ! methods[i].isAccessible() ) { - methods[i].setAccessible( true ); + if ( ! method.isAccessible() ) { + method.setAccessible( true ); } callbacks.add( 0, callback ); //superclass first } @@ -144,6 +88,7 @@ if ( !stopListeners ) { getListeners( currentClazz, orderedListeners ); stopListeners = currentClazz.isAnnotationPresent( ExcludeSuperclassListeners.class ); + stopDefaultListeners = currentClazz.isAnnotationPresent( ExcludeDefaultListeners.class ); } do { @@ -156,15 +101,34 @@ } while ( currentClazz != null ); + //handle default listeners + log.error("default listeners for: " + beanClass.getName() + annotation ); + if (! stopDefaultListeners) { + log.error("notstopped" ); + List<Class> defaultListeners = (List<Class>) reflectionManager.getDefaults().get( EntityListeners.class ); + + if (defaultListeners != null) { + int defaultListenerSize = defaultListeners.size(); + log.error("defaultlistenerssize" + defaultListenerSize ); + for (int i = defaultListenerSize - 1 ; i >= 0 ; i--) { + orderedListeners.add( defaultListeners.get(i) ); + } + } + } + for ( Class listener : orderedListeners ) { Callback callback = null; if ( listener != null ) { - Method[] methods = listener.getDeclaredMethods(); - for ( int i = 0; i < methods.length ; i++ ) { - if ( methods[i].getAnnotation( annotation ) != null ) { + XClass xListener = reflectionManager.toXClass( listener ); + List<XMethod> methods = xListener.getDeclaredMethods(); + final int size = methods.size(); + for ( int i = 0; i < size ; i++ ) { + final XMethod xMethod = methods.get(i); + final Method method = reflectionManager.toMethod( xMethod ); + if ( xMethod.isAnnotationPresent( annotation ) ) { if ( callback == null ) { try { - callback = new ListenerCallback( methods[i], listener.newInstance() ); + callback = new ListenerCallback( method, listener.newInstance() ); } catch (IllegalAccessException e) { throw new PersistenceException( @@ -178,16 +142,16 @@ + " as a listener of beanClass", e ); } - Class returnType = methods[i].getReturnType(); - Class[] args = methods[i].getParameterTypes(); + Class returnType = method.getReturnType(); + Class[] args = method.getParameterTypes(); if ( returnType != Void.TYPE || args.length != 1 ) { throw new PersistenceException( "Callback methods annotated in a listener bean class must return void and take one argument: " + annotation - .getName() + " - " + methods[i] + .getName() + " - " + method ); } - if ( ! methods[i].isAccessible() ) { - methods[i].setAccessible( true ); + if ( ! method.isAccessible() ) { + method.setAccessible( true ); } callbacks.add( 0, callback ); // listeners first } @@ -205,7 +169,7 @@ return callbacks.toArray( new Callback[ callbacks.size() ] ); } - private static void getListeners(Class currentClazz, List<Class> orderedListeners) { + private static void getListeners(XClass currentClazz, List<Class> orderedListeners) { EntityListeners entityListeners = (EntityListeners) currentClazz.getAnnotation( EntityListeners.class ); if ( entityListeners != null ) { Class[] classes = entityListeners.value(); Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EntityCallbackHandler.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EntityCallbackHandler.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/event/EntityCallbackHandler.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -16,6 +16,9 @@ import javax.persistence.PreRemove; import javax.persistence.PreUpdate; +import org.hibernate.reflection.XClass; +import org.hibernate.reflection.ReflectionManager; + /** * Keep track of all lifecycle callbacks and listeners for a given persistence unit * @@ -30,14 +33,14 @@ private HashMap<Class, Callback[]> postUpdates = new HashMap<Class, Callback[]>(); private HashMap<Class, Callback[]> postLoads = new HashMap<Class, Callback[]>(); - public void add(Class entity) { - addCallback( entity, preCreates, PrePersist.class ); - addCallback( entity, postCreates, PostPersist.class ); - addCallback( entity, preRemoves, PreRemove.class ); - addCallback( entity, postRemoves, PostRemove.class ); - addCallback( entity, preUpdates, PreUpdate.class ); - addCallback( entity, postUpdates, PostUpdate.class ); - addCallback( entity, postLoads, PostLoad.class ); + public void add(XClass entity, ReflectionManager reflectionManager) { + addCallback( entity, preCreates, PrePersist.class, reflectionManager ); + addCallback( entity, postCreates, PostPersist.class, reflectionManager ); + addCallback( entity, preRemoves, PreRemove.class, reflectionManager ); + addCallback( entity, postRemoves, PostRemove.class, reflectionManager ); + addCallback( entity, preUpdates, PreUpdate.class, reflectionManager ); + addCallback( entity, postUpdates, PostUpdate.class, reflectionManager ); + addCallback( entity, postLoads, PostLoad.class, reflectionManager ); } public boolean preCreate(Object bean) { @@ -82,9 +85,11 @@ } - private void addCallback(Class entity, HashMap<Class, Callback[]> map, Class annotation) { + private void addCallback( + XClass entity, HashMap<Class, Callback[]> map, Class annotation, ReflectionManager reflectionManager + ) { Callback[] callbacks = null; - callbacks = CallbackResolver.resolveCallback( entity, annotation ); - map.put( entity, callbacks ); + callbacks = CallbackResolver.resolveCallback( entity, annotation, reflectionManager ); + map.put( reflectionManager.toClass( entity ), callbacks ); } } Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/PackagedEntityManagerTest.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -13,6 +13,9 @@ import org.hibernate.ejb.test.pack.defaultpar.Lighter; import org.hibernate.ejb.test.pack.defaultpar.Mouse; import org.hibernate.ejb.test.pack.defaultpar.Version; +import org.hibernate.ejb.test.pack.defaultpar.IncrementListener; +import org.hibernate.ejb.test.pack.defaultpar.OtherIncrementListener; +import org.hibernate.ejb.test.pack.defaultpar.Money; import org.hibernate.ejb.test.pack.excludehbmpar.Caipirinha; import org.hibernate.ejb.test.pack.explodedpar.Carpet; import org.hibernate.ejb.test.pack.explodedpar.Elephant; @@ -65,6 +68,42 @@ emf.close(); } + public void testListenersDefaultPar() throws Exception { + IncrementListener.reset(); + OtherIncrementListener.reset(); + EntityManagerFactory emf = Persistence.createEntityManagerFactory( "defaultpar", new HashMap() ); + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + ApplicationServer as = new ApplicationServer(); + as.setName( "JBoss AS" ); + Version v = new Version(); + v.setMajor( 4 ); + v.setMinor( 0 ); + v.setMicro( 3 ); + as.setVersion( v ); + em.persist( as ); + em.flush(); + assertEquals( "Failure in default listeners", 1, IncrementListener.getIncrement() ); + assertEquals( "Failuer in XML overriden listeners", 1, OtherIncrementListener.getIncrement() ); + + Mouse mouse = new Mouse(); + mouse.setName( "mickey" ); + em.persist( mouse ); + em.flush(); + assertEquals( "Failure in @ExcludeDefaultListeners", 1, IncrementListener.getIncrement() ); + assertEquals( 1, OtherIncrementListener.getIncrement() ); + + Money money = new Money(); + em.persist( money ); + em.flush(); + assertEquals( "Failure in @ExcludeDefaultListeners", 2, IncrementListener.getIncrement() ); + assertEquals( 1, OtherIncrementListener.getIncrement() ); + + em.getTransaction().rollback(); + em.close(); + emf.close(); + } + public void testExplodedPar() throws Exception { EntityManagerFactory emf = Persistence.createEntityManagerFactory( "explodedpar", new HashMap() ); EntityManager em = emf.createEntityManager(); @@ -303,4 +342,4 @@ super( arg0 ); } -} +} \ No newline at end of file Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/callbacks/CallbacksTest.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -78,7 +78,8 @@ assertNotNull( id ); } - public void testListenerAnnotation() throws Exception { + //Not a test since the spec did not make the proper change on listeners + public void listenerAnnotation() throws Exception { EntityManager em = factory.createEntityManager(); Translation tl = new Translation(); em.getTransaction().begin(); Added: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/IncrementListener.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/IncrementListener.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/IncrementListener.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -0,0 +1,24 @@ +//$Id: $ +package org.hibernate.ejb.test.pack.defaultpar; + +import javax.persistence.PrePersist; + +/** + * @author Emmanuel Bernard + */ +public class IncrementListener { + private static int increment; + + public static int getIncrement() { + return increment; + } + + public static void reset() { + increment = 0; + } + + @PrePersist + public void increment(Object entity) { + increment++; + } +} Added: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Money.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Money.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Money.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -0,0 +1,24 @@ +//$Id: $ +package org.hibernate.ejb.test.pack.defaultpar; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class Money { + private Integer id; + + @Id @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + +} Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Mouse.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Mouse.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/Mouse.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -1,9 +1,12 @@ //$Id$ package org.hibernate.ejb.test.pack.defaultpar; +import javax.persistence.ExcludeDefaultListeners; + /** * @author Emmanuel Bernard */ +@ExcludeDefaultListeners public class Mouse { private Integer id; private String name; Added: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/OtherIncrementListener.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/OtherIncrementListener.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/pack/defaultpar/OtherIncrementListener.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -0,0 +1,21 @@ +//$Id: $ +package org.hibernate.ejb.test.pack.defaultpar; + +/** + * @author Emmanuel Bernard + */ +public class OtherIncrementListener { + private static int increment; + + public static int getIncrement() { + return OtherIncrementListener.increment; + } + + public static void reset() { + increment = 0; + } + + public void increment(Object entity) { + OtherIncrementListener.increment++; + } +} Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/packaging/JarVisitorTest.java 2006-05-03 23:14:10 UTC (rev 9864) @@ -50,7 +50,7 @@ JarVisitor jarVisitor = new InputStreamZippedJarVisitor( new URL( jarFileName ), filters ); assertEquals( "defaultpar", jarVisitor.getUnqualifiedJarName() ); Set entries = jarVisitor.getMatchingEntries()[1]; - assertEquals( 2, entries.size() ); + assertEquals( 3, entries.size() ); JarVisitor.Entry entry = new JarVisitor.Entry( ApplicationServer.class.getName(), null ); assertTrue( entries.contains( entry ) ); entry = new JarVisitor.Entry( org.hibernate.ejb.test.pack.defaultpar.Version.class.getName(), null ); Modified: trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/orm.xml =================================================================== --- trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/orm.xml 2006-05-03 23:13:22 UTC (rev 9863) +++ trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/orm.xml 2006-05-03 23:14:10 UTC (rev 9864) @@ -5,6 +5,15 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd" version="1.0" > + <persistence-unit-metadata> + <persistence-unit-defaults> + <entity-listeners> + <entity-listener class="org.hibernate.ejb.test.pack.defaultpar.IncrementListener"> + <pre-persist method-name="increment"/> + </entity-listener> + </entity-listeners> + </persistence-unit-defaults> + </persistence-unit-metadata> <package>org.hibernate.ejb.test.pack.defaultpar</package> <entity class="Lighter" access="FIELD" metadata-complete="true"> <attributes> @@ -14,4 +23,11 @@ <basic name="power"></basic> </attributes> </entity> + <entity class="ApplicationServer"> + <entity-listeners> + <entity-listener class="OtherIncrementListener"> + <pre-persist method-name="increment"/> + </entity-listener> + </entity-listeners> + </entity> </entity-mappings> \ No newline at end of file |
Author: epbernard Date: 2006-05-03 19:13:22 -0400 (Wed, 03 May 2006) New Revision: 9863 Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/LogListener.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/OtherLogListener.java Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/ReflectionManager.java trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXFactory.java trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/Administration.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/EJB3OverridenAnnotationReaderTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/orm.xml Log: EJB-165 entity listeners and default entity listeners Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationConfiguration.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -45,8 +45,8 @@ import org.xml.sax.SAXException; /** - * Add JSR 175 configuration capability. - * For now, only programmatic configuration is available. + * Similar to the {@link Configuration} object but handles EJB3 and Hibernate + * specific annotations as a metadata facility * * @author Emmanuel Bernard */ @@ -584,4 +584,9 @@ } } } + + //not a public API + public ReflectionManager getReflectionManager() { + return reflectionManager; + } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/ReflectionManager.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/ReflectionManager.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/ReflectionManager.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -1,6 +1,7 @@ package org.hibernate.reflection; import java.util.Map; +import java.lang.reflect.Method; /** * The entry point to the reflection layer (a.k.a. the X* layer). @@ -17,6 +18,8 @@ public Class toClass(XClass xClazz); + public Method toMethod(XMethod method); + public <T> XClass classForName(String name, Class<T> caller) throws ClassNotFoundException; public XPackage packageForName(String packageName) throws ClassNotFoundException; Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -69,6 +69,14 @@ import javax.persistence.Transient; import javax.persistence.UniqueConstraint; import javax.persistence.Version; +import javax.persistence.EntityListeners; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; +import javax.persistence.PostRemove; +import javax.persistence.PostPersist; +import javax.persistence.PostUpdate; +import javax.persistence.PostLoad; import org.dom4j.Attribute; import org.dom4j.Element; @@ -153,7 +161,14 @@ annotationToXml.put( JoinColumns.class, "join-column" ); annotationToXml.put( MapKey.class, "map-key" ); annotationToXml.put( OrderBy.class, "order-by" ); - + annotationToXml.put( EntityListeners.class, "entity-listeners" ); + annotationToXml.put( PrePersist.class, "pre-persist" ); + annotationToXml.put( PreRemove.class, "pre-remove" ); + annotationToXml.put( PreUpdate.class, "pre-update" ); + annotationToXml.put( PostPersist.class, "post-persist" ); + annotationToXml.put( PostRemove.class, "post-remove" ); + annotationToXml.put( PostUpdate.class, "post-update" ); + annotationToXml.put( PostLoad.class, "post-load" ); } private XMLContext xmlContext; @@ -305,6 +320,8 @@ if ( current != null ) annotationList.add( current ); current = getAssociationOverrides( tree, defaults ); if ( current != null ) annotationList.add( current ); + current = getEntityListeners( tree, defaults ); + if ( current != null ) annotationList.add( current ); this.annotations = annotationList.toArray( new Annotation[ annotationList.size() ] ); } else if ( className != null && propertyName != null ) { @@ -337,6 +354,7 @@ getAssociation( OneToMany.class, annotationList, defaults ); getAssociation( ManyToMany.class, annotationList, defaults ); } + processEventAnnotations(annotationList, defaults); this.annotations = annotationList.toArray( new Annotation[ annotationList.size() ] ); } else { @@ -345,6 +363,96 @@ } } + private void processEventAnnotations(List<Annotation> annotationList, XMLContext.Default defaults) { + boolean eventElement = false; + for ( Element element : elementsForProperty ) { + String elementName = element.getName(); + if ( "pre-persist".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PrePersist.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + else if ( "pre-remove".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PreRemove.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + else if ( "pre-update".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PreUpdate.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + else if ( "post-persist".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PostPersist.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + else if ( "post-remove".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PostRemove.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + else if ( "post-update".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PostUpdate.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + else if ( "post-load".equals( elementName ) ) { + AnnotationDescriptor ad = new AnnotationDescriptor( PostLoad.class ); + annotationList.add( AnnotationFactory.create( ad ) ); + eventElement = true; + } + } + if ( ! eventElement && defaults.canUseJavaAnnotations() ) { + Annotation ann = super.getAnnotation(PrePersist.class); + if (ann != null) annotationList.add( ann ); + ann = super.getAnnotation(PreRemove.class); + if (ann != null) annotationList.add( ann ); + ann = super.getAnnotation(PreUpdate.class); + if (ann != null) annotationList.add( ann ); + ann = super.getAnnotation(PostPersist.class); + if (ann != null) annotationList.add( ann ); + ann = super.getAnnotation(PostRemove.class); + if (ann != null) annotationList.add( ann ); + ann = super.getAnnotation(PostUpdate.class); + if (ann != null) annotationList.add( ann ); + ann = super.getAnnotation(PostLoad.class); + if (ann != null) annotationList.add( ann ); + } + } + + private EntityListeners getEntityListeners(Element tree, XMLContext.Default defaults) { + Element element = tree != null ? tree.element( "entity-listeners" ) : null; + if ( element != null) { + List<Class> entityListenerClasses = new ArrayList<Class>(); + for (Element subelement : (List<Element>) element.elements( "entity-listener" ) ) { + String className = subelement.attributeValue( "class" ); + try { + entityListenerClasses.add( + ReflectHelper.classForName( + XMLContext.buildSafeClassName( className, defaults ), + this.getClass() + ) + ); + } + catch (ClassNotFoundException e) { + throw new AnnotationException( + "Unable to find " + element.getPath() + ".class: " + className, e + ); + } + } + AnnotationDescriptor ad = new AnnotationDescriptor( EntityListeners.class ); + ad.setValue( "value", entityListenerClasses.toArray( new Class[ entityListenerClasses.size() ] ) ); + return AnnotationFactory.create( ad ); + } + else if ( defaults.canUseJavaAnnotations() ) { + return super.getAnnotation( EntityListeners.class ); + } + else { + return null; + } + } + private JoinTable overridesDefaultsInJoinTable(XMLContext.Default defaults) { //no element but might have some default or some annotation final Class<JoinTable> annotationType = JoinTable.class; @@ -765,6 +873,7 @@ private void preCalculateElementsForProperty(Element tree) { elementsForProperty = new ArrayList<Element>(); Element element = tree != null ? tree.element( "attributes" ) : null; + //put entity.attributes elements if ( element != null ) { for ( Element subelement : (List<Element>) element.elements() ) { if ( propertyName.equals( subelement.attributeValue( "name" ) ) ) { @@ -772,6 +881,14 @@ } } } + //add pre-* etc from entity and pure entity listener classes + if (tree != null) { + for ( Element subelement : (List<Element>) tree.elements() ) { + if ( propertyName.equals( subelement.attributeValue( "method-name" ) ) ) { + elementsForProperty.add( subelement ); + } + } + } } private void getId(List<Annotation> annotationList, XMLContext.Default defaults) { Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXFactory.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXFactory.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXFactory.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -1,6 +1,7 @@ package org.hibernate.reflection.java; import java.lang.reflect.Member; +import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; @@ -12,6 +13,7 @@ import javax.persistence.SequenceGenerator; import javax.persistence.SqlResultSetMapping; import javax.persistence.TableGenerator; +import javax.persistence.EntityListeners; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -88,6 +90,13 @@ return (Class) ( (JavaXClass) xClazz ).toAnnotatedElement(); } + public Method toMethod(XMethod xMethod) { + if ( ! ( xMethod instanceof JavaXMethod ) ) { + throw new IllegalArgumentException( "XMethod not coming from this ReflectionManager implementation" ); + } + return (Method) ( (JavaXAnnotatedElement) xMethod ).toAnnotatedElement(); + } + public XClass classForName(String name, Class caller) throws ClassNotFoundException { return toXClass( ReflectHelper.classForName( name, caller ) ); } @@ -100,7 +109,18 @@ if (defaults == null) { defaults = new HashMap(); XMLContext.Default xmlDefaults = xmlContext.getDefault( null ); + List<Class> entityListeners = new ArrayList<Class>(); + for ( String className : xmlContext.getDefaultEntityListeners() ) { + try { + entityListeners.add( ReflectHelper.classForName( className, this.getClass() ) ); + } + catch (ClassNotFoundException e) { + throw new IllegalStateException( "Default entity listener class not found: " + className ); + } + } + defaults.put( EntityListeners.class, entityListeners ); for( Element element : xmlContext.getAllDocuments() ) { + List<Element> elements = element.elements( "sequence-generator" ); List<SequenceGenerator> sequenceGenerators = (List<SequenceGenerator>) defaults.get(SequenceGenerator.class); if (sequenceGenerators == null) { Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/xml/XMLContext.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -21,11 +21,13 @@ private Map<String, Element> classOverriding = new HashMap<String, Element>(); private Map<String, Default> defaultsOverriding = new HashMap<String, Default>(); private List<Element> defaultElements = new ArrayList<Element>(); + private List<String> defaultEntityListeners = new ArrayList<String>(); /** * Add a document and return the list of added classes names */ public List<String> addDocument(Document doc) { + List<String> addedClasses = new ArrayList<String>(); Element root = doc.getRootElement(); //global defaults Element metadata = root.element( "persistence-unit-metadata" ); @@ -47,11 +49,11 @@ globalDefaults.setAccess( unitElement != null ? unitElement.getTextTrim() : null ); unitElement = defaultElement.element( "cascade-persist" ); globalDefaults.setCascadePersist( unitElement != null ? Boolean.TRUE : null ); - //TODO entity listeners + defaultEntityListeners.addAll( addEntityListenerClasses( defaultElement, null, addedClasses ) ); } } else { - log.warn( "Found more than one <persistence-unit-metadata>, ignored" ); + log.warn( "Found more than one <persistence-unit-metadata>, subsequent ignored" ); } } @@ -68,7 +70,6 @@ entityMappingDefault.setAccess( unitElement != null ? unitElement.getTextTrim() : null ); defaultElements.add(root); - List<String> addedClasses = new ArrayList<String>(); List<Element> entities = (List<Element>) root.elements( "entity" ); addClass( entities, packageName, entityMappingDefault, addedClasses ); @@ -100,9 +101,39 @@ defaultsOverriding.put( className, localDefault ); log.debug( "Adding XML overriding information for " + className ); + addEntityListenerClasses( element, packageName, addedClasses ); } } + private List<String> addEntityListenerClasses(Element element, String packageName, List<String> addedClasses) { + List<String> localAddedClasses = new ArrayList<String>(); + Element listeners = element.element( "entity-listeners" ); + if (listeners != null) { + List<Element> elements = (List<Element>) listeners.elements( "entity-listener" ); + for ( Element listener : elements ) { + String listenerClassName = buildSafeClassName( listener.attributeValue( "class" ), packageName ); + if ( classOverriding.containsKey( listenerClassName ) ) { + //maybe switch it to warn? + if ( "entity-listener".equals( classOverriding.get( listenerClassName).getName() ) ) { + log.info( + "entity-listener duplication, first event definition will be used: " + + listenerClassName + ); + continue; + } + else { + throw new IllegalStateException( "Duplicate XML entry for " + listenerClassName ); + } + } + localAddedClasses.add( listenerClassName ); + classOverriding.put( listenerClassName, listener ); + } + } + log.debug( "Adding XML overriding information for listener: " + listeners ); + addedClasses.addAll( localAddedClasses ); + return localAddedClasses; + } + private static String buildSafeClassName(String className, String defaultPackageName) { if ( className.indexOf( '.' ) < 0 && defaultPackageName != null ) { className = StringHelper.qualify( defaultPackageName, className ); @@ -205,6 +236,9 @@ if ( globalDefault.getCascadePersist() != null ) cascadePersist = globalDefault.getCascadePersist(); } } + } + public List<String> getDefaultEntityListeners() { + return defaultEntityListeners; } } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/Administration.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/Administration.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/Administration.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -7,6 +7,7 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinColumns; import javax.persistence.OneToOne; +import javax.persistence.PostLoad; import javax.persistence.SecondaryTable; import javax.persistence.Table; @@ -68,4 +69,9 @@ public void setLastname(String lastname) { this.lastname = lastname; } + + @PostLoad + public void calculate() { + //... + } } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/EJB3OverridenAnnotationReaderTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/EJB3OverridenAnnotationReaderTest.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/EJB3OverridenAnnotationReaderTest.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -51,6 +51,10 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; import javax.persistence.Version; +import javax.persistence.PrePersist; +import javax.persistence.EntityListeners; +import javax.persistence.PostLoad; +import javax.persistence.PostPersist; import junit.framework.TestCase; import org.dom4j.DocumentException; @@ -361,6 +365,31 @@ assertEquals( "maxSpeed", reader.getAnnotation( OrderBy.class ).value() ); } + public void testEntityListeners() throws Exception { + XMLContext context = buildContext( "org/hibernate/test/reflection/java/xml/orm.xml" ); + + Method method = Administration.class.getDeclaredMethod( "calculate" ); + EJB3OverridenAnnotationReader reader = new EJB3OverridenAnnotationReader( method, context ); + assertTrue( reader.isAnnotationPresent( PrePersist.class ) ); + + reader = new EJB3OverridenAnnotationReader( Administration.class, context ); + assertTrue( reader.isAnnotationPresent( EntityListeners.class ) ); + assertEquals( 1, reader.getAnnotation( EntityListeners.class ).value().length ); + assertEquals( LogListener.class, reader.getAnnotation( EntityListeners.class ).value()[0] ); + + method = LogListener.class.getDeclaredMethod( "noLog", Object.class ); + reader = new EJB3OverridenAnnotationReader( method, context ); + assertTrue( reader.isAnnotationPresent( PostLoad.class ) ); + + method = LogListener.class.getDeclaredMethod( "log", Object.class ); + reader = new EJB3OverridenAnnotationReader( method, context ); + assertTrue( reader.isAnnotationPresent( PrePersist.class ) ); + assertFalse( reader.isAnnotationPresent( PostPersist.class ) ); + + assertEquals( 1, context.getDefaultEntityListeners().size() ); + assertEquals( OtherLogListener.class.getName(), context.getDefaultEntityListeners().get(0) ); + } + private XMLContext buildContext(String ormfile) throws SAXException, DocumentException, IOException { XMLHelper xmlHelper = new XMLHelper(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/LogListener.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/LogListener.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/LogListener.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -0,0 +1,26 @@ +//$Id: $ +package org.hibernate.test.reflection.java.xml; + +import javax.persistence.PrePersist; +import javax.persistence.PostPersist; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author Emmanuel Bernard + */ +public class LogListener { + Log log = LogFactory.getLog( LogListener.class ); + + @PrePersist + @PostPersist + public void log(Object entity) { + log.debug( "Logging entity " + entity.getClass().getName() + " with hashCode: " + entity.hashCode() ); + } + + + public void noLog(Object entity) { + log.debug( "NoLogging entity " + entity.getClass().getName() + " with hashCode: " + entity.hashCode() ); + } +} Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/OtherLogListener.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/OtherLogListener.java 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/OtherLogListener.java 2006-05-03 23:13:22 UTC (rev 9863) @@ -0,0 +1,26 @@ +//$Id: $ +package org.hibernate.test.reflection.java.xml; + +import javax.persistence.PrePersist; +import javax.persistence.PostPersist; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author Emmanuel Bernard + */ +public class OtherLogListener { + Log log = LogFactory.getLog( OtherLogListener.class ); + + @PrePersist + @PostPersist + public void log(Object entity) { + log.debug( "Logging entity " + entity.getClass().getName() + " with hashCode: " + entity.hashCode() ); + } + + + public void noLog(Object entity) { + log.debug( "NoLogging entity " + entity.getClass().getName() + " with hashCode: " + entity.hashCode() ); + } +} Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/orm.xml =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/orm.xml 2006-05-03 14:44:42 UTC (rev 9862) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/reflection/java/xml/orm.xml 2006-05-03 23:13:22 UTC (rev 9863) @@ -10,6 +10,11 @@ <schema>myschema</schema> <catalog>mycatalog</catalog> <cascade-persist/> + <entity-listeners> + <entity-listener class="org.hibernate.test.reflection.java.xml.OtherLogListener"> + <post-update method-name="log"/> + </entity-listener> + </entity-listeners> </persistence-unit-defaults> </persistence-unit-metadata> <package>org.hibernate.test.reflection.java.xml</package> @@ -28,6 +33,13 @@ </secondary-table> <sequence-generator name="seqhilo" sequence-name="seqhilo"/> <table-generator name="table" table="tablehilo"/> + <entity-listeners> + <entity-listener class="LogListener"> + <pre-persist method-name="log"/> + <post-load method-name="noLog"/> + </entity-listener> + </entity-listeners> + <pre-persist method-name="calculate"/> <attributes> <id name="id"> <column name="fld_id"/> @@ -75,6 +87,12 @@ </sql-result-set-mapping> <exclude-default-listeners/> <exclude-superclass-listeners/> + <entity-listeners> + <entity-listener class="LogListener"> + <pre-persist method-name="log"/> + <post-load method-name="noLog"/> + </entity-listener> + </entity-listeners> <attributes> <embedded name="playerASSN"/> </attributes> |
From: <hib...@li...> - 2006-05-03 14:44:50
|
Author: epbernard Date: 2006-05-03 10:44:42 -0400 (Wed, 03 May 2006) New Revision: 9862 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java Log: EJB-159 RESOURCE_LOCAL is the default in JavaSE Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-03 14:10:52 UTC (rev 9861) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-03 14:44:42 UTC (rev 9862) @@ -754,6 +754,10 @@ //override the new defaults with the user defined ones if ( properties != null ) preparedProperties.putAll( properties ); + if (transactionType == null) { + //if it has not been set, the user use a programmatic way + transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL; + } defineTransactionType( preparedProperties.getProperty( HibernatePersistence.TRANSACTION_TYPE ), workingVars |
From: <hib...@li...> - 2006-05-03 14:10:57
|
Author: epbernard Date: 2006-05-03 10:10:52 -0400 (Wed, 03 May 2006) New Revision: 9861 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/persistence.xml Log: EJB-159 RESOURCE_LOCAL is the default in JavaSE Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-03 00:03:03 UTC (rev 9860) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-05-03 14:10:52 UTC (rev 9861) @@ -82,7 +82,7 @@ settingsFactory = new InjectionSettingsFactory(); cfg = new AnnotationConfiguration( settingsFactory ); listenerConfigurator = new EventListenerConfigurator( this ); - transactionType = PersistenceUnitTransactionType.JTA; //default as per the spec + //transactionType = PersistenceUnitTransactionType.JTA; //default as per the spec } /** @@ -272,7 +272,11 @@ // defineTransactionType( overridenTxType, info.getPersistenceUnitName() ); // } // else { - defineTransactionType( info.getTransactionType(), workingVars ); + + PersistenceUnitTransactionType transactionType = info.getTransactionType(); + //in JavaEE the default is JTA + transactionType = transactionType != null ? transactionType : PersistenceUnitTransactionType.JTA; + defineTransactionType( transactionType, workingVars ); // } //workingVars.put( HibernatePersistence.TRANSACTION_TYPE, transactionType ); boolean[] detectArtifact = getDetectedArtifacts( info.getProperties(), null ); @@ -335,9 +339,10 @@ private void defineTransactionType(Object overridenTxType, Map workingVars) { if ( overridenTxType == null ) { - if ( transactionType == null ) { - transactionType = PersistenceUnitTransactionType.JTA; //this is the default value - } +// if ( transactionType == null ) { +// transactionType = PersistenceUnitTransactionType.JTA; //this is the default value +// } + //nothing to override } else if ( overridenTxType instanceof String ) { transactionType = PersistenceXmlLoader.getTransactionType( (String) overridenTxType ); Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java 2006-05-03 00:03:03 UTC (rev 9860) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/PersistenceXmlLoader.java 2006-05-03 14:10:52 UTC (rev 9861) @@ -86,7 +86,7 @@ metadata.setProvider( provider ); } String transactionType = (String) overrides.get( HibernatePersistence.TRANSACTION_TYPE ); - if ( transactionType != null ) { + if ( StringHelper.isNotEmpty( transactionType ) ) { metadata.setTransactionType( PersistenceXmlLoader.getTransactionType( transactionType ) ); } String dataSource = (String) overrides.get( HibernatePersistence.JTA_DATASOURCE ); @@ -115,7 +115,10 @@ log.trace( "Persistent Unit name from persistence.xml: " + puName ); metadata.setName( puName ); } - metadata.setTransactionType( getTransactionType( top.getAttribute( "transaction-type" ) ) ); + PersistenceUnitTransactionType transactionType = getTransactionType( top.getAttribute( "transaction-type" ) ); + //parsing a persistence.xml means we are in a JavaSE environment + transactionType = transactionType != null ? transactionType : PersistenceUnitTransactionType.RESOURCE_LOCAL; + metadata.setTransactionType( transactionType ); NodeList children = top.getChildNodes(); for ( int i = 0; i < children.getLength() ; i++ ) { if ( children.item( i ).getNodeType() == Node.ELEMENT_NODE ) { @@ -173,7 +176,7 @@ public static PersistenceUnitTransactionType getTransactionType(String elementContent) { if ( StringHelper.isEmpty( elementContent ) ) { - return PersistenceUnitTransactionType.JTA; + return null; //PersistenceUnitTransactionType.JTA; } else if ( elementContent.equalsIgnoreCase( "JTA" ) ) { return PersistenceUnitTransactionType.JTA; Modified: trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/persistence.xml =================================================================== --- trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/persistence.xml 2006-05-03 00:03:03 UTC (rev 9860) +++ trunk/HibernateExt/ejb/src/test-resources/defaultpar/META-INF/persistence.xml 2006-05-03 14:10:52 UTC (rev 9861) @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> - <persistence-unit name="defaultpar" transaction-type="RESOURCE_LOCAL"> + <persistence-unit name="defaultpar"> <class>org.hibernate.ejb.test.pack.defaultpar.Lighter</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> |
From: <hib...@li...> - 2006-05-03 00:03:06
|
Author: epbernard Date: 2006-05-02 20:03:03 -0400 (Tue, 02 May 2006) New Revision: 9860 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java Log: EJB-168 Check that the transaction is not marked for rollback before considering it as in progress. This will avoid any Synchronization registration issue Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java 2006-05-02 23:33:15 UTC (rev 9859) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableCMTTransaction.java 2006-05-03 00:03:03 UTC (rev 9860) @@ -2,6 +2,7 @@ package org.hibernate.ejb.transaction; import javax.transaction.SystemException; +import javax.transaction.Transaction; import org.hibernate.HibernateException; import org.hibernate.TransactionException; @@ -41,9 +42,10 @@ private boolean isTransactionInProgress() { try { + Transaction transaction = transactionContext.getFactory().getTransactionManager().getTransaction(); return JTAHelper.isTransactionInProgress( - transactionContext.getFactory().getTransactionManager().getTransaction() - ); + transaction + ) && ! JTAHelper.isRollback( transaction.getStatus() ); } catch (SystemException se) { throw new TransactionException( "Unable to check transaction status", se ); |