-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: one-to-one via many-to-one and delete-orphan
PostPosted: Tue Jul 19, 2005 7:32 pm 
Newbie

Joined: Wed May 18, 2005 3:02 pm
Posts: 18
This is a simplification of my actual problem in order make the description clearer.

I have a User object which can be created by filling out a form in a webapp. At that time, a UserToken object is created and stored as a property of the User object. The UserToken object contains a single property - id - which is generated via uuid.hex generator. Behind the scenes, an email is generated to the newly registered user, containing the new uuid string in the URL. When the user clicks on the URL, I can look up the user via the uuid string stored in the TOKEN_ID column, set the 'activated' flag to true, and then set the TOKEN_ID column to null so that the token can be cleared out of the database, since it is no longer needed.

I am using a simple one-to-one relation, via the many-to-one mapping - as follows:


Code:
    <class name="User" table="user">
        <id name="id" type="long" unsaved-value="null" >
            <column name="USER_ID" not-null="true"/>
            <generator class="hilo"/>
        </id>

...

        <many-to-one name="token"
                     column="TOKEN_ID"
                     unique="true"
                     cascade="all,delete-orphan" />
    </class>

    <class name="UserToken" table="usertoken">
        <id name="id" type="string" unsaved-value="null" >
            <column name="USERTOKEN_ID"
                          sql-type="char(32)"
                          not-null="true"/>
            <generator class="uuid.hex"/>
        </id>

    </class>


My problem lies in the fact that if I create a new user and a new UserToken is assigned to that user and I save the User, the new UserToken is created correctly. If I then load that User and call user.setToken(null) and then persist the user, the database shows a NULL value in the TOKEN_ID column of the user table, but the row of the usertoken table corresponding to the no-longer-used token does not get deleted. If I do this instead

Code:
    UserToken token = user.getToken();
    user.setToken(null);
    session.delete(token);


then the row gets removed from usertoken correctly. Why is the cascade not working correctly? I have tried cascade="all,delete-orphan", cascade="all-delete-orphan", and every other variation of cascade options I could think of.

--sam


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 7:39 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Re-read the documentation. There is no orphan delete for single-valued associations.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 7:50 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
I think you need this to be a one-to-one mapping. The problem is that by making it a many-to-one, you are making the token the parent of the child. Thus, when you set the user's reference to the token to null, you only remove the association to the token, not the actual token. With a one-to-one, if I understand the documentation correctly, your cascade will work as you expect:

Code:
<class name="User" table="user">
        <id name="id" type="long" unsaved-value="null" >
            <column name="USER_ID" not-null="true"/>
            <generator class="hilo"/>
        </id>

...

        <one-to-one name="token"
                     column="TOKEN_ID"
                     unique="true"
                     cascade="all,delete-orphan" />
    </class>

    <class name="UserToken" table="usertoken">
        <id name="id" type="string" unsaved-value="null" >
            <column name="USERTOKEN_ID"
                          sql-type="char(32)"
                          not-null="true"/>
            <generator class="uuid.hex"/>
        </id>

    </class>


Make sure you test this and confirm it before you use it. I'm far from a hibernate expert ;)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 7:50 pm 
Newbie

Joined: Wed May 18, 2005 3:02 pm
Posts: 18
I was afraid of that

--sam


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 7:56 pm 
Newbie

Joined: Wed May 18, 2005 3:02 pm
Posts: 18
eagle79 wrote:
With a one-to-one, if I understand the documentation correctly, your cascade will work as you expect:

Code:
<class name="User" table="user">
        <id name="id" type="long" unsaved-value="null" >
            <column name="USER_ID" not-null="true"/>
            <generator class="hilo"/>
        </id>

...

        <one-to-one name="token"
                     column="TOKEN_ID"
                     unique="true"
                     cascade="all,delete-orphan" />
    </class>

    <class name="UserToken" table="usertoken">
        <id name="id" type="string" unsaved-value="null" >
            <column name="USERTOKEN_ID"
                          sql-type="char(32)"
                          not-null="true"/>
            <generator class="uuid.hex"/>
        </id>

    </class>




Yeah, I already tried that. It doesn't work. I suspect Gavin nailed the problem. I'd have to make a collection of UserTokens in the user object, and then orphans would be deleted. I can't get any one-to-one mapping to actually function with hibernate. I either get illegal XML exceptions during schema export (because of the 'column' attribute), or else no column gets created in the user object to associate with the UserToken. I'm not sure just how one-to-one is supposed to be used, yet, but it sure ain't here.

I'm just going to explicitly delete the UserToken object via session.delete() for now.

--sam


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 8:00 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
We really, really, really don't like people posting here who have not read the documentation!

http://www.hibernate.org/hib_docs/v3/re ... tional-121

This explains clearly exactly how to do one-to-one associations. (No, you can't have orphan delete.)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 8:02 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Quote:
I suspect Gavin nailed the problem. I'd have to make a collection of UserTokens in the user object, and then orphans would be deleted.

Yep, I started my post before he answered. Kinda wish I'd waited. Gavin, dammit, quit knowing so much! You make me look like an ass! ;) Ah, but I guess I do that myself...

Quote:
I'm just going to explicitly delete the UserToken object via session.delete() for now.


Now that's a solutions that will always work :-)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 9:34 pm 
Newbie

Joined: Wed May 18, 2005 3:02 pm
Posts: 18
gavin wrote:
We really, really, really don't like people posting here who have not read the documentation!



And we really, really, really don't like moderators who assume the worst about everyone and everything and seem to delight in lambasting new users about it. I DID read the documentation - thoroughly, AND the Hibernate in action book, and I played around with a variety of solutions before posting my query. Hell, I read H-i-A cover to cover before I wrote a single line of Hibernate code. The docs aren't exactly clear to someone who isn't deeply familiar with Hibernate. I'm sure it all makes perfect sense to you, but to someone who is using it as more than just a syntax reference, it isn't so easy.

Take a look at 6.1.10 and tell me that that makes it clear that delete-orphan isn't available in the context in which I have had my troubles. I sure don['t see where it does. It specifies it as an option, and makes no mention of a special case. Even 11.11 (referenced by 6.1.10) isn't entirely clear. It kind of hints at the limitation you pointed out, but doesn't really make it explicit, which is exactly why I posted my question. I was looking for elaboration on the muddy explanation in 11.11

Incidentally, why do I see "all-delete-orphan" referenced in some locations (online) and "all, delete-orphan" in others (docs). The DTD seems to accept either, and the docs don't seem to deprecate the first one, even though they seem to only use the second one. Some clarity on that point wouldn't go amiss, either.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 9:48 pm 
Newbie

Joined: Wed May 18, 2005 3:02 pm
Posts: 18
gavin wrote:
This explains clearly exactly how to do one-to-one associations. (No, you can't have orphan delete.)


I would have thought that the content of my original post would have made it abundantly clear that i had read the page in question. Obviously, that page is much clearer for you than for me. Note that my own example code uses the first example from that page. Note also that NO mention is made of the fact that delete-orphan would be unavailable in that first example.

The second example appears to me to limit the key of the child object to be equal to the key of the parent object (with a foreign key linking them), so that no extra column is necessary. That doesn't work for me, since I have no interest in making the key sent in the email as predictable as the user's id, so that solution doesn't work for me. I attempted to use one-to-one in other ways (trying to force the use of an extra column in the parent object and a unique key in the child), which don't appear to be explicitly forbidden by the the docs, and had no success, so I mentioned it. In response, you got on my case for not reading the docs?

--sam


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 9:52 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Quote:
And we really, really, really don't like moderators who assume the worst about everyone and everything and seem to delight in lambasting new users about it.


I have to agree with this. I have read the documentation. In fact, I just completed reading Hibernate in Action cover to cover myself and I've probably read (not skimmed -- read) most of the reference manual as well. HIA is probably one of the most influential and best-written software-related books I've ever read. It's made me "a believer" -- both in ORM in general and in hibernate in particular. But reading is not the same as complete perfect understanding and memorization. I've mentioned this to you before: there's a lot of documentation for Hibernate. Even HIA admits that there's a steep learning curve to hibernate.

Why can't you understand that the fact that you know hibernate so completely intimately doesn't mean that all users will be able to just by reading the documentation? It will take literally years for anyone to gain the level of expertise and knowledge of Hibernate that you seem to expect.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 12:22 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Guys, my comment was in response to this rantishy stuff:

Quote:
I can't get any one-to-one mapping to actually function with hibernate. I either get illegal XML exceptions during schema export (because of the 'column' attribute), or else no column gets created in the user object to associate with the UserToken. I'm not sure just how one-to-one is supposed to be used, yet, but it sure ain't here.


Don't you see that writing stuff like this, in this tone, is kinda insulting and frustrating to us? Especially when all you have to do to make it work is exactly follow the example I quoted from the documentation, or look at some other examples in the test packages? You probably didn't mean to be insulting, but think how it sounds to me... Yes, I am over-sensitive; that's because it's my work you're talking about.

I was actually not refering to your comments about orphan delete, which I after checking I have to agree is a little less than explicit in the HB3 docs (it used to be clearer in the 2.1 docs). You see, orphan delete is basically sugar. You certainly don't need it to, quote "get any one-to-one mapping to actually function".

If you guys can keep the frustrated tone out of your posts, you'll find that we will be much less likely to get frustrated ourselves.

Anyway, I'm sorry for saying you didn't read the docs when you actually did, that's certainly not fair.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 7:01 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Quote:
Don't you see that writing stuff like this, in this tone, is kinda insulting and frustrating to us? Especially when all you have to do to make it work is exactly follow the example I quoted from the documentation, or look at some other examples in the test packages? You probably didn't mean to be insulting, but think how it sounds to me... Yes, I am over-sensitive; that's because it's my work you're talking about.


Well, now, that makes sense to me. I certainly know how touchy I can get about my work, so I can understand your position. It is why, even when reprimanded for not reading documentation in one of my earliest posts, I tried to remain respectful in my reply. The service that hibernate offers to us (for free!) is incredible, and I do not wish to be anything less than grateful. But I do try very hard to understand how it works and all of the documentation. Being accused of not reading docs when I have (but either don't remember where I read it, when I read it, or even that I read it) can be just as frustrating: that's my work you're talking about. I will strive harder to remember your position in my posts.

Now, as for this case, to summarize:
- no singe-valued relationship (either <many-to-one> or <one-to-one>) may specify delete-orphan in its cascade type.
- the correct solution to "allow" this behavior is to change the association (user.setToken(null)) and directly delete the referenced entity using session.delete()

Are these correct?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 1:29 pm 
Newbie

Joined: Wed May 18, 2005 3:02 pm
Posts: 18
Speaking of which, if you are open to some constructive (I hope) criticism of the H-i-A book (if not, stop reading now!), I think what it is lacking most is a chapter that discusses how things work internally. I like to understand what is going on below the programmer API, so that I can take that knowledge into account when writing my own software using that API. I'll delve into developer docs and the source code eventually, but a high-level introductory overview as part of the user's guide (and HIA) would be appropriate.

And while I'm criticizing, my only other problem with the book was the relationship between chapter 3 and chapter 6. I felt there was not enough overlap of the content between those two chapters. Chapter 3 frequently mentioned that some concepts would be introduced or discussed more thoroughly in chapter 6, so I read through chapter 3 as though it were something of a high level overview of object mapping. I was expecting chapter 6 to then go through mapping concepts in depth, including the concepts we had already seen in chapter 3. Instead, I discovered that chapter 6 was picking up where chapter 3 had left off (a week or more prior, in my case), rather than re-introducing the chapter 3 concepts in more detail before delving into more advanced concepts. I wound up having to do a lot of flipping between the chapters in order to get the complete picture. It would be much more useful to have a single chapter that covers all mapping concepts, making the book much more useful as a reference, too, even if that means some redundancy with an earlier introductory chapter. I still find myself flipping between the two chapters quite a bit. I suspect that, eventually, the simpler concepts from chapter 3 will become second nature and I'll stop visiting that chapter, but for the rank beginner, the separation definitely makes comprehension more difficult. Basically, about halfway through chapter 6, I realized that I needed to go back and reread chapter 3, since I'd forgotten much of the detail while going through chapters 4 and 5. Then I had to reread chapter 6 again.

Given that getting the mapping right is the single most important piece of getting an application that works and scales well, it is worth making sure that those concepts are explained with utmost clarity. RIght now, I find that mapping is the concept covered least well by the documentation that I've read. Which isn't to say that it is bad, just that it is the weakest section of the standard documentation. I haven't read all the content on the wiki yet, so it could be that there is clarity offered there that I haven't found elsewhere.

--sam


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 29, 2005 8:59 pm 
Beginner
Beginner

Joined: Thu Jul 28, 2005 6:40 pm
Posts: 29
Hi;

Having just started on Hibernate a couple of days ago - but having a lot of experience in ORM, EJBs, etc (in the old EJB 1.0 days basically wrote the equivilent of a lot of the EJB 2.0 functionality at one company long before EJB 2.0 was defined) I figured I'd put in my $0.02 worth.

I think the hibernate design is brilliant. And I think the HiA book is well written. But it's not totally clear in places. And in many places the samples are incomplete, not just with a ... for parts, but it's just the xml with no associated java or vice-versa.

And so ine is left making assumptions that are not always correct. And that gets difficult to figure out. I really wish there were very very very simple samples for each common case. In most cases that would be a class with a PK and a string. A sub-class would add a single property. And then listing the full xml and java for that setup.

Again, this is not to say the present documentation is bad - it isn't. But in many cases it gets you 98% of the way there and I think that actually is more frustrating than bad documentation - because you are so close, but you can't figure out that last 2%.

thanks - dave


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 29, 2005 9:02 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
There are many, many, many examples in the test directory.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.