-->
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.  [ 9 posts ] 
Author Message
 Post subject: bulk delete with paths in the where clause
PostPosted: Thu Sep 22, 2005 11:12 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Hibernate version: 3.0.5

I just had a developer come to me attempting to do a query something like this:
Code:
delete from Address where owner.lastName = ?

This doesn't seem to work because of the path operation in the where clause (note, Address has a many-to-one association through its 'owner' property to a Person object -- a much simplified example, but it illustrates the point).

At first glance, I didn't understand why. Then I started considering what the SQL would look like. Maybe something like this:
Code:
delete from Address a where a.owner_id in (select id from Owner o where o.lastName = ?)

The solution, of course, is that I should mimic this in my HQL:
Code:
delete from Address where owner in (from Owner o where o.lastName = ?)

I tried to look this up in the documentation, and I noticed this:
Quote:
No joins (either implicit or explicit) can be specified in a bulk HQL query

So here's my questions:
1) Does using a path (owner.lastName) in a bulk delete where clause constitute an "implicit join" (which I assume it does)?
2) Would it be possible to more explicitly state this in section 14.3 of the reference? The text was (at least to me) not immediately obvious until after I had run into the problem.
3) Is this likely (or even possible) to become a feature in a later version of hibernate?


Top
 Profile  
 
 Post subject: it is property
PostPosted: Fri Sep 23, 2005 5:33 pm 
Expert
Expert

Joined: Fri Jul 22, 2005 2:42 pm
Posts: 670
Location: Seattle, WA
Should be
Code:
delete from Address as add where add.owner.lastName = ?

_________________
--------------
Konstantin

SourceLabs - dependable OpenSource systems


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 23, 2005 7:28 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
According to the reference manual here: http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#batch-direct,
Quote:
There can only be a single class named in the from-clause, and it cannot have an alias.


Nonetheless, I tried a similar query anyway:
Code:
delete from Address as add where add.owner.firstName = :name


and got this:
Code:
org.hibernate.hql.ast.QuerySyntaxError: unexpected token: as near line 1, column 58 [delete from net.vickerscraven.learning.hibernate.Address as add where add.owner.firstName = :name]
   at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:63)
   at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:215)
   at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:127)
   at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:83)
   at org.hibernate.impl.SessionFactoryImpl.getQuery(SessionFactoryImpl.java:427)
   at org.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:884)
   at org.hibernate.impl.SessionImpl.executeUpdate(SessionImpl.java:865)
   at org.hibernate.impl.QueryImpl.executeUpdate(QueryImpl.java:89)
   at net.vickerscraven.learning.hibernate.TestHibernate.main(TestHibernate.java:106)
Caused by: line 1:58: unexpected token: as
   at org.hibernate.hql.antlr.HqlBaseParser.deleteStatement(HqlBaseParser.java:242)
   at org.hibernate.hql.antlr.HqlBaseParser.statement(HqlBaseParser.java:139)
   at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:209)
   ... 7 more


Top
 Profile  
 
 Post subject: oops!
PostPosted: Fri Sep 23, 2005 8:48 pm 
Expert
Expert

Joined: Fri Jul 22, 2005 2:42 pm
Posts: 670
Location: Seattle, WA
You are right, my bad. Well Hibernate doc also says
Quote:
14.3

No joins (either implicit or explicit) can be specified in a bulk HQL query. Sub-queries may be used in the where-clause.


That explains why query does not work. So you I guess you have to use SQL

_________________
--------------
Konstantin

SourceLabs - dependable OpenSource systems


Top
 Profile  
 
 Post subject: Re: oops!
PostPosted: Sat Sep 24, 2005 1:15 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
kgignatyev wrote:
So you I guess you have to use SQL


Well, not quite. As I mentioned earlier, I can write some HQL that works that is more like the SQL:
Code:
delete from Address where owner in (from Owner o where o.lastName = ?)

So I don't have to resort to direct SQL.

Really, what I had in mind here, though, was to feel out whether the other syntax might be a reasonable feature. To wit:

I think we've established that using property paths in the where-clause of an HQL bulk delete doesn't work. The solution in my case was that it had to be written as an IN constraint using a subselect.

Thinking through things, I understand now why HQL does not support paths in the where-clause, but because I'm used to using paths in select statements, it never occurred to me that they wouldn't work in a bulk delete. I believe this is what the documentation means when it refers to "implicit joins":
Quote:
No joins (either implicit or explicit) can be specified in a bulk HQL query. Sub-queries may be used in the where-clause.

However, the documentation did not really make this obvious to me, and I didn't really realize the implications of the quoted text until after I ran into the problem. If nothing else comes of this thread, I would ask that whoever maintains the reference consider adding a bit more text to explicitly discuss property paths -- perhaps with an example or two.

The other goal I had was to feel out whether this could ever be a hibernate feature. I understand that it could be rather complex, as hibernate would have to know how to convert something like this:
Code:
delete from Address where owner.lastName = ?

Into SQL that uses a subquery like this:
Code:
delete from Address a where a.owner_id in (select p.id from Person p where p.lastName = ?)

You don't have to be a ORM expert to see that something like this might grow fairly complex fairly quickly. But if it could be done, I feel it would be a very useful addition to the HQL language. After all, my initial intuition was to use property paths to achieve the desired results. You can really see where this would be powerful in more complex situations. Consider:
Code:
delete from Car where brakeSystem.isABS = true and suspension.tires.maxInflationPSI = 45

The SQL for this would not be simple, but the HQL cetainly is!

That said, though, I'm not in the habit of just tossing feature requests into a project's tracking software before I know whether the change is feasible (or in this case, even possible). In fact, I usually prefer to let someone who is more involved in the project make the decision of whether it should be considered for a new feature altogether

thoughts?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 26, 2005 10:13 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
There was discussion of this as I implemented the bulk features. The basic reason for not currently allowing it is simply that alot of databases do not allow joins in delete statements (otherwise we could simply pass off the join onto the db). Now, of course, we could "interpret" the intent of the join here and munge the resulting SQL into a subquery form as you suggest, but that does not seem reasonable to me given that you can quite easily just write the query using the subquery form in the first place. Certainly, I can add some more discussion of what "implicit join" means to the docs if you really think that helps.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 26, 2005 10:42 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
steve wrote:
There was discussion of this as I implemented the bulk features. The basic reason for not currently allowing it is simply that alot of databases do not allow joins in delete statements (otherwise we could simply pass off the join onto the db). Now, of course, we could "interpret" the intent of the join here and munge the resulting SQL into a subquery form as you suggest, but that does not seem reasonable to me given that you can quite easily just write the query using the subquery form in the first place. Certainly, I can add some more discussion of what "implicit join" means to the docs if you really think that helps.


Hmmm. I fear that even "munging" (a good word!) into a subquery form would be dangerously full of subtle complications that would make it impossible to reliably do with all databases and valid HQL queries. Nonetheless, I still think this would be a beautiful feature to add to HQL. I do, of course, understand why it isn't though. Consider it a wish-list item that'll probably never happen :-)

I do think it would be great of the docs could be clarified a bit. They are clear to me now that I understand what's happening under the covers of Hibernate, but I didn't really think of owner.lastName = ? as a join at all, but rather a where-clause conditional. This of course, was shortsighted on my part, but if the docs warned me of the pothole, maybe I could have avoided the "smack-myself-in-the-head-and-say-of-course!" moment :-)

Thanks for the clarification!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 26, 2005 11:47 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
No problem. Considering we use the term "implicit join" quite a bit, I'll add a section about implicit vs. explicit joins in the HQL chapter and appropriately link to it from the HQL-bulk section.

http://opensource2.atlassian.com/projects/hibernate/browse/HHH-989


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 26, 2005 11:57 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
steve wrote:
No problem. Considering we use the term "implicit join" quite a bit, I'll add a section about implicit vs. explicit joins in the HQL chapter and appropriately link to it from the HQL-bulk section.

http://opensource2.atlassian.com/projects/hibernate/browse/HHH-989


That would be excellent. Thanks again, Steve.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

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.