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
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]]
==== 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.SqlTypeRegistration;
import org.hibernate.annotations.SqlTypeRegistrations;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import org.hibernate.annotations.Where;
@ -2713,7 +2711,6 @@ public final class AnnotationBinder {
}
}
XProperty property = inferredData.getProperty();
setupComponentTuplizer( property, comp );
PropertyBinder binder = new PropertyBinder();
binder.setDeclaringClass(inferredData.getDeclaringClass());
binder.setName( inferredData.getPropertyName() );
@ -2987,7 +2984,6 @@ public final class AnnotationBinder {
}
//tuplizers
XProperty property = inferredData.getProperty();
setupComponentTuplizer( property, componentId );
}
else {
//TODO I think this branch is never used. Remove.
@ -3070,21 +3066,6 @@ public final class AnnotationBinder {
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(
String cascadeStrategy,
Ejb3JoinColumn[] columns,

View File

@ -27,7 +27,6 @@ import javax.persistence.SharedCacheMode;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
@ -54,8 +53,6 @@ import org.hibernate.annotations.SelectBeforeUpdate;
import org.hibernate.annotations.Subselect;
import org.hibernate.annotations.Synchronize;
import org.hibernate.annotations.Tables;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.Where;
import org.hibernate.annotations.common.reflection.ReflectionManager;
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.Value;
import org.hibernate.tuple.Tuplizer;
import org.jboss.logging.Logger;
import static org.hibernate.cfg.BinderHelper.toAliasEntityMap;
@ -365,17 +363,6 @@ public class EntityBinder {
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 ) {
String filterName = filter.name();
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.Hibernate;
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.SessionFactoryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.PersistentClass;
@ -186,8 +181,7 @@ public class LazyToOnesNoProxyFactoryWithSubclassesStatefulTest extends BaseNonC
@Entity(name = "Animal")
@Table(name = "Animal")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Tuplizer(impl=NoProxyFactoryPojoEntityTuplizer.class)
public static abstract class Animal {
public static abstract class Animal {
@Id
private String name;

View File

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