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>
|