simply remove @Tuplizer completely

This commit is contained in:
Gavin King 2021-02-25 14:44:26 +01:00
parent 20e855acf1
commit d193a9409a
28 changed files with 3 additions and 1119 deletions

View File

@ -492,74 +492,6 @@ include::{extrasdir}/entity/entity-proxy-persist-mapping.sql[]
As you can see in the associated SQL snippet, Hibernate issues no SQL SELECT query since the proxy can be As you can see in the associated SQL snippet, Hibernate issues no SQL SELECT query since the proxy can be
constructed without needing to fetch the actual entity POJO. constructed without needing to fetch the actual entity POJO.
[[entity-tuplizer]]
==== Dynamic entity proxies using the @Tuplizer annotation
It is possible to map your entities as dynamic proxies using
the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Tuplizer.html[`@Tuplizer`] annotation.
In the following entity mapping, both the embeddable and the entity are mapped as interfaces, not POJOs.
[[entity-tuplizer-entity-mapping]]
.Dynamic entity proxy mapping
====
[source,java]
----
include::{sourcedir-proxy}/tuplizer/Cuisine.java[tag=entity-tuplizer-entity-mapping,indent=0]
----
[source,java]
----
include::{sourcedir-proxy}/tuplizer/Country.java[tag=entity-tuplizer-entity-mapping,indent=0]
----
====
The `@Tuplizer` instructs Hibernate to use the `DynamicEntityTuplizer` and `DynamicEmbeddableTuplizer` to handle
the associated entity and embeddable object types.
Both the `Cuisine` entity and the `Country` embeddable types are going to be instantiated as Java dynamic proxies,
as you can see in the following `DynamicInstantiator` example:
[[entity-tuplizer-instantiator]]
.Instantiating entities and embeddables as dynamic proxies
====
[source,java]
----
include::{sourcedir-proxy}/tuplizer/DynamicEntityTuplizer.java[tag=entity-tuplizer-instantiator,indent=0]
----
[source,java]
----
include::{sourcedir-proxy}/tuplizer/DynamicEmbeddableTuplizer.java[tag=entity-tuplizer-instantiator,indent=0]
----
[source,java]
----
include::{sourcedir-proxy}/tuplizer/DynamicInstantiator.java[tag=entity-tuplizer-instantiator,indent=0]
----
[source,java]
----
include::{sourcedir-proxy}/tuplizer/ProxyHelper.java[tag=entity-tuplizer-instantiator,indent=0]
----
[source,java]
----
include::{sourcedir-proxy}/tuplizer/DataProxyHandler.java[tag=entity-tuplizer-instantiator,indent=0]
----
====
With the `DynamicInstantiator` in place, we can work with the dynamic proxy entities just like with POJO entities.
[[entity-tuplizer-dynamic-proxy-example]]
.Persisting entities and embeddables as dynamic proxies
====
[source,java]
----
include::{sourcedir-proxy}/tuplizer/TuplizerTest.java[tag=entity-tuplizer-dynamic-proxy-example,indent=0]
----
====
[[entity-persister]] [[entity-persister]]
==== Define a custom entity persister ==== Define a custom entity persister

View File

@ -1,26 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import javax.persistence.Column;
import javax.persistence.Embeddable;
/**
* @author Emmanuel Bernard
*/
//tag::entity-tuplizer-entity-mapping[]
@Embeddable
public interface Country {
@Column(name = "CountryName")
String getName();
void setName(String name);
}
//end::entity-tuplizer-entity-mapping[]

View File

@ -1,36 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.Tuplizer;
/**
* @author Emmanuel Bernard
*/
//tag::entity-tuplizer-entity-mapping[]
@Entity
@Tuplizer(impl = DynamicEntityTuplizer.class)
public interface Cuisine {
@Id
@GeneratedValue
Long getId();
void setId(Long id);
String getName();
void setName(String name);
@Tuplizer(impl = DynamicEmbeddableTuplizer.class)
Country getCountry();
void setCountry(Country country);
}
//end::entity-tuplizer-entity-mapping[]

View File

@ -1,61 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* A simple {@link InvocationHandler} to act as the handler for our generated
* {@link java.lang.reflect.Proxy}-based entity instances.
* <p/>
* This is a trivial impl which simply keeps the property values into
* a Map.
*
* @author <a href="mailto:steve@hibernate.org">Steve Ebersole </a>
*/
//tag::entity-tuplizer-instantiator[]
public final class DataProxyHandler implements InvocationHandler {
private String entityName;
private Map<String, Object> data = new HashMap<>();
public DataProxyHandler(String entityName, Object 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 this.hashCode();
}
return null;
}
public String getEntityName() {
return entityName;
}
}
//end::entity-tuplizer-instantiator[]

View File

@ -1,32 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import org.hibernate.mapping.Component;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.component.PojoComponentTuplizer;
/**
* @author Emmanuel Bernard
*/
//tag::entity-tuplizer-instantiator[]
public class DynamicEmbeddableTuplizer
extends PojoComponentTuplizer {
public DynamicEmbeddableTuplizer(Component embeddable) {
super( embeddable );
}
protected Instantiator buildInstantiator(Component embeddable) {
return new DynamicInstantiator(
embeddable.getComponentClassName()
);
}
}
//end::entity-tuplizer-instantiator[]

View File

@ -1,49 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.userguide.proxy.tuplizer;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.PojoEntityTuplizer;
/**
* @author Emmanuel Bernard
*/
//tag::entity-tuplizer-instantiator[]
public class DynamicEntityTuplizer extends PojoEntityTuplizer {
public DynamicEntityTuplizer(
EntityMetamodel entityMetamodel,
PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
@Override
protected Instantiator buildInstantiator(
EntityMetamodel entityMetamodel,
PersistentClass persistentClass) {
return new DynamicInstantiator(
persistentClass.getClassName()
);
}
@Override
protected ProxyFactory buildProxyFactory(
PersistentClass persistentClass,
Getter idGetter,
Setter idSetter) {
return super.buildProxyFactory(
persistentClass, idGetter,
idSetter
);
}
}
//end::entity-tuplizer-instantiator[]

View File

@ -1,54 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.tuple.Instantiator;
/**
* @author Emmanuel Bernard
*/
//tag::entity-tuplizer-instantiator[]
public class DynamicInstantiator
implements Instantiator {
private final Class targetClass;
public DynamicInstantiator(String targetClassName) {
try {
this.targetClass = Class.forName( targetClassName );
}
catch (ClassNotFoundException e) {
throw new HibernateException( e );
}
}
public Object instantiate(Object id) {
return ProxyHelper.newProxy( targetClass, id );
}
public Object instantiate() {
return instantiate( null );
}
public boolean isInstance(Object object) {
try {
return targetClass.isInstance( object );
}
catch( Throwable t ) {
throw new HibernateException(
"could not get handle to entity as interface : " + t
);
}
}
}
//end::entity-tuplizer-instantiator[]

View File

@ -1,31 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import org.hibernate.EmptyInterceptor;
/**
* @author Emmanuel Bernard
*/
public class EntityNameInterceptor extends EmptyInterceptor {
/**
* The callback from Hibernate to determine the entity name given
* a presumed entity instance.
*
* @param object The presumed entity instance.
* @return The entity name (pointing to the proper entity mapping).
*/
public String getEntityName(Object object) {
String entityName = ProxyHelper.extractEntityName( object );
if ( entityName == null ) {
entityName = super.getEntityName( object );
}
return entityName;
}
}

View File

@ -1,48 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.userguide.proxy.tuplizer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author Emmanuel Bernard
*/
//tag::entity-tuplizer-instantiator[]
public class ProxyHelper {
public static <T> T newProxy(Class<T> targetClass, Object id) {
return ( T ) Proxy.newProxyInstance(
targetClass.getClassLoader(),
new Class[] {
targetClass
},
new DataProxyHandler(
targetClass.getName(),
id
)
);
}
public static String extractEntityName(Object object) {
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;
}
}
//end::entity-tuplizer-instantiator[]

View File

@ -1,57 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.userguide.proxy.tuplizer;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernateSessionBuilder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Emmanuel Bernard
*/
public class TuplizerTest extends BaseCoreFunctionalTestCase {
@Test
public void testEntityTuplizer() throws Exception {
//tag::entity-tuplizer-dynamic-proxy-example[]
Cuisine _cuisine = doInHibernateSessionBuilder(
() -> sessionFactory()
.withOptions()
.interceptor( new EntityNameInterceptor() ),
session -> {
Cuisine cuisine = ProxyHelper.newProxy( Cuisine.class, null );
cuisine.setName( "Française" );
Country country = ProxyHelper.newProxy( Country.class, null );
country.setName( "France" );
cuisine.setCountry( country );
session.persist( cuisine );
return cuisine;
} );
doInHibernateSessionBuilder(
() -> sessionFactory()
.withOptions()
.interceptor( new EntityNameInterceptor() ),
session -> {
Cuisine cuisine = session.get( Cuisine.class, _cuisine.getId() );
assertEquals( "Française", cuisine.getName() );
assertEquals( "France", cuisine.getCountry().getName() );
} );
//end::entity-tuplizer-dynamic-proxy-example[]
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { Cuisine.class };
}
}

View File

@ -1,33 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Define a tuplizer for an entity or a component.
*
* @author Emmanuel Bernard
*
* @deprecated since {@link org.hibernate.tuple.Tuplizer} is deprecated
*/
@java.lang.annotation.Target( {TYPE, FIELD, METHOD} )
@Retention( RUNTIME )
@Repeatable(Tuplizers.class)
@Deprecated
public @interface Tuplizer {
/**
* Tuplizer implementation.
*/
Class<? extends org.hibernate.tuple.Tuplizer> impl();
}

View File

@ -1,28 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Grouping of tuplizers.
*
* @author Emmanuel Bernard
*
* @deprecated since {@link org.hibernate.tuple.Tuplizer} is deprecated
*/
@java.lang.annotation.Target( {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} )
@Retention( RetentionPolicy.RUNTIME )
@Deprecated
public @interface Tuplizers {
/**
* The grouping of tuplizers.
*/
Tuplizer[] value();
}

View File

@ -121,8 +121,6 @@ import org.hibernate.annotations.SortNatural;
import org.hibernate.annotations.Source; import org.hibernate.annotations.Source;
import org.hibernate.annotations.SqlTypeRegistration; import org.hibernate.annotations.SqlTypeRegistration;
import org.hibernate.annotations.SqlTypeRegistrations; import org.hibernate.annotations.SqlTypeRegistrations;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.TypeDefs;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
@ -2713,7 +2711,6 @@ public final class AnnotationBinder {
} }
} }
XProperty property = inferredData.getProperty(); XProperty property = inferredData.getProperty();
setupComponentTuplizer( property, comp );
PropertyBinder binder = new PropertyBinder(); PropertyBinder binder = new PropertyBinder();
binder.setDeclaringClass(inferredData.getDeclaringClass()); binder.setDeclaringClass(inferredData.getDeclaringClass());
binder.setName( inferredData.getPropertyName() ); binder.setName( inferredData.getPropertyName() );
@ -2987,7 +2984,6 @@ public final class AnnotationBinder {
} }
//tuplizers //tuplizers
XProperty property = inferredData.getProperty(); XProperty property = inferredData.getProperty();
setupComponentTuplizer( property, componentId );
} }
else { else {
//TODO I think this branch is never used. Remove. //TODO I think this branch is never used. Remove.
@ -3070,21 +3066,6 @@ public final class AnnotationBinder {
return baseClassElements.get( 0 ); return baseClassElements.get( 0 );
} }
private static void setupComponentTuplizer(XProperty property, Component component) {
if ( property == null ) {
return;
}
if ( property.isAnnotationPresent( Tuplizers.class ) ) {
for ( Tuplizer tuplizer : property.getAnnotation( Tuplizers.class ).value() ) {
component.addTuplizer( EntityMode.POJO, tuplizer.impl().getName() );
}
}
if ( property.isAnnotationPresent( Tuplizer.class ) ) {
Tuplizer tuplizer = property.getAnnotation( Tuplizer.class );
component.addTuplizer( EntityMode.POJO, tuplizer.impl().getName() );
}
}
private static void bindManyToOne( private static void bindManyToOne(
String cascadeStrategy, String cascadeStrategy,
Ejb3JoinColumn[] columns, Ejb3JoinColumn[] columns,

View File

@ -27,7 +27,6 @@ import javax.persistence.SharedCacheMode;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache; import org.hibernate.annotations.Cache;
@ -54,8 +53,6 @@ import org.hibernate.annotations.SelectBeforeUpdate;
import org.hibernate.annotations.Subselect; import org.hibernate.annotations.Subselect;
import org.hibernate.annotations.Synchronize; import org.hibernate.annotations.Synchronize;
import org.hibernate.annotations.Tables; import org.hibernate.annotations.Tables;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XAnnotatedElement;
@ -91,6 +88,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.mapping.TableOwner; import org.hibernate.mapping.TableOwner;
import org.hibernate.mapping.Value; import org.hibernate.mapping.Value;
import org.hibernate.tuple.Tuplizer;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.cfg.BinderHelper.toAliasEntityMap; import static org.hibernate.cfg.BinderHelper.toAliasEntityMap;
@ -365,17 +363,6 @@ public class EntityBinder {
this.subselect = subselect.value(); this.subselect = subselect.value();
} }
//tuplizers
if ( annotatedClass.isAnnotationPresent( Tuplizers.class ) ) {
for (Tuplizer tuplizer : annotatedClass.getAnnotation( Tuplizers.class ).value()) {
persistentClass.addTuplizer( EntityMode.POJO, tuplizer.impl().getName() );
}
}
if ( annotatedClass.isAnnotationPresent( Tuplizer.class ) ) {
Tuplizer tuplizer = annotatedClass.getAnnotation( Tuplizer.class );
persistentClass.addTuplizer( EntityMode.POJO, tuplizer.impl().getName() );
}
for ( Filter filter : filters ) { for ( Filter filter : filters ) {
String filterName = filter.name(); String filterName = filter.name();
String cond = filter.condition(); String cond = filter.condition();

View File

@ -1,21 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import javax.persistence.Column;
import javax.persistence.Embeddable;
/**
* @author Emmanuel Bernard
*/
@Embeddable
public interface Country {
@Column(name = "CountryName")
public String getName();
public void setName(String name);
}

View File

@ -1,35 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.Tuplizer;
/**
* @author Emmanuel Bernard
*/
@Entity
@Tuplizer(impl = DynamicEntityTuplizer.class)
public interface Cuisine {
@Id
@GeneratedValue
public Long getId();
public void setId(Long id);
public String getName();
public void setName(String name);
@Tuplizer(impl = DynamicComponentTuplizer.class)
public Country getCountry();
public void setCountry(Country country);
}

View File

@ -1,59 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* A simple {@link java.lang.reflect.InvocationHandler} to act as the handler for our generated
* {@link java.lang.reflect.Proxy}-based entity instances.
* <p/>
* This is a trivial impl which simply keeps the property values into
* a Map.
*
* @author <a href="mailto:steve@hibernate.org">Steve Ebersole </a>
*/
public final class DataProxyHandler implements InvocationHandler {
private String entityName;
private HashMap data = new HashMap();
public DataProxyHandler(String entityName, Object 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;
}
}

View File

@ -1,26 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import org.hibernate.mapping.Component;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.component.PojoComponentTuplizer;
/**
* @author Emmanuel Bernard
*/
public class DynamicComponentTuplizer extends PojoComponentTuplizer {
public DynamicComponentTuplizer(Component component) {
super( component );
}
protected Instantiator buildInstantiator(Component component) {
return new DynamicInstantiator( component.getComponentClassName() ); //To change body of overridden methods use File | Settings | File Templates.
}
}

View File

@ -1,39 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.tuplizer;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.PojoEntityTuplizer;
/**
* @author Emmanuel Bernard
*/
public class DynamicEntityTuplizer extends PojoEntityTuplizer {
public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
return new DynamicInstantiator( persistentClass.getEntityName() );
}
@Override
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.
//
// Here we simply use the default...
return super.buildProxyFactory( persistentClass, idGetter, idSetter );
}
}

View File

@ -1,62 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.tuple.Instantiator;
/**
* @author Emmanuel Bernard
*/
public class DynamicInstantiator implements Instantiator {
private final String entityName;
public DynamicInstantiator(String entityName) {
this.entityName = entityName;
}
public Object instantiate(Object id) {
if ( Cuisine.class.getName().equals( entityName ) ) {
return ProxyHelper.newCuisineProxy( id );
}
if ( Country.class.getName().equals( entityName ) ) {
return ProxyHelper.newCountryProxy( id );
}
else {
throw new IllegalArgumentException( "unknown entity for instantiation [" + entityName + "]" );
}
}
public Object instantiate() {
return instantiate( null );
}
public boolean isInstance(Object object) {
String resolvedEntityName = null;
if ( Proxy.isProxyClass( object.getClass() ) ) {
InvocationHandler handler = Proxy.getInvocationHandler( object );
if ( DataProxyHandler.class.isAssignableFrom( handler.getClass() ) ) {
DataProxyHandler myHandler = ( DataProxyHandler ) handler;
resolvedEntityName = myHandler.getEntityName();
}
}
try {
return ReflectHelper.classForName( entityName ).isInstance( object );
}
catch( Throwable t ) {
throw new HibernateException( "could not get handle to entity-name as interface : " + t );
}
// return entityName.equals( resolvedEntityName );
}
}

View File

@ -1,31 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import org.hibernate.EmptyInterceptor;
/**
* @author Emmanuel Bernard
*/
public class EntityNameInterceptor extends EmptyInterceptor {
/**
* The callback from Hibernate to determine the entity name given
* a presumed entity instance.
*
* @param object The presumed entity instance.
* @return The entity name (pointing to the proper entity mapping).
*/
public String getEntityName(Object object) {
String entityName = ProxyHelper.extractEntityName( object );
if ( entityName == null ) {
entityName = super.getEntityName( object );
}
return entityName;
}
}

View File

@ -1,56 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id$
package org.hibernate.test.annotations.tuplizer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author Emmanuel Bernard
*/
public class ProxyHelper {
public static Country newPersonProxy() {
return newCountryProxy( null );
}
public static Country newCountryProxy(Object id) {
return ( Country ) Proxy.newProxyInstance(
Country.class.getClassLoader(),
new Class[] {Country.class},
new DataProxyHandler( Country.class.getName(), id )
);
}
public static Cuisine newCustomerProxy() {
return newCuisineProxy( null );
}
public static Cuisine newCuisineProxy(Object id) {
return ( Cuisine ) Proxy.newProxyInstance(
Cuisine.class.getClassLoader(),
new Class[] {Cuisine.class},
new DataProxyHandler( Cuisine.class.getName(), id )
);
}
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;
}
}

View File

@ -1,45 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.tuplizer;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Emmanuel Bernard
*/
public class TuplizerTest extends BaseCoreFunctionalTestCase {
@Test
public void testEntityTuplizer() throws Exception {
Cuisine cuisine = ProxyHelper.newCuisineProxy( null );
cuisine.setName( "Francaise" );
Country country = ProxyHelper.newCountryProxy( null );
country.setName( "France" );
cuisine.setCountry( country );
Session s = openSession( new EntityNameInterceptor() );
s.getTransaction().begin();
s.persist( cuisine );
s.flush();
s.clear();
cuisine = (Cuisine) s.get(Cuisine.class, cuisine.getId() );
assertNotNull( cuisine );
assertEquals( "Francaise", cuisine.getName() );
assertEquals( "France", country.getName() );
s.getTransaction().rollback();
s.close();
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { Cuisine.class };
}
}

View File

@ -1,60 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.tuplizer.bytebuddysubclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.tuple.Instantiator;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.matcher.ElementMatchers;
import static org.hibernate.bytecode.spi.ClassLoadingStrategyHelper.resolveClassLoadingStrategy;
/**
* @author Florian Bien
*/
public class MyEntityInstantiator implements Instantiator {
private final PersistentClass persistentClass;
public MyEntityInstantiator(PersistentClass persistentClass) {
this.persistentClass = persistentClass;
}
@Override
public Object instantiate(Object id) {
return instantiate();
}
@Override
public Object instantiate() {
return createInstance( persistentClass.getMappedClass() );
}
public static <E> E createInstance(Class<E> entityClass) {
Class<? extends E> loaded = new ByteBuddy()
.subclass( entityClass )
.method( ElementMatchers.named( "toString" ) )
.intercept( FixedValue.value( "transformed" ) )
.make()
// we use our internal helper to get a class loading strategy suitable for the JDK used
.load( entityClass.getClassLoader(), resolveClassLoadingStrategy( entityClass ) )
.getLoaded();
try {
return loaded.newInstance();
}
catch (Exception e) {
throw new RuntimeException( "Unable to create new instance of " + entityClass.getSimpleName(), e );
}
}
@Override
public boolean isInstance(Object object) {
return true;
}
}

View File

@ -1,55 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.tuplizer.bytebuddysubclass;
import org.hibernate.EntityNameResolver;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.PojoEntityTuplizer;
/**
* @author Florian Bien
*/
public class MyTuplizer extends PojoEntityTuplizer {
public MyTuplizer(
EntityMetamodel entityMetamodel,
PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
public EntityNameResolver[] getEntityNameResolvers() {
return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
}
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
return new MyEntityInstantiator( persistentClass );
}
public static class MyEntityNameResolver implements EntityNameResolver {
public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver();
public String resolveEntityName(Object entity) {
if ( entity.getClass().getName().contains( "$ByteBuddy$" ) ) {
return entity.getClass().getSuperclass().getName();
}
else {
return entity.getClass().getName();
}
}
public boolean equals(Object obj) {
return getClass().equals( obj.getClass() );
}
public int hashCode() {
return getClass().hashCode();
}
}
}

View File

@ -1,60 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.tuplizer.bytebuddysubclass;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Florian Bien
*/
public class TuplizerInstantiatesByteBuddySubclassTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { SimpleEntity.class };
}
@Test
public void hhh11655Test() throws Exception {
Session session = openSession();
session.beginTransaction();
SimpleEntity simpleEntityNonProxy = new SimpleEntity();
Assert.assertFalse( session.contains( simpleEntityNonProxy ) );
SimpleEntity simpleEntity = MyEntityInstantiator.createInstance( SimpleEntity.class );
Assert.assertFalse( session.contains( simpleEntity ) );
session.persist( simpleEntity );
Assert.assertTrue( session.contains( simpleEntity ) );
session.getTransaction().rollback();
session.close();
}
@Entity(name = "SimpleEntity")
@Tuplizer(impl = MyTuplizer.class)
public static class SimpleEntity {
protected SimpleEntity() {
}
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -19,13 +19,8 @@ import org.hibernate.EntityMode;
import org.hibernate.EntityNameResolver; import org.hibernate.EntityNameResolver;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.SessionFactoryBuilder; import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
@ -186,8 +181,7 @@ public class LazyToOnesNoProxyFactoryWithSubclassesStatefulTest extends BaseNonC
@Entity(name = "Animal") @Entity(name = "Animal")
@Table(name = "Animal") @Table(name = "Animal")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Tuplizer(impl=NoProxyFactoryPojoEntityTuplizer.class) public static abstract class Animal {
public static abstract class Animal {
@Id @Id
private String name; private String name;

View File

@ -19,13 +19,8 @@ import org.hibernate.EntityMode;
import org.hibernate.EntityNameResolver; import org.hibernate.EntityNameResolver;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.SessionFactoryBuilder; import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
@ -187,8 +182,7 @@ public class LazyToOnesNoProxyFactoryWithSubclassesStatelessTest extends BaseNon
@Entity(name = "Animal") @Entity(name = "Animal")
@Table(name = "Animal") @Table(name = "Animal")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Tuplizer(impl=NoProxyFactoryPojoEntityTuplizer.class) public static abstract class Animal {
public static abstract class Animal {
@Id @Id
private String name; private String name;