EAGER持って参加するときにHibernateんStatelessSession防ぐには重複を除外

ポール・テイラー:

私が持っているのコレクション含んでいるクラスCoverArt

たとえば、

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

そして、休止状態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);
        }
    }

我々はセットがするフェッチモードを持って注意してください、JOINcoverArtsのコレクション、そして私たちは集合sに必要であることをetResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 我々は2つのcoverartレコードを持つ曲があったらそう、我々は2ソング返さバックオブジェクトを取得します。使用している場合でも、Criteria.DISTINCT_ROOT_ENTITY休止状態を正しく2 coverArtsを含む1ソングを返します。

しかし、私はちょうど同じことを実行しようとしましたが、StatelessSessionを使用しています。推論は、しかし、私はレポートを作成するためのデータを選択しようとしていると私は最大化の速度をしたいとメモリ消費を最小限に抑えること

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

これは、リターンの重複行をANDS .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)を無視しているようです。

これは、それが動作するように意図方法、既知のバグですか?

df778899:

このように見えますが邪魔に欠点でStatelessSessionImpl休止状態で実装されていますが、修正は、あまりにも途中であるかもしれません...

明らかにしてFetchMode.JOIN、SQLクエリを2つのテーブル間で結ぶ(外側左)されるので、曲ごとに複数の行を返すことがあります。通常、Hibernateはそれを介して返された各列を解決しますPersistenceContext

興味を持っている場合は、のために、Hibernateのソースでこれを見ることができますLoader ここにその後、の種類に応じてSessionSessionImpl.getEntityUsingInterceptor()への交渉PersistenceContextが、StatelessSessionImpl.getEntityUsingInterceptor()だけを返すのはnull。しかし、そこにある、後にコミットルックスが正しいことを行うためにことをこのメソッドに。一部であり、コミットHHH-11147に表示されない- 、修正バージョンは休止状態5.3.11と5.4.4あると言うMavenのレポを書いている時点で。

一方で、1つの修正が独自のロールすることであろう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あなたは、比較見ることができます-だけのセッション内のエンティティの固有のインスタンスが存在することになると仮定し、ここで

明らかに、特に抽象的に、あまりにもその一例が、より再利用可能にする余地がありますgetId()

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=209274&siteId=1