views:

121

answers:

1
+1  A: 

That's much clearer now, thank you.

Is it really SampleBean1 in both cases (e.g. entity itself and the OneToOne mapped property) or is it a typo? If they are the same, I'm pretty sure it's illegal (how do you imagine that mapping would work)? I'm a bit surprised it's quietly downgraded to "many-to-one" instead of throwing an error, but perhaps that's what Hibernate Annotations mapper does.

ChssPly76
SampleBean1 is mapped to itself on each relation. I figured it would make it easier to test. Can you not have a OneToOne relation with yourself in Hibernate? In SQL you can just add a Foreign Key and all is well.
User1
So say you have three instance of SampleBean1 - SB1, SB2 and SB3. SB1's oneToOne property points to SB2 PK. SB2's oneToOne property points to SB3 PK. Now which "one" is SB2 one-to-one'd with - SB1 or SB3? :-) That's why it's illegal.
ChssPly76
Well. What if you have two entities, A and B, with 1-to-1 relationships to each other. What if both A1 and A2 point to B1? Which "one" is B1 one-to-one'd with? I guess if the point you proposed is illegal, that's not because of the example you gave.
André Neves
@Andre - your example is not of one-to-one relationship. It's many-to-one from A to B or one-to-many from B to A
ChssPly76
@ChssPly76 Thanks so much for your help so far. Wouldn't SB2.oneToOne=SB3? It was supposed to be a unidirectional OneToOne, but I may have coded it wrong. I updated the question with further details on what I "think" unidirectional one-to-one means. Maybe you can give a counter-example. Maybe it's even a Hibernate defect. It's a very complex issue.
User1
"Unidirectional" simply means that one end of association links to another but the other doesn't link back. In no way does that change the cardinality of the relationship. One-to-one to self makes no sense simply because "self" (same instance) would have to be on both ends of relationship; otherwise you end up with a "chain" like the one you've shown in your question where each middle "link" connects two separate instances and thus can not be part of one-to-one relationship. You'll need to map another entity (SampleBean2) as one-to-one.
ChssPly76
I'm not sure I follow. Here's a real-world example. Consider, a transaction management system. Every time a record is changed, a new record is inserted into the database. The new record has a field called originalRecord that points back to the old record. The old record's originalRecord field is null (it's the first one). This architecture possible to see the history of the record thru time. This is the intent of SampleBean1. Each record should only have one oldRecord column and each oldRecord entry should have a unique oldRecord entry. Isn't that One-to-One or is it something else?
User1
No, that's not one-to-one - it's many-to-one. I understand that distinction seems somewhat ethereal :-) but think of it this way: imagine that all relationships are bi-directional and count the number of entity instances you entity could POTENTIALLY be linked to. New record points to old record (+1) and, once it gets superseded by even newer record, will be linked to that newer record as well (+1). That makes 2 links which means it's not one-to-one :-)
ChssPly76
I may be misunderstanding this, but wouldn't that make it impossible to have something like previousRecord AND nextRecord fields in my previous example? Is there a good document about this somewhere? The initial problem remains..if the annotation was marked as @OneToOne how can I tell? Can I at least get a Field that I can reflect? Thanks again for your help.
User1
You can very much map the previous / next record fields but it's going to be a many-to-one relationship, not a one-to-one. As far as inital problem goes, your initial solution (checking `entityType.isOneToOne()`) IS correct. It was returning false because the relationship you were checking was not really one-to-one. Create a SampleBean2 entity and map it as one-to-one (using either shared PK or FK) and it'll work.
ChssPly76
I really appreciate your help and do not want to sound difficult, but Hibernate's definition of OneToOne is a bit different than what our requirements consider OneToOne. I completely understand that Hibernate is calling this ManyToOne, and the rationale seems reasonable. But, I'd like to be able to take a look at the original annotation so our library can act appropriately on this special case. Any suggestions? Again, thank you so much for your help!
User1
You can always check the actual annotation. You know the property name and the class; use reflection to grab the field and `get` method (choosing between the two can be problematic; I suggest you check both), and call `setAccessible()` on it followed by `getAnnotation(OneToOne.class)`. If the latter does not return NULL, it was marked `OneToOne`. I'd be cautious with this, though - the fact that Hibernate quietly 'downgrades' an illegal OneToOne to ManyToOne seems rather iffy to me, that may very well change in the future.
ChssPly76
I was afraid you'd recommend reflection. It's ugly but it works for now. I made a special unit test for this case so hopefully it will be obvious for future developers on the project. Thanks again. I believe this fixed our issue!
User1
You're very welcome, but notice that I don't "recommend" it - I recommend using real OneToOne instead :-) Take a look at Hibernate's `AnnotationBinder.bindOneToOne()` method - you'll see where it falls back onto ManyToOne mapping. Perhaps you'll be able to alter your requirements a little bit so you can avoid dealing with this as a special case.
ChssPly76
Nice. Thanks for the tip about where this all happens in the Hibernate code. I found it at: http://koders.com/java/fid87D9ED964A2266421D97E3A2A7ACBF4339642A66.aspx?s=AnnotationBinder+bindOneToOne#L1641I may dig in as time permits.
User1