Hibernate,获取一对多的最佳方法

时间:2011-06-20 12:01:11

标签: hibernate jpa-2.0 java-ee-6

背景

我最近使用JBoss和Hibernate创建了一个新的Java EE 6对象。从早期的项目中,我有使用Eclipselink作为JPA提供商的Glassfish经验。

在我之前的项目中,我将所有关系映射为Lists,当我知道我需要从关系中获取大批量数据时,我会获取所需的数据。如果我忘了取东西,稍后可能会从视图/控制器层延迟加载。使用Hibernate,我发现在延迟加载和提取方面,事情的工作方式与其他提供程序的工作方式完全不同(不允许在EJB外部进行延迟加载,不允许多次提取/预加载)。

问题

使用Hibernate处理提取的事实标准是什么?我看到了一些可能性:

  • 如前所述将一对多映射到List,但使用@IndexColumn。使用通过条件api获取,导致连接 优点:设计看起来不错 缺点:需要更改表结构,连接具有非常糟糕的性能和深层结构。

  • 将一对多映射到Set。允许多次抓取 优点:不需要@IndexColumn 缺点:没有排序,通常需要将其转换为List并返回使用许多需要列表的JSF 2组件。

  • 将一对多映射到List并在实体类上使用特定于hibernate的@Fetch批注,主要使用FetchMode.SUBSELECT和延迟加载。 EJB方法不会使用提取,而只是进行简单的选择,然后手动读取所选对象和我们想要获取的“延迟加载”关系。
    优点:由于子选择,性能非常好。不需要@IndexColumn。
    缺点:非常奇怪的EJB方法,因为需要手动加载关系(例如见下文)。

#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;
    }

如果想要在控制器/视图层中使用加载了关系的几个实体这样的常见场景,那么真的没有更好的选择吗?

1 个答案:

答案 0 :(得分:1)

我建议使用这些套装,原因如下:

1)你不要触摸架构。最好不要使架构保持原状

2)您可以在从db中获取集合后对它们进行排序。例如:

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

3)使用任何类型的映射(xml或注释)都可以懒惰和急切地获取集合