HHH-3760 : document EntityNameResolver
git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_3@15931 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
e8f38ede57
commit
098586a4f0
|
@ -551,11 +551,157 @@ public class CustomMapTuplizerImpl
|
|||
return new CustomMap();
|
||||
}
|
||||
}
|
||||
}]]></programlisting>m
|
||||
}]]></programlisting>
|
||||
|
||||
|
||||
</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>
|
||||
|
||||
<!--<sect1 id="persistent-classes-extensions">
|
||||
<title>Extensions</title>
|
||||
<para>
|
||||
|
|
Loading…
Reference in New Issue