|
From: Emmanuel B. <emm...@hi...> - 2006-03-29 09:39:17
|
You have found a bug for sure, so JIRA can be used :-)
Thanks for having tracking down the bug, that will help a lot.
When you use an embeddedaccessor, you expect the information to be
filled through alternative properties, hence a noop here.
3. was my initial thought, why do you think it won't help for multi
column mapping?
Ron...@to... wrote:
>
> Hi Emmanuel,
>
> I think we might have found a bug in
> BindHelper.bindPropertiesByColumns, want to run by you to see if it's
> worth while submitting to Jira.
>
> What we are trying to do is to associate two attributes of the same
> type to an object.
>
> i.e.,
>
> class Deal {
> @ManyToOne
> @JoinColumn(name = "a_customer_id", referencedColumnName =
> "customer_id", nullable = true)
> Customer a;
>
> @ManyToOne
> @JoinColumn(name = "b_customer_id", referencedColumnName =
> "customer_id", nullable = true)
> Customer b;
> }
>
> // note: customer id is not a pk
> class Customer {
> @Column(name = "customer_id")
> String customerId;
> }
>
> When loading deal object, customer a is always populated correctly but
> customer b will only be populated occasionally (depending on your luck!).
>
> After digging through Hibernate annotation source, I think I've found
> the cause of the problem in BindHelper.bindPropertiesByColumns where
> HashSet is being used.
>
> From looking through the source, my understanding is that hibernate
> will create a synthetic property for each of the customer Deal.a and
> Deal.b and add it to a list of properties type mapping within Customer
> persistent class object. This type mapping is then used to hydrate
> Deal.a and Deal.b when Deal object is being resolved.
>
> When synthetic property for Deal.a is being created, the
> propertymapping is straight forward because only customerId property
> is available in the Customer persistent class. Deal.a is then mapped
> simply to a simple type of Customer.customerId.
>
> Subsequently, when synthetic property for Deal.b is being created
> (BindHelper:97), the property mapping has two possible values - one is
> the Customer.customerId, the other is the recently created synthetic
> mapping (_Deal_a). These two values are extracted out and put into a
> HashSet (BindHelper.bindPropertiesByColumn:190). The hashset is then
> the being iterated through to return the first value of iterator
> (which the order is not guaranteed). Obviously it would be wrong to
> create a synthetic property for Deal.b with synthetic property _Deal_a
> type mapping (which is what occasionally happens).
>
> Upon load, hibernate core will then attempt to hydrate Deal.a by
> instantiating Customer (_Deal_a) type object and inject a_customer_id
> into an instance of _Deal_a type. This will result in a correct load.
>
> When hibernate core attempt to hydrate Deal.b, it will instantiate
> Customer (_Deal_b) type object. However, _Deal_b type object mapps to
> an embedded _Deal_a type. So it will then recurse through the embedded
> type, instantiate Customer (_Deal_a) type object, assign b_customer_id
> into embedded Customer.customerId after which instance of
> Customer(_Deal_a) will be assigned to Customer.customerId (_Deal_b).
> This assignment is done via
> EmbeddedPropertyAccessor.EmbeddedSetter.set method - which looks like
> a null implementation. The result is that Deal.b won't be set and no
> errors is being reported at all. What worst is that the system can
> appear to have been working most of the time, but if you add
> additional attribute to class Deal to disturb the balance of the
> hashcode generation, then all of the sudden it won't work.
>
> I can think of a couple of fixes in BindHelper.bindPropertiesByColumns:
> 1. Instead of using HashSet we use an ordered set to guarantee the
> order, this way the native properties will always be returned first.
> 2. Use List instead of Set to guarantee the order - the values being
> added in to the columnsToProperty map can never be null or repeated
> anyway.
> 3. Filter out all of the synthetic properties from columnsToProperty
> mapping (this propbably wouldn't help for muti column mapping?).
>
> BTW: It also perplex me why
> EmbeddedPropertyAccessor.EmbeddedSetter.set method would do nothing
> and report no error when it can't set the property.
>
> Sorry for the lengthy email but it's a fairly subtle bug that can't
> always be replicated so I thought it's worth while explaining in
> details. Let me know if you want me to submit this to Jira. We have
> opted for option 2 on local fix and it appear to be working well.
>
> Regards,
> rOnn c.
>
> ##########################################################
> DISCLAIMER:
> This email and any attachment may contain confidential information.
> If you are not the intended recipient you are not authorized to copy
> or disclose all or any part of it without the prior written consent
> of Toyota.
>
> Opinions expressed in this email and any attachments are those of the
> sender and not necessarily the opinions of Toyota.
> Please scan this email and any attachment(s) for viruses.
> Toyota does not accept any responsibility for problems caused by
> viruses, whether it is Toyota's fault or not.
> ##########################################################
>
|