Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Hibernate中,无状态会话是否阻止在具有渴望加入时过滤出重复项_Java_Hibernate_Hibernate 4.x - Fatal编程技术网

Java 在Hibernate中,无状态会话是否阻止在具有渴望加入时过滤出重复项

Java 在Hibernate中,无状态会话是否阻止在具有渴望加入时过滤出重复项,java,hibernate,hibernate-4.x,Java,Hibernate,Hibernate 4.x,我有一个歌曲班,里面有一系列的连续剧 e、 g @OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.ALL}) @JoinColumn(name=“recNo”) 私人物品清单; 我正在使用Hibernate4.3.11和DB2数据库,我有一个查询,通过主键和coverArt检索歌曲列表 public static List<Song> getSongsWithCoverArtFromDatabase(Session sessi

我有一个歌曲班,里面有一系列的连续剧

e、 g

@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.ALL})
@JoinColumn(name=“recNo”)
私人物品清单;
我正在使用Hibernate4.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);
        }
    }
公共静态列表GetSongSwithCovertFromDatabase(会话,列表ID)
{
尝试
{
标准c=会话
.createCriteria(Song.class)
.setFetchMode(“covertars”,FetchMode.JOIN)
.setResultTransformer(标准.DISTINCT\u ROOT\u实体)
.添加(限制。在(“recNo”,ID));
列表歌曲=c.List();
返回歌曲;
}
捕获(例外e)
{
MainWindow.logger.log(Level.severy,“加载到数据库失败:”+e.getMessage(),e);
抛出新的运行时异常(e);
}
}
请注意,我们已将获取模式设置为在Covertart集合上加入,并且需要设置setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY),否则,如果我们有一首包含两个Covertart记录的歌曲,我们将返回两个歌曲对象。但是当使用Criteria.DISTINCT\u ROOT\u实体Hibernate时,它会正确地返回一首包含两个covertart的歌曲

然而,我刚刚尝试做同样的事情,但是使用了一个无状态会话。理由是,我只是试图选择数据来创建报告,但我希望最大限度地提高速度,最大限度地减少内存消耗

   public static List<Song> getSongsWithCoverArtFromDatabase(StatelessSession 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);
        }
    }
公共静态列表GetSongSwithCovertFromDatabase(无状态会话,列表ID)
{
尝试
{
标准c=会话
.createCriteria(Song.class)
.setFetchMode(“covertars”,FetchMode.JOIN)
.setResultTransformer(标准.DISTINCT\u ROOT\u实体)
.添加(限制。在(“recNo”,ID));
列表歌曲=c.List();
返回歌曲;
}
捕获(例外e)
{
MainWindow.logger.log(Level.severy,“加载到数据库失败:”+e.getMessage(),e);
抛出新的运行时异常(e);
}
}
这似乎忽略了.setResultTransformer(Criteria.DISTINCT\u ROOT\u实体)并返回重复的行


这是一个已知的错误,它的行为是什么意思

看起来这是Hibernate中实现
无状态SessionImpl
的方式中的一个缺点,但是可能也会有一个修复方案

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

如果感兴趣,您可以在
加载程序的Hibernate源代码中看到这一点。然后,根据会话的类型,与PersistenceContext对话,但只返回null。然而,这种方法有一个缺点,看起来是做正确的事情。提交是的一部分,它表示修复版本是Hibernate 5.3.11和5.4.4-在撰写本文时未显示在中

同时,一个解决方案是推出自己的
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());
    }
}
公共类DistinctSongResultTransformer实现ResultTransformer{
private ResultTransformer defaultTransformer=Criteria.DISTINCT\u ROOT\u实体;
@凌驾
公共对象转换元组(对象[]元组,字符串[]别名){
返回defaultTransformer.transformTuple(tuple,别名);
}
@抑制警告(“原始类型”)
@凌驾
公共列表列表(列表集合){
Map distinctSongs=newlinkedhashmap();
用于(对象:集合){
Song=(Song)对象;
distinctSongs.putIfAbsent(song.getId(),song);
}
返回新的ArrayList(distinctSongs.values());
}
}
不同之处在于,普通的
DistinctRootEntityResultTransformer
假设会话中只有实体的唯一实例-您可以看到比较


显然,还有空间使该示例更具可重用性,特别是抽象
getId()

谢谢你的详细回答,我不明白的是,既然HIbernate意味着隐藏数据库复杂性,如果我有一个具有一对多关联的对象,为什么它在默认情况下不处理它,“我越是使用Hibernate,我就越是对它感到失望。”@PaulTaylor——根据我的经验,大多数框架使简单的事情变得更容易,但偏离支持的功能则困难得多(可能我们期望太多,因为简单的东西太容易了)。Hibernate就是一个典型的例子。出于同样的原因,我认识的大多数人都与它有爱恨关系是的,但是我很困惑,如果我在这里做了一些奇怪的事情,因为在我看来,使用EAGER检索对象列表及其相关的1:M似乎是一个相当标准的用例?
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());
    }
}