-->
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.  [ 5 posts ] 
Author Message
 Post subject: HQL Join
PostPosted: Mon Jul 10, 2006 4:53 pm 
Beginner
Beginner

Joined: Sat Apr 15, 2006 12:49 pm
Posts: 20
Location: austria
Hi,

is it possible to provide a 'WHERE' statement for collections in HQL queries so that I can limit the rows returned by an association 'left joined' in a HQL query?

I.e. I'd like to do something like the following:
Code:
SELECT new SomeDto(item.itemId, item.defaultDescription, tr.translation)
FROM Item item
LEFT JOIN (FROM item.translations tr WHERE tr.locale = de_DE)


This should then lead to some SQL syntax similar to:

Code:
SELECT item.itemId, item.description, item.defaultDescription, t.translatedDescription
FROM tblItem item
LEFT OUTER JOIN (
SELECT *
FROM tblItemTranslation
WHERE locale = 'de_DE'
) AS t ON item.itemId = t.item_fk


I know this does not work, but just to express what I'm looking for. The reason I need this, is that I want to retrieve both an Item's translation and the Item itself within one query. Furthermore if no translation is available, the translation string should be NULL (instead of not returning the row at all which would be the case if I used a normal WHERE containing the locale on the whole query).

The resultsset would then look like:
Code:
1 | Item A | Artikel A
2 | Item B | NULL

with having a translation available for item A, but not for item B.

Thx,

john


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 11, 2006 11:55 am 
Beginner
Beginner

Joined: Mon Jul 26, 2004 4:29 pm
Posts: 45
Location: TX, USA
Hi,

The answer is yes.

I don't claim to be an expert, but I don't understand the reason for the sub-select in your SQL. You are selecting everything from the table in your sub-select, which should be no different than just joining on the table:

SQL:

Code:
SELECT item.itemId, item.description, item.defaultDescription, t.translatedDescription
FROM tblItem item
LEFT OUTER JOIN tblItemTranslation AS t ON item.itemId = t.item_fk
WHERE locale = 'de_DE'


This would mean the HQL would be something like:

HQL:

Code:
FROM Item item
LEFT JOIN itemtranslations tr
WHERE tr.locale = de_DE


The other thing that occurs to me is that if you have mapped both of the tables in, say, a bi-directional one-to-many/many-to-one then a query with an outer join appears unnecessary to me.

Take the example of a department table and an employee table. The SQL would look like:

Code:
create table department (
   department_id identity
  ,department_desc varchar(30));
 
create table employee (
   employee_id identity
  ,name varchar(30)
  ,department_id integer
  ,foreign key (department_id) references department (department_id));


Here the employee has a foreign key which refereneces the department. These can be mapped as follows:

Code:
    <class name="Employee" table="EMPLOYEE">
        <id name="employeeId" column="EMPLOYEE_ID">
            <generator class="native" />
        </id>
        <many-to-one name="department" column="DEPARTMENT_ID" not-null="false" lazy="false" />
        <property name="name" column="NAME" />
    </class>

    <class name="Department" table="DEPARTMENT">
        <id name="departmentId" column="DEPARTMENT_ID">
            <generator class="native" />
        </id>
        <property name="departmentDesc" column="DEPARTMENT_DESC" />
        <set name="employees" inverse="true" lazy="false">
            <key column="DEPARTMENT_ID" />
            <one-to-many class="Employee" />
        </set>
    </class>


Now if you wrote a function to return all departments like this:

(using Spring's HibernateTemplate)
Code:
    public List getAllDepartments() {
        return getHibernateTemplate().find("from egjoin.Department dept");
    }


Then you could iterate through the departments like so:

Code:
        lgr.info("Let's list Departments");
        List departments = departmentDao.getAllDepartments();
        it = departments.iterator();
        while (it.hasNext()) {
            Department department = (Department) it.next();
            lgr.info("Department is: " + department);
            Double sum = 0.0;
            Iterator empIt = department.getEmployees().iterator();
            while (empIt.hasNext()) {
                Employee employee = (Employee) empIt.next();
                lgr.info("\tAssociated Employee: " + employee);
            }
        }


And this code will list all departments whether or not there are any employees associated with them...

Code:
INFO  Main - Department is: Department[0,San Fransisco]
INFO  Main -    Associated Employee: Employee[0,Smith]
INFO  Main - Department is: Department[1,New York]
INFO  Main -    Associated Employee: Employee[1,Smith]
INFO  Main - Department is: Department[2,Chicago]


The Chicago department has no employees, but is listed along with the others... the same effect as an SQL left outer join would have had.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 9:42 am 
Newbie

Joined: Wed Jul 12, 2006 9:36 am
Posts: 1
mo, the reason he had the sub select was to ensure he the left join worked. (i.e., if the item has an english transalation, but no german one, he still wants to get the item, just without any "translation" value)


Anyhoo, med, you were real close with your first query, you just needed to use the "with" clause (since that will limit the "joined" objects, before the join, and thus get you the appropriate nulls

HQL:
SELECT new SomeDto(item.itemId, item.defaultDescription, tr.translation)
FROM Item item
LEFT JOIN item.translations tr With tr.locale = de_DE


Note, there are all sorts of limitations on the with clause. for instance, you can't do "tr.locale.componentobject.id=something", you can only reference properties that are on the same table as the "joined" object.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 9:29 pm 
Beginner
Beginner

Joined: Mon Jul 26, 2004 4:29 pm
Posts: 45
Location: TX, USA
Cool. Thanks for the info. I figured there was a reason I wasn't aware of.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 3:15 am 
Beginner
Beginner

Joined: Sat Apr 15, 2006 12:49 pm
Posts: 20
Location: austria
thanks for the info about the 'WITH' clause, mbirenbaum! works fine for the case I mentioned!

but what if I don't have an attribute connecting the two tables? I.e. if I have some translation table including the translation values but no association going from my translated entity to the translation table. I therefore can't use 'LEFT JOIN item.translations tr With tr.locale = de_DE ' because no property 'translations' exists. Is there a possibilty in HQL to make a JOIN on an arbitraty table or can I only join tables mapped via some kind of association?

thx,

john


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.