> 3. was my initial thought, why do you think it won't help for multi
> column mapping?
Probably due to my lack of understanding on how column mapping works. I'm confused why columnsToProperty is a Map<Column, Set<Property>> - can there be more than one property mapping to a join column? And if that is the case, down below when iterate through all the columnsToProperty mappings it has found, only first one is selected and put into orderedProperties anyway (BindHelper:234).
But yes techically, synthetic property shouldn't need to be considered in BinderHelper.findPropertiesByColumns method anyway. I'm wondering that if there is ever more than one property being mapped into a column then HashSet iterator won't guarantee the order and similar behaviour will still occur.
Regards,
rOnn c.
Emmanuel Bernard <[EMAIL PROTECTED]>
29/03/2006 08:38 PM |
To: [EMAIL PROTECTED] cc: hibernate-devel@lists.sourceforge.net Subject: Re: [Hibernate] BindHelper.findPropertiesByColumns behaviour is non deterministic due to HashSet being used. |
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?
[EMAIL PROTECTED] 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.
> ##########################################################
>
##########################################################
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.
##########################################################