HHH-5255 : Merge detached entity failed when the instrumented lazy property is initialized
(cherry picked from commit c00d4609ef
)
This commit is contained in:
parent
3908215685
commit
fd760dcf2e
|
@ -173,6 +173,22 @@ public class TypeHelper {
|
|||
|| original[i] == BackrefPropertyAccessor.UNKNOWN ) {
|
||||
copied[i] = target[i];
|
||||
}
|
||||
else if ( target[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||
// Should be no need to check for target[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN
|
||||
// because PropertyAccessStrategyBackRefImpl.get( object ) returns
|
||||
// PropertyAccessStrategyBackRefImpl.UNKNOWN, so target[i] == original[i].
|
||||
//
|
||||
// We know from above that original[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY &&
|
||||
// original[i] != PropertyAccessStrategyBackRefImpl.UNKNOWN;
|
||||
// This is a case where the entity being merged has a lazy property
|
||||
// that has been initialized. Copy the initialized value from original.
|
||||
if ( types[i].isMutable() ) {
|
||||
copied[i] = types[i].deepCopy( original[i], session.getFactory() );
|
||||
}
|
||||
else {
|
||||
copied[i] = original[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
copied[i] = types[i].replace( original[i], target[i], session, owner, copyCache );
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ import org.hibernate.test.instrument.cases.TestDirtyCheckExecutable;
|
|||
import org.hibernate.test.instrument.cases.TestFetchAllExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestInjectFieldInterceptorExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestLazyBasicPropertyUpdateExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestLazyBasicFieldAccessExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestLazyBasicPropertyAccessExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestLazyExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestLazyManyToOneExecutable;
|
||||
import org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable;
|
||||
|
@ -90,8 +91,13 @@ public class InstrumentTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testLazyBasicPropertyUpdate() throws Exception {
|
||||
execute( new TestLazyBasicPropertyUpdateExecutable() );
|
||||
public void testLazyBasicFieldAccess() throws Exception {
|
||||
execute( new TestLazyBasicFieldAccessExecutable() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLazyBasicPropertyAccess() throws Exception {
|
||||
execute( new TestLazyBasicPropertyAccessExecutable() );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package org.hibernate.test.instrument.cases;
|
||||
import org.junit.Assert;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.test.instrument.domain.Document;
|
||||
import org.hibernate.test.instrument.domain.Folder;
|
||||
import org.hibernate.test.instrument.domain.Owner;
|
||||
|
||||
/**
|
||||
* @author Andrei Ivanov
|
||||
*/
|
||||
public class TestLazyBasicFieldAccessExecutable extends AbstractExecutable {
|
||||
protected String[] getResources() {
|
||||
return new String[] {"org/hibernate/test/instrument/domain/Documents.hbm.xml"};
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
Session s = getFactory().openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
Owner o = new Owner();
|
||||
Document doc = new Document();
|
||||
Folder fol = new Folder();
|
||||
o.setName( "gavin" );
|
||||
doc.setName( "Hibernate in Action" );
|
||||
doc.setSummary( "blah" );
|
||||
doc.updateText( "blah blah" );
|
||||
fol.setName( "books" );
|
||||
doc.setOwner( o );
|
||||
doc.setFolder( fol );
|
||||
fol.getDocuments().add( doc );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
|
||||
s.persist( o );
|
||||
s.persist( fol );
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// update with lazy property initialized
|
||||
doc.setName( "Doc Name" );
|
||||
doc.setSummary( "u" );
|
||||
s.update( doc );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// merge with lazy property initialized and updated
|
||||
doc.setName( "Doc Name 1" );
|
||||
doc.setSummary( "v" );
|
||||
Document docManaged = (Document) s.merge( doc );
|
||||
Assert.assertEquals( "v", docManaged.getSummary() );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
docManaged = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// merge with lazy property initialized in doc; uninitialized in docManaged.
|
||||
doc.setSummary( "w" );
|
||||
Assert.assertSame( docManaged, s.merge( doc ) );
|
||||
Assert.assertEquals( "w", docManaged.getSummary() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
docManaged = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// initialize docManaged.getSummary
|
||||
Assert.assertEquals( "w", docManaged.getSummary() );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// merge with lazy property initialized in both doc and docManaged.
|
||||
doc.setSummary( "x" );
|
||||
Assert.assertSame( docManaged, s.merge( doc ) );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
Assert.assertEquals( "x", docManaged.getSummary() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
Document docWithLazySummary = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// summary should still be uninitialized.
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
|
||||
docWithLazySummary.setName( "new name" );
|
||||
// merge the Document with an uninitialized summary
|
||||
docManaged = (Document) s.merge( docWithLazySummary );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
docManaged = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// initialize docManaged.getSummary
|
||||
Assert.assertEquals( "x", docManaged.getSummary() );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// merge the Document with an uninitialized summary
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
|
||||
docManaged = (Document) s.merge( docWithLazySummary );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
Assert.assertEquals( "x", docManaged.getSummary() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package org.hibernate.test.instrument.cases;
|
||||
import org.junit.Assert;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.test.instrument.domain.Document;
|
||||
import org.hibernate.test.instrument.domain.Folder;
|
||||
import org.hibernate.test.instrument.domain.Owner;
|
||||
|
||||
/**
|
||||
* @author Andrei Ivanov
|
||||
*/
|
||||
public class TestLazyBasicPropertyAccessExecutable extends AbstractExecutable {
|
||||
protected String[] getResources() {
|
||||
return new String[] {"org/hibernate/test/instrument/domain/DocumentsPropAccess.hbm.xml"};
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
Session s = getFactory().openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
Owner o = new Owner();
|
||||
Document doc = new Document();
|
||||
Folder fol = new Folder();
|
||||
o.setName( "gavin" );
|
||||
doc.setName( "Hibernate in Action" );
|
||||
doc.setSummary( "blah" );
|
||||
doc.updateText( "blah blah" );
|
||||
fol.setName( "books" );
|
||||
doc.setOwner( o );
|
||||
doc.setFolder( fol );
|
||||
fol.getDocuments().add( doc );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
|
||||
s.persist( o );
|
||||
s.persist( fol );
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// update with lazy property initialized
|
||||
doc.setName( "Doc Name" );
|
||||
doc.setSummary( "u" );
|
||||
s.update( doc );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// merge with lazy property initialized and updated
|
||||
doc.setName( "Doc Name 1" );
|
||||
doc.setSummary( "v" );
|
||||
Document docManaged = (Document) s.merge( doc );
|
||||
Assert.assertEquals( "v", docManaged.getSummary() );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
docManaged = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// merge with lazy property initialized in doc; uninitialized in docManaged.
|
||||
doc.setSummary( "w" );
|
||||
Assert.assertSame( docManaged, s.merge( doc ) );
|
||||
Assert.assertEquals( "w", docManaged.getSummary() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
docManaged = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// initialize docManaged.getSummary
|
||||
Assert.assertEquals( "w", docManaged.getSummary() );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// merge with lazy property initialized in both doc and docManaged.
|
||||
doc.setSummary( "x" );
|
||||
Assert.assertSame( docManaged, s.merge( doc ) );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
Assert.assertEquals( "x", docManaged.getSummary() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
Document docWithLazySummary = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// summary should still be uninitialized.
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
|
||||
docWithLazySummary.setName( "new name" );
|
||||
// merge the Document with an uninitialized summary
|
||||
docManaged = (Document) s.merge( docWithLazySummary );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = getFactory().openSession();
|
||||
s.getTransaction().begin();
|
||||
// get the Document with an uninitialized summary
|
||||
docManaged = (Document) s.get( Document.class, doc.getId() );
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// initialize docManaged.getSummary
|
||||
Assert.assertEquals( "x", docManaged.getSummary() );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
// merge the Document with an uninitialized summary
|
||||
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
|
||||
docManaged = (Document) s.merge( docWithLazySummary );
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
|
||||
Assert.assertEquals( "x", docManaged.getSummary() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package org.hibernate.test.instrument.cases;
|
||||
import org.junit.Assert;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.test.instrument.domain.Document;
|
||||
import org.hibernate.test.instrument.domain.Folder;
|
||||
import org.hibernate.test.instrument.domain.Owner;
|
||||
|
||||
/**
|
||||
* @author Andrei Ivanov
|
||||
*/
|
||||
public class TestLazyBasicPropertyUpdateExecutable extends AbstractExecutable {
|
||||
public void execute() {
|
||||
Session s = getFactory().openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
Owner o = new Owner();
|
||||
Document doc = new Document();
|
||||
Folder fol = new Folder();
|
||||
o.setName("gavin");
|
||||
doc.setName("Hibernate in Action");
|
||||
doc.setSummary("blah");
|
||||
doc.updateText("blah blah");
|
||||
fol.setName("books");
|
||||
doc.setOwner(o);
|
||||
doc.setFolder(fol);
|
||||
fol.getDocuments().add(doc);
|
||||
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
|
||||
s.persist(o);
|
||||
s.persist(fol);
|
||||
t.commit();
|
||||
|
||||
s.evict(doc);
|
||||
|
||||
doc.setSummary("u");
|
||||
s.merge(doc);
|
||||
|
||||
s.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.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>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<!--
|
||||
|
||||
This mapping demonstrates
|
||||
|
||||
(1) use of lazy properties - this feature requires buildtime
|
||||
bytecode instrumentation; we don't think this is a very
|
||||
necessary feature, but provide it for completeleness; if
|
||||
Hibernate encounters uninstrumented classes, lazy property
|
||||
fetching will be silently disabled, to enable testing
|
||||
|
||||
(2) use of a formula to define a "derived property"
|
||||
|
||||
-->
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.instrument.domain" default-access="property">
|
||||
|
||||
<class name="Folder" table="folders">
|
||||
<id name="id">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="name" not-null="true" length="50"/>
|
||||
<many-to-one name="parent"/>
|
||||
<bag name="subfolders" inverse="true" cascade="save-update">
|
||||
<key column="parent"/>
|
||||
<one-to-many class="Folder"/>
|
||||
</bag>
|
||||
<bag name="documents" inverse="true" cascade="all-delete-orphan">
|
||||
<key column="folder"/>
|
||||
<one-to-many class="Document"/>
|
||||
</bag>
|
||||
</class>
|
||||
|
||||
<class name="Owner" table="owners" lazy="false">
|
||||
<id name="id">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="name" not-null="true" length="50"/>
|
||||
</class>
|
||||
|
||||
<class name="Document" table="documents">
|
||||
<id name="id">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="name" not-null="true" length="50"/>
|
||||
<property name="upperCaseName" formula="upper(name)" lazy="true"/>
|
||||
<property name="summary" column="`summary`" not-null="true" length="200" lazy="true"/>
|
||||
<many-to-one name="folder" not-null="true" lazy="no-proxy"/>
|
||||
<many-to-one name="owner" not-null="true" lazy="no-proxy" fetch="select"/>
|
||||
<property name="text" not-null="true" length="2000" lazy="true"/>
|
||||
<property name="lastTextModification" not-null="true" lazy="true" access="field"/>
|
||||
<property name="sizeKb" lazy="true">
|
||||
<column name="size_mb"
|
||||
read="size_mb * 1024.0"
|
||||
write="? / cast( 1024.0 as float )"/>
|
||||
</property>
|
||||
</class>
|
||||
|
||||
<class name="Entity" table="entity">
|
||||
<id name="id" column="ID" type="long">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="name" column="NAME" type="string" lazy="true"/>
|
||||
<many-to-one name="child" column="PRNT_ID" class="Entity" lazy="proxy" cascade="all" />
|
||||
<many-to-one name="sibling" column="RIGHT_ID" class="Entity" lazy="no-proxy" cascade="all" />
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -124,8 +124,16 @@ public abstract class AbstractTransformingClassLoaderInstrumentTestCase extends
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testLazyBasicPropertyUpdate() {
|
||||
executeExecutable( "org.hibernate.test.instrument.cases.TestLazyBasicPropertyUpdateExecutable" );
|
||||
@FailureExpected( jiraKey = "HHH-9984")
|
||||
@TestForIssue( jiraKey = "HHH-9984")
|
||||
public void testLazyBasicFieldAccess() {
|
||||
executeExecutable( "org.hibernate.test.instrument.cases.TestLazyBasicFieldAccessExecutable" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-5255")
|
||||
public void testLazyBasicPropertyAccess() {
|
||||
executeExecutable( "org.hibernate.test.instrument.cases.TestLazyBasicPropertyAccessExecutable" );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue