HIBERNATE JBoss.org
 |  Register  | 
     
News 
About 
   Feature List 
   Road Map 
Documentation 
   Related Projects 
   External Documentation 
Download 
Forum & Mailinglists 
Support & Training 
JIRA Issue Tracking
Wiki Community Area


Hibernate Public Training Courses


Get Hibernate in Action eBook!


JavaWorld 2003 Finalist


Jolt Award 2004 Winner
      
Documentation > FAQs > Hibernate Users FAQ - Tips & Tricks

Hibernate Users FAQ - Tips & Tricks

Tips & Tricks

How can I count the number of query results without actually returning them?

( (Integer) session.iterate("select count(*) from ....").next() ).intValue()

How can I find the size of a collection without initializing it?

( (Integer) s.createFilter( collection, "select count(*)" ).iterate().next() ).intValue()

How can I order by the size of a collection?

Use a left join, together with group by

select user 
from User user
left join user.messages msg
group by user 
order by count(msg)

How can I place a condition upon a collection size?

If your database supports subselects:

from User user where size(user.messages) >= 1

If not, and in the case of a one-to-many or many-to-many association:

select user 
from User user 
join user.messages msg 
group by user 
having count(msg) >= 1

Because of the inner join, this form can't be used to return a User with zero messages, so the following form is also useful (Hibernate2 only)

select user 
from User as user
left join user.messages as msg
group by user 
having count(msg) = 0

How can I query for entities with empty collections?

Try this:

select box
from Box box
   left join box.balls ball
where ball is null

How can I sort / order collection elements?

There are three different approaches:

1. Use a SortedSet or SortedMap, specifying a comparator class in the sort attribute or <set> or <map>. This solution does a sort in memory.

2. Specify an order-by attribute of <set>, <map> or <bag>, naming a list of table columns to sort by. This solution works only in JDK 1.4+.

3. Use a filter s.filter( collection, "order by ...." )

Are collections pageable?

Query q = s.createFilter( collection, "" ); // the trivial filter
q.setMaxResults(PAGE_SIZE);
q.setFirstResult(PAGE_SIZE * pageNumber);
List page = q.list();

I have a one-to-one association between two classes. Ensuring that associated objects have matching identifiers is bugprone. Is there a better way?

In Hibernate2, simply use

<generator class="foreign">
     <param name="property">parent</param>
</generator>

For Hibernate 1.x

Yes, actually. Suppose Foo has a one-to-one reference to Bar that is never null, ie. the mapping for Foo contains

<class name="Foo" .... >
    <id name="id">
        <generator class="assigned"/> <!-- can't use an id generator here! -->
    </id>
    ....
    <one-to-one class="Bar" constrained="true"/>
</class>

You could implement Foo's identifier property to actually return the identifier of Bar by delegation (the setter would do nothing). You must use an assigned identifier mapping for Foo. Note that the identifier of the Bar must have been generated/assigned before the Foo is saved, eg.

Bar bar = new Bar();
Foo foo = new Foo();
foo.setBar(bar);
sess.save(bar);
sess.save(foo);

You can't just save foo and let bar be saved by cascade, because bar's identifier will be generated too late. ie. you can't use

Bar bar = new Bar();
Foo foo = new Foo();
foo.setBar(bar);
sess.save(foo); //ERROR!

The approach above spares you the following alternative idiom:

Bar bar = new Bar();
Foo foo = new Foo();
foo.setBar(bar);
Long id = (Long) sess.save(bar);
sess.save(foo, id);

I have a many-to-many association between two tables, but the association table has some extra columns (apart from the foreign keys). What kind of mapping should I use?

Use a composite-element to model the association table. For example, given the following association table:

create table relationship ( 
    fk_of_foo bigint not null, 
    fk_of_bar bigint not null, 
    multiplicity smallint, 
    created date )

you could use this collection mapping (inside the mapping for class Foo):

<set name="relationship">
    <key column="fk_of_foo"/>
    <composite-element class="Relationship">
        <property name="multiplicity" type="short" not-null="true"/>
        <property name="created" type="date" not-null="true"/>
        <many-to-one name="bar" class="Bar" not-null="true"/>
    </composite-element>
</set>

You may also use an <idbag> with a surrogate key column for the collection table. This would allow you to have nullable columns.

In an MVC application, how can we ensure that all proxies and lazy collections will be initialized when the view tries to access them?

One possible approach is to leave the session open (and transaction uncommitted) when forwarding to the view. The session/transaction would be closed/committed after the view is rendered in, for example, a servlet filter (another example would by to use the ModelLifetime.discard() callback in Maverick). One difficulty with this approach is making sure the session/transaction is closed/rolled back if an exception occurs rendering the view.

Another approach is to simply force initialization of all needed objects using Hibernate.initialize(). This is often more straightforward than it sounds.

How can I bind a dynamic list of values into an in query expression?

Query q = s.createQuery("from foo in class Foo where foo.id in (:id_list)");
q.setParameterList("id_list", fooIdList);
List foos = q.list();

How can I bind properties of a JavaBean to named query parameters?

Query q = s.createQuery("from foo in class Foo where foo.name=:name and foo.size=:size");
q.setProperties(fooBean); // fooBean has getName() and getSize()
List foos = q.list();

Can I map an inner class?

You may persist any static inner class. You should specify the class name using the standard form ie. eg.Foo$Bar

How can I assign a default value to a property when the database column is null?

Use a UserType.

How can I trucate String data?

Use a UserType.

How can I convert the type of a property to/from the database column type?

Use a UserType.

How can I get access to O/R mapping information such as table and column names at runtime?

This information is available via the Configuration object. For example, entity mappings may be obtained using Configuration.getClassMapping(). It is even possible to manipulate this metamodel at runtime and then build a new SessionFactory.

How can I create an association to an entity without fetching that entity from the database (if I know the identifier)?

If the entity is proxyable (lazy="true"), simply use load(). The following code does not result in any SELECT statement:

Item itemProxy = (Item) session.load(Item.class, itemId);
Bid bid = new Bid(user, amount, itemProxy);
session.save(bid);

How can I retrieve the identifier of an associated object, without fetching the association?

Just do it! The following code does not result in any SELECT statement, even if the item association is lazy.

Long itemId = bid.getItem().getId();
      

coWiki