HHH-11173 - Fix text serialization of uninitialized lazy attributes
This commit is contained in:
parent
4dad087b39
commit
4d6cda1548
|
@ -13,8 +13,10 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -288,6 +290,9 @@ public abstract class AbstractStandardBasicType<T>
|
|||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public final String toLoggableString(Object value, SessionFactoryImplementor factory) {
|
||||
if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY || !Hibernate.isInitialized( value ) ) {
|
||||
return "<uninitialized>";
|
||||
}
|
||||
return javaTypeDescriptor.extractLoggableRepresentation( (T) value );
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,12 @@ import java.util.Set;
|
|||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.internal.ForeignKeys;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
|
@ -304,11 +306,14 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
|||
@Override
|
||||
public String toLoggableString(Object value, SessionFactoryImplementor factory) throws HibernateException {
|
||||
//TODO: terrible implementation!
|
||||
return value == null
|
||||
? "null"
|
||||
: factory.getTypeHelper()
|
||||
.entity( HibernateProxyHelper.getClassWithoutInitializingProxy( value ) )
|
||||
.toLoggableString( value, factory );
|
||||
if ( value == null ) {
|
||||
return "null";
|
||||
}
|
||||
if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY || !Hibernate.isInitialized( value ) ) {
|
||||
return "<uninitialized>";
|
||||
}
|
||||
Class valueClass = HibernateProxyHelper.getClassWithoutInitializingProxy( value );
|
||||
return factory.getTypeHelper().entity( valueClass ).toLoggableString( value, factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,7 +14,9 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.collection.internal.PersistentArrayHolder;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -74,7 +76,13 @@ public class ArrayType extends CollectionType {
|
|||
List list = new ArrayList(length);
|
||||
Type elemType = getElementType(factory);
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
list.add( elemType.toLoggableString( Array.get(value, i), factory ) );
|
||||
Object element = Array.get(value, i);
|
||||
if ( element == LazyPropertyInitializer.UNFETCHED_PROPERTY || !Hibernate.isInitialized( element ) ) {
|
||||
list.add( "<uninitialized>" );
|
||||
}
|
||||
else {
|
||||
list.add( elemType.toLoggableString( element, factory ) );
|
||||
}
|
||||
}
|
||||
return list.toString();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.hibernate.EntityMode;
|
|||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.collection.internal.AbstractPersistentCollection;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
|
@ -194,13 +195,7 @@ public abstract class CollectionType extends AbstractType implements Association
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !Hibernate.isInitialized( value ) ) {
|
||||
return "<uninitialized>";
|
||||
}
|
||||
else {
|
||||
return renderLoggableString( value, factory );
|
||||
}
|
||||
return renderLoggableString( value, factory );
|
||||
}
|
||||
|
||||
protected String renderLoggableString(Object value, SessionFactoryImplementor factory) throws HibernateException {
|
||||
|
@ -208,7 +203,13 @@ public abstract class CollectionType extends AbstractType implements Association
|
|||
Type elemType = getElementType( factory );
|
||||
Iterator itr = getElementsIterator( value );
|
||||
while ( itr.hasNext() ) {
|
||||
list.add( elemType.toLoggableString( itr.next(), factory ) );
|
||||
Object element = itr.next();
|
||||
if ( element == LazyPropertyInitializer.UNFETCHED_PROPERTY || !Hibernate.isInitialized( element ) ) {
|
||||
list.add( "<uninitialized>" );
|
||||
}
|
||||
else {
|
||||
list.add( elemType.toLoggableString( element, factory ) );
|
||||
}
|
||||
}
|
||||
return list.toString();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.FetchMode;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -472,7 +473,12 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
Map<String, String> result = new HashMap<>();
|
||||
Object[] values = getPropertyValues( value, entityMode );
|
||||
for ( int i = 0; i < propertyTypes.length; i++ ) {
|
||||
result.put( propertyNames[i], propertyTypes[i].toLoggableString( values[i], factory ) );
|
||||
if ( values[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||
result.put( propertyNames[i], "<uninitialized>" );
|
||||
}
|
||||
else {
|
||||
result.put( propertyNames[i], propertyTypes[i].toLoggableString( values[i], factory ) );
|
||||
}
|
||||
}
|
||||
return StringHelper.unqualify( getName() ) + result.toString();
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.io.Serializable;
|
|||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -374,7 +375,14 @@ public class TypeHelper {
|
|||
if ( i > 0 ) {
|
||||
buff.append( ", " );
|
||||
}
|
||||
buff.append( types[i].toLoggableString( state[i], factory ) );
|
||||
|
||||
// HHH-11173 - Instead of having to account for unfectched lazy properties in all types, it's done here
|
||||
if ( state[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || !Hibernate.isInitialized( state[i] ) ) {
|
||||
buff.append( "<uninitialized>" );
|
||||
}
|
||||
else {
|
||||
buff.append( types[i].toLoggableString( state[i], factory ) );
|
||||
}
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.test.bytecode.enhancement.lazy.LazyLoadingTestTask;
|
|||
import org.hibernate.test.bytecode.enhancement.lazy.LazyProxyOnEnhancedEntityTestTask;
|
||||
import org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicFieldAccessTestTask;
|
||||
import org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicPropertyAccessTestTask;
|
||||
import org.hibernate.test.bytecode.enhancement.lazy.cache.LazyInCacheTestTask;
|
||||
import org.hibernate.test.bytecode.enhancement.lazy.group.LazyGroupAccessTestTask;
|
||||
import org.hibernate.test.bytecode.enhancement.lazy.group.LazyGroupUpdateTestTask;
|
||||
import org.hibernate.test.bytecode.enhancement.lazy.group.SimpleLazyGroupUpdateTestTask;
|
||||
|
@ -119,6 +120,12 @@ public class EnhancerTest extends BaseUnitTestCase {
|
|||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-11173" )
|
||||
public void testLazyCache() {
|
||||
EnhancerTestUtils.runEnhancerTestTask( LazyInCacheTestTask.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-10252" )
|
||||
public void testCascadeDelete() {
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.bytecode.enhancement.lazy.cache;
|
||||
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
|
||||
import org.junit.Assert;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Luis Barreiro
|
||||
*/
|
||||
public class LazyInCacheTestTask extends AbstractEnhancerTestTask {
|
||||
|
||||
public Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[]{Order.class, Product.class, Tag.class};
|
||||
}
|
||||
|
||||
public void prepare() {
|
||||
Configuration cfg = new Configuration();
|
||||
cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
|
||||
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" );
|
||||
prepare( cfg );
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
EntityManager entityManager = getFactory().createEntityManager();
|
||||
Order order = new Order();
|
||||
Product product = new Product();
|
||||
order.products.add( product );
|
||||
order.data = "some data".getBytes();
|
||||
entityManager.getTransaction().begin();
|
||||
entityManager.persist( product );
|
||||
entityManager.persist( order );
|
||||
entityManager.getTransaction().commit();
|
||||
|
||||
long orderId = order.id;
|
||||
|
||||
entityManager = getFactory().createEntityManager();
|
||||
order = entityManager.find( Order.class, orderId );
|
||||
Assert.assertEquals( 1, order.products.size() );
|
||||
entityManager.close();
|
||||
|
||||
}
|
||||
|
||||
protected void cleanup() {
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Cache( usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE )
|
||||
public static class Order {
|
||||
|
||||
@Id
|
||||
@GeneratedValue( strategy = GenerationType.IDENTITY )
|
||||
long id;
|
||||
|
||||
@OneToMany
|
||||
List<Product> products = new ArrayList<>();
|
||||
|
||||
@OneToMany
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
|
||||
@Basic( fetch = FetchType.LAZY )
|
||||
@Column
|
||||
@Type( type = "org.hibernate.type.BinaryType" )
|
||||
private byte[] data;
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class Product {
|
||||
|
||||
@Id
|
||||
@GeneratedValue( strategy = GenerationType.IDENTITY )
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
public class Tag {
|
||||
|
||||
@Id
|
||||
@GeneratedValue( strategy = GenerationType.IDENTITY )
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue