From 6145c9a66a708fdc7efc14d6093da012f882ce53 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 21 Mar 2014 11:33:49 -0400 Subject: [PATCH] HHH-9071 When an already initialized proxy is narrowed, initialize the new proxy (cherry picked from commit 2cf52cc7f1e1d8f918188d5166a3a869fc213cd8) Conflicts: hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java --- .../internal/StatefulPersistenceContext.java | 14 ++- .../test/proxy/narrow/AbstractEntity.java | 50 +++++++++++ .../test/proxy/narrow/ConcreteEntity.java | 46 ++++++++++ .../narrow/LazyAbstractEntityReference.java | 67 ++++++++++++++ .../test/proxy/narrow/ProxyNarrowingTest.java | 90 +++++++++++++++++++ 5 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java index b1d565a149..1d9c6f26ed 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java @@ -732,9 +732,19 @@ public class StatefulPersistenceContext implements PersistenceContext { "proxy not of type HibernateProxy; it is " + proxyOrig.getClass() ); } + + HibernateProxy originalHibernateProxy = (HibernateProxy) proxyOrig; + HibernateProxy newHibernateProxy = (HibernateProxy) proxy; + // set the read-only/modifiable mode in the new proxy to what it was in the original proxy - boolean readOnlyOrig = ( ( HibernateProxy ) proxyOrig ).getHibernateLazyInitializer().isReadOnly(); - ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().setReadOnly( readOnlyOrig ); + final boolean readOnlyOrig = originalHibernateProxy.getHibernateLazyInitializer().isReadOnly(); + newHibernateProxy.getHibernateLazyInitializer().setReadOnly( readOnlyOrig ); + + // if the original proxy is already initialized, initialize the new proxy + if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) { + newHibernateProxy.getHibernateLazyInitializer().setImplementation( + originalHibernateProxy.getHibernateLazyInitializer().getImplementation() ); + } } return proxy; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java new file mode 100644 index 0000000000..8f764ed249 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +@Entity +public abstract class AbstractEntity { + + @Id + @GeneratedValue + private Integer id; + + public AbstractEntity() { + super(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java new file mode 100644 index 0000000000..4cbee7e7f6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import javax.persistence.Entity; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +@Entity +public class ConcreteEntity extends AbstractEntity { + + private String content = "text"; + + public ConcreteEntity() { + super(); + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java new file mode 100644 index 0000000000..b97c70cb43 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +@Entity +public class LazyAbstractEntityReference { + + @Id + @GeneratedValue + private Integer id; + + @ManyToOne(fetch = FetchType.LAZY) + private AbstractEntity entity; + + protected LazyAbstractEntityReference() { + } + + public LazyAbstractEntityReference(AbstractEntity entity) { + super(); + setEntity( entity ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public AbstractEntity getEntity() { + return entity; + } + + public void setEntity(AbstractEntity entity) { + this.entity = entity; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java new file mode 100644 index 0000000000..0794a2a3dc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import static org.junit.Assert.assertTrue; + +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.proxy.HibernateProxy; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +public class ProxyNarrowingTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { AbstractEntity.class, ConcreteEntity.class, LazyAbstractEntityReference.class }; + } + + @Test + public void testNarrowedProxyIsInitializedIfOriginalProxyIsInitialized() { + Session session = openSession(); + + Integer entityReferenceId = null; + + // Populate the database + try { + Transaction t = session.beginTransaction(); + + ConcreteEntity entity = new ConcreteEntity(); + session.save( entity ); + + LazyAbstractEntityReference reference = new LazyAbstractEntityReference( entity ); + session.save( reference ); + entityReferenceId = reference.getId(); + + session.flush(); + t.commit(); + } + finally { + session.close(); + } + + session = openSession(); + + try { + // load a proxified version of the entity into the session: the proxy is based on the AbstractEntity class + // as the reference class property is of type AbstractEntity. + LazyAbstractEntityReference reference = (LazyAbstractEntityReference) session.get( LazyAbstractEntityReference.class, entityReferenceId ); + AbstractEntity abstractEntityProxy = reference.getEntity(); + + assertTrue( ( abstractEntityProxy instanceof HibernateProxy ) && !Hibernate.isInitialized( abstractEntityProxy ) ); + Hibernate.initialize( abstractEntityProxy ); + assertTrue( Hibernate.isInitialized( abstractEntityProxy ) ); + + // load the concrete class via session.load to trigger the StatefulPersistenceContext.narrowProxy code + ConcreteEntity concreteEntityProxy = (ConcreteEntity) session.load( ConcreteEntity.class, abstractEntityProxy.getId() ); + + // the new proxy created should be initialized + assertTrue( ( concreteEntityProxy instanceof HibernateProxy ) && Hibernate.isInitialized( concreteEntityProxy ) ); + } + finally { + session.close(); + } + } + +}