1
votes

Background

I recently started a new Java EE 6 object, using JBoss and Hibernate. From earlier projects, I have experience with Glassfish using Eclipselink as JPA provider.

In my earlier project, I mapped up all relations as Lists, and when I knew I was going to need large batches of data from a relationship, I would fetch the data needed. If I forgot to fetch something, it could be lazy loaded later from the view/controller layer. Using Hibernate, I discovered that things works very differently than other providers regarding lazy loading and fetches (not allowing lazy loading outside an EJB, not allowing more than a single fetch/eager load).

Question

What is the de-facto standard of handling fetching with Hibernate? I see a few possibilities:

  • Map one-to-many to List as earlier, but using @IndexColumn. Use fetch through criteria api, causing joins.
    Pros: design looks decent.
    Cons: need to change table structure, joins have very bad performance with a deep structure.

  • Map one-to-many to Set. Allows multiple fetches.
    Pros: no need for @IndexColumn.
    Cons: No sorting, would often need to convert it to a List and back to use many JSF 2 components that wants a list.

  • Map one-to-many to List and use hibernate specific @Fetch annotation on entity classes, mostly with FetchMode.SUBSELECT, together with lazy loading. EJB methods would not use fetches, but simply make a simple select, then manually read from the selected object and "lazy load" relations that we want to fetch.
    Pros: very good performance due to subselects. No need for @IndexColumn.
    Cons: very weird-looking looking EJB methods, due to the need to manually load relationsships (see below for example).

Example of #3

   public List<User> findAllUsers(){
        CriteriaQuery<User> cq = cb.createQuery(User.class);
        Root<User> from = cq.from(User.class);
        List<User> users = em.createQuery(cq).getResultList();
        if(users.isEmpty())
            return users;
        users.get(0).getRoleList().size();
        users.get(0).getUserHasCompanyList().size();
        users.get(0).getUserInUnitList().size();
        return users;
    }

With such a common scenario as wanting a few entities loaded with relationships to use in the controller/view layer, is there really no better alternative?

1

1 Answers

1
votes

I would recommend using the sets for the following reasons:

1) you DO NOT touch the schema. it's always best practice to leave the schema untouched

2) you can sort the sets after fetching them from the db. For example:

List<MyType> list = query.list();
Collections.sort( list, myComparator );

3) sets can be both lazily and eagerly fetched with any type of mapping (xml or annotations)