[hibernate-commits] Hibernate SVN: r15933 - core/branches/Branch_3_2/doc/reference/en/modules.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Feb 10 16:45:05 EST 2009


Author: steve.ebersole at jboss.com
Date: 2009-02-10 16:45:05 -0500 (Tue, 10 Feb 2009)
New Revision: 15933

Modified:
   core/branches/Branch_3_2/doc/reference/en/modules/persistent_classes.xml
Log:
HHH-3760 : document EntityNameResolver

Modified: core/branches/Branch_3_2/doc/reference/en/modules/persistent_classes.xml
===================================================================
--- core/branches/Branch_3_2/doc/reference/en/modules/persistent_classes.xml	2009-02-10 21:44:48 UTC (rev 15932)
+++ core/branches/Branch_3_2/doc/reference/en/modules/persistent_classes.xml	2009-02-10 21:45:05 UTC (rev 15933)
@@ -1,3 +1,5 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+
 <chapter id="persistent-classes" revision="2">
     <title>Persistent Classes</title>
 
@@ -523,6 +525,153 @@
 
     </sect1>
 
+    <sect1 id="persistent-classes-entity-name-resolver" revision="0">
+        <title>EntityNameResolvers</title>
+
+        <para>
+            The <interfacename>org.hibernate.EntityNameResolver</interfacename> interface is a contract for resolving the
+            entity name of a given entity instance.  The interface defines a single method <methodname>resolveEntityName</methodname>
+            which is passed the entity instance and is expected to return the appropriate entity name (null is allowed and
+            would indicate that the resolver does not know how to resolve the entity name of the given entity instance).
+            Generally speaking, an <interfacename>org.hibernate.EntityNameResolver</interfacename> is going to be most
+            useful in the case of dynamic models.  One example might be using proxied interfaces as your domain model.  The
+            hibernate test suite has an example of this exact style of usage under the
+            <package>org.hibernate.test.dynamicentity.tuplizer2</package>.  Here is some of the code from that package
+            for illustration.
+        </para>
+
+        <programlisting>
+/**
+ * A very trivial JDK Proxy InvocationHandler implementation where we proxy an interface as
+ * the domain model and simply store persistent state in an internal Map.  This is an extremely
+ * trivial example meant only for illustration.
+ */
+public final class DataProxyHandler implements InvocationHandler {
+	private String entityName;
+	private HashMap data = new HashMap();
+
+	public DataProxyHandler(String entityName, Serializable id) {
+		this.entityName = entityName;
+		data.put( "Id", id );
+	}
+
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		String methodName = method.getName();
+		if ( methodName.startsWith( "set" ) ) {
+			String propertyName = methodName.substring( 3 );
+			data.put( propertyName, args[0] );
+		}
+		else if ( methodName.startsWith( "get" ) ) {
+			String propertyName = methodName.substring( 3 );
+			return data.get( propertyName );
+		}
+		else if ( "toString".equals( methodName ) ) {
+			return entityName + "#" + data.get( "Id" );
+		}
+		else if ( "hashCode".equals( methodName ) ) {
+			return new Integer( this.hashCode() );
+		}
+		return null;
+	}
+
+	public String getEntityName() {
+		return entityName;
+	}
+
+	public HashMap getData() {
+		return data;
+	}
+}
+
+/**
+ *
+ */
+public class ProxyHelper {
+    public static String extractEntityName(Object object) {
+        // Our custom java.lang.reflect.Proxy instances actually bundle
+        // their appropriate entity name, so we simply extract it from there
+        // if this represents one of our proxies; otherwise, we return null
+        if ( Proxy.isProxyClass( object.getClass() ) ) {
+            InvocationHandler handler = Proxy.getInvocationHandler( object );
+            if ( DataProxyHandler.class.isAssignableFrom( handler.getClass() ) ) {
+                DataProxyHandler myHandler = ( DataProxyHandler ) handler;
+                return myHandler.getEntityName();
+            }
+        }
+        return null;
+    }
+
+    // various other utility methods ....
+
+}
+
+/**
+ * The EntityNameResolver implementation.
+ * IMPL NOTE : An EntityNameResolver really defines a strategy for how entity names should be
+ * resolved.  Since this particular impl can handle resolution for all of our entities we want to
+ * take advantage of the fact that SessionFactoryImpl keeps these in a Set so that we only ever
+ * have one instance registered.  Why?  Well, when it comes time to resolve an entity name,
+ * Hibernate must iterate over all the registered resolvers.  So keeping that number down
+ * helps that process be as speedy as possible.  Hence the equals and hashCode impls
+ */
+public class MyEntityNameResolver implements EntityNameResolver {
+    public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver();
+
+    public String resolveEntityName(Object entity) {
+        return ProxyHelper.extractEntityName( entity );
+    }
+
+    public boolean equals(Object obj) {
+        return getClass().equals( obj.getClass() );
+    }
+
+    public int hashCode() {
+        return getClass().hashCode();
+    }
+}
+
+public class MyEntityTuplizer extends PojoEntityTuplizer {
+	public MyEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
+		super( entityMetamodel, mappedEntity );
+	}
+
+	public EntityNameResolver[] getEntityNameResolvers() {
+		return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
+	}
+
+    public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
+        String entityName = ProxyHelper.extractEntityName( entityInstance );
+        if ( entityName == null ) {
+            entityName = super.determineConcreteSubclassEntityName( entityInstance, factory );
+        }
+        return entityName;
+    }
+
+    ...
+}
+        </programlisting>
+
+        <para>
+            In order to register an <interfacename>org.hibernate.EntityNameResolver</interfacename> users must either:
+            <orderedlist>
+                <listitem>
+                    <para>
+                        Implement a custom <link linkend="persistent-classes-tuplizers">Tuplizer</link>, implementing
+                        the <methodname>getEntityNameResolvers</methodname> method.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        Register it with the <classname>org.hibernate.impl.SessionFactoryImpl</classname> (which is the
+                        implementation class for <interfacename>org.hibernate.SessionFactory</interfacename>) using the
+                        <methodname>registerEntityNameResolver</methodname> method.
+                    </para>
+                </listitem>
+            </orderedlist>
+        </para>
+    </sect1>
+
+
     <para>
         TODO: Document user-extension framework in the property and proxy packages
     </para>




More information about the hibernate-commits mailing list