[Hibernate-JIRA] Created: (HHH-2864) Merging a detached instance with a new child in a unidirectional one-to-many association fails if the parent was previously loaded as a proxy
by Carl-Eric Menzel (JIRA)
Merging a detached instance with a new child in a unidirectional one-to-many association fails if the parent was previously loaded as a proxy
---------------------------------------------------------------------------------------------------------------------------------------------
Key: HHH-2864
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2864
Project: Hibernate3
Issue Type: Bug
Affects Versions: 3.2.5, 3.1.3
Environment: Tested with Hibernate 3.1.3 and 3.2.5 on HSQL and Oracle 9, using JDK 1.4 and 1.6. The behavior is the same in each case.
Reporter: Carl-Eric Menzel
Attachments: ProxyMergeTest.zip
Given a class One and a class Many with a unidirectional one-to-many relationship.
I'm getting a PropertyValueException: "not-null property references a null or transient value: test.Many._toManyBackref" when merging a detached "One" instance which contains a new "Many" instance if and only if the "One" was previously loaded as a proxy in the same transaction. The meat of the problem:
// create new One
One one = new One();
one.setOneOther(new One());
session.save(one);
commitAndGetNewSession();
/*
* load saved instance as a proxy, but do not use it. we could use get() so we wouldn't get a proxy, but a real-world
* application might have only loaded this instance transitively as a proxy before merging a detached instance, so this is a
* real problem.
*/
Object proxyWeDontUse = session.load(One.class, new Integer(one.getId()));
assertTrue(proxyWeDontUse instanceof HibernateProxy);
// use detached instance and add a Many
one.getToMany().add(new Many());
// merge the detached instance. this should work, but doesn't. the backref-getter doesn't correctly
// find the parent object of the new Many, because the copyCache/mergeMap only contains the proxy loaded
// above, but the entityEntries in PersistenceContext contain the raw unproxied object.
session.merge(one);
In this simplified testcase I explicitly load the proxy. In our actual scenario, the One is loaded transitively as a child of yet another parent object - usually as a proxy. We need to load this to perform some authorization checks before we can actually merge the incoming detached One instance. This leads to the situation of having the proxy first and only then merging. As far as I understand the documentation, this *should* work.
I spent quite some time getting to the bottom of this - mostly debugging through the MergeEventListener. I found this: DefaultMergeEventListener uses Session.get() to load the persistent instance when merging a detached one. get() returns the proxy that was previously created. DefaultMergeEventListener then stores this returned proxy as the value of an entry in the copyCache. Later the backref-getter gets the actual persistent instance from the PersistenceContext and uses this to look for the detached instance in the mergeMap (which is the inverted copyCache, if I understood that correctly). But this only returns null, since the only key it can see is the *proxy* that was put as a value into the copyCache. Thus the backref-getter can't find its backref, leading to the exception.
Proposed solution: Store the persistent instance in the copyCache instead of the proxy, or do some dereferencing magic when looking for the backref. I can't judge that though - all I know about this right now comes from several hours of serious debugging.
I'm attaching an almost ready-to-use testcase as a zipped Eclipse project. Sources and config are in src/, the lib/ directory contains a hsqldb.jar which I used for fast testing. Simply add the required Hibernate jars and run the MergeUnidirectionalOneToManyTest. We currently use Hibernate 3.1.3 in production, but the problem occurs with 3.2.5 as well. A patched 3.1 release would be the best for us, but I'm not sure whether that is possible.
Thanks!
Carl-Eric Menzel
Senacor Technologies AG
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
18 years, 2 months
[Hibernate-JIRA] Created: (HHH-2197) make more information about the persistent class available to NamingStrategy methods
by Jason Trump (JIRA)
make more information about the persistent class available to NamingStrategy methods
------------------------------------------------------------------------------------
Key: HHH-2197
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2197
Project: Hibernate3
Type: Improvement
Components: core
Versions: 3.2.0.ga
Environment: all environments
Reporter: Jason Trump
Priority: Minor
Currently NamingStrategy.propertyToColumnName() implementations are only passed the bare property name for persistent entities, without any information about which class is being persisted. It would be nice if the persistent classname was also provided, so that information about the class could be used in deciding how to generate the column name.
To give an example, in a client's database, all of the column names begin with an abbreviation of the table name itself:
create table TBL_Foo (
FooUuid tinyint primary key,
FooProperty varchar(32)
)
maps to class:
public class Foo {
private Integer uuid;
private String property;
....
}
Right now propertyToColumnName(String) is only called with the arguments "uuid" or "property", making it impossible to automatically prefix "Foo" with a NamingStrategy. To preserve backwards-compatibility, maybe we could get another version of propertyToColumnName, like
/**
* @param className fully-qualified className of the persistent class, or entity-name for non-pojo persistence
* @param propertyPath property name relative to <code>className</code>
*/
public String propertyToColumnName(String className, String propertyPath);
with similar overloaded versions on other methods in the interface, with the same idea. apologies if this type of thing is already available in the current release, but I didn't find evidence of this either in the forums or by inspecting the code.
thanks for hibernate and Hibernate entitymanager! i've been a fan for several years now.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
18 years, 2 months
[Hibernate-JIRA] Created: (HHH-2869) Atomic remove + add of unique properties to a persistent set fails
by Pietu Pohjalainen (JIRA)
Atomic remove + add of unique properties to a persistent set fails
------------------------------------------------------------------
Key: HHH-2869
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2869
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.5
Environment: Hibernate 3.2.5 (2007.07.31);
Oracle 9
Reporter: Pietu Pohjalainen
Priority: Minor
Attachments: hibernate-unique-showcase.zip
Trying to remove and add equal objects to a persistent set with unique property on, fails.
E.g. we have a set 'set' with one object, "X" contained in it. A sequence of
set.clear();
set.add("X");
session.update(set);
produces a unique constraint exception from the underlying database, because the update first tries to add the newly added objects, and only after that it tries to remove those.
E.g. Oracle produces the following exception: "Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint (SHOWCASE.SYS_C0036053) violated"
A workaround is would be to run the session.update(set); session.flush(); after clearing the set - but I would argue that interleaving the persistence-code with regular object handling code does not exactly fulfill the promise of 'transparent persistency'.
Please see the attached showcase.zip, which sets up a database. There's a 'container', which contains a set of 'values', where values should be unique across all sets in the system. When trying to remove and add the same value to a set, the program throws an exception.
The showcase driver script is located in class hibernate.Showcase. The object model classes are located in test.Container and test.Value.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
18 years, 2 months
[Hibernate-JIRA] Created: (HHH-2556) HQL queries with many-to-one joins with property-ref fail
by Bill Swayze (JIRA)
HQL queries with many-to-one joins with property-ref fail
----------------------------------------------------------
Key: HHH-2556
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2556
Project: Hibernate3
Issue Type: Bug
Affects Versions: 3.2.1
Environment: 3.2.1 Sybase 12.x
Reporter: Bill Swayze
Priority: Critical
I am experiencing a similar problem to HHH768. In HQL with many-to-one associations using a property-ref, the 'one' end of the association (all requisite fields) is retrieved and partially resolved and saved in entitiesByKey. In subsequent result set processing, an attempt to resolve the entity in entitiesByUniqueKey is unsuccessful as it is trying to use the pk. Ultimately, the entity is null in the results of .list().
Consider the following simple mappings and query:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="test.A"
table="a_t">
<id name="id" column="id" type="java.lang.Integer">
<generator class="assigned"/>
</id>
<many-to-one name="child" class="test.B" column="str_id" property-ref="key" not-null="true"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="test.B"
table="b_t">
<id name="id" column="id" type="java.lang.Integer">
<generator class="assigned"/>
</id>
<property name="data" type="java.lang.String" column="data" not-null="true" length="80" />
<property name="key" type="java.lang.String" column="str_id" unique="true" not-null="true" length="80" />
</class>
</hibernate-mapping>
select aa.id, bb from A aa inner join aa.child bb where aa.id = 1
This query returns all requisite fields along with an additional column that refers to b's pk. This column is used, erroneously, to try to look up the entity by unique key. It is not clear to me whether the problem is in the result set processing or the new query parser.
I was counting on using this functionality to expand our use of Hibernate and ease the transition of significant amounts of legacy tables.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
18 years, 2 months