java-在Hibernate中,当有EAGER JOIN时,StatelessSession是否防止过滤出重复项

我有一个Song类,其中包含CoverArts的集合

例如

@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.ALL})
@JoinColumn(name = "recNo")
private List<CoverArt> coverArts;

并且正在使用Hibernate 4.3.11和DB2数据库,并且我有这个查询,用于按其主键及其CoverArt检索歌曲列表.

public static List<Song> getSongsWithCoverArtFromDatabase(Session session,List<Integer> ids)
    {
        try
        {
            Criteria c = session
                    .createCriteria(Song.class)
                    .setFetchMode("coverArts",FetchMode.JOIN)
                    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                    .add(Restrictions.in("recNo",ids));
            List<Song> songs = c.list();
            return songs;
        }
        catch (Exception e)
        {
            MainWindow.logger.log(Level.SEVERE,"Failed LoadSongToDatabase:" + e.getMessage(),e);
            throw new RuntimeException(e);
        }
    }

请注意,我们已经在coverArts集合上将获取模式设置为JOIN,并且需要设置setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY),否则,如果我们有一首带有两个Coverart记录的歌曲,我们将返回两个Song对象.但是,当使用Criteria.DISTINCT_ROOT_ENTITY时,Hibernate将正确返回一首包含两个CoverArt的乐曲.

但是我只是尝试使用StatelessSession做同样的事情.原因是我只是试图选择用于创建报告的数据,但是我想最大化速度并最小化内存消耗,但是

   public static List<Song> getSongsWithCoverArtFromDatabase(StatelessSession session,e);
            throw new RuntimeException(e);
        }
    }

这似乎忽略了.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)并返回重复行.

这是一个已知的错误,它意味着什么?

最佳答案
看起来这在Hibernate中实现StatelessSessionImpl的方式是有缺陷的,但是也可能正在解决此问题.

显然,使用FetchMode.JOIN,SQL查询将在两个表之间(左外侧)联接,因此每首歌曲可能返回几行.通常,Hibernate解析通过其PersistenceContext返回的每一行.

如果感兴趣的话,您可以在Loader here的Hibernate源代码中看到它.然后,根据Session的类型,@L_502_1@与PersistenceContext进行通信,但是StatelessSessionImpl.getEntityUsingInterceptor()只是返回null.但是,此方法有一个later commit看起来可以做正确的事.提交是HHH-11147的一部分,其中说修订版本是Hibernate 5.3.11和5.4.4-在撰写本文时未显示Maven repo中.

同时,一种解决方法是投放自己的ResultTransformer.这是一个相当“关键”的例子:

public class DistinctSongResultTransformer implements ResultTransformer {
    private ResultTransformer defaultTransformer = Criteria.DISTINCT_ROOT_ENTITY;

    @Override
    public Object transformTuple(Object[] tuple,String[] aliases) {
        return defaultTransformer.transformTuple(tuple,aliases);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public List transformList(List collection) {
        Map<Integer,Song> distinctSongs = new LinkedHashMap<>();
        for (Object object : collection) {
            Song song = (Song) object;
            distinctSongs.putIfAbsent(song.getId(),song);
        }
        return new ArrayList<>(distinctSongs.values());
    }
}

不同之处在于正常的DistinctRootEntityResultTransformer假定会话中将只有该实体的唯一实例-您可以看到比较here.

显然,还有空间使该示例也更具可重用性,尤其是抽象getId()的空间.

相关文章

ArrayList简介:ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增...
一、进程与线程 进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。 线程...
本文为博客园作者所写:&#160;一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 简单的一个类...
#############java面向对象详解#############1、面向对象基本概念2、类与对象3、类和对象的定义格式4、...
一、什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错。在java中,阻止当前方法或作用域...
Collection接口 Collection接口 Collection接口 Collection是最基本的集合接口,一个Collection代表一组...