【问题标题】:Duplicate rows using Hibernate native query with return-join使用带有 return-join 的 Hibernate 本机查询复制行
【发布时间】:2012-08-17 18:02:59
【问题描述】:

我使用的是 Hibernate (3.3.x),我有两个实体:

public class FtChargeAcctPkgDtl {
    private FtChargeAcctPkgDtlId id;
    private Set<FtChargeAcctPkgRate> ftChargeAcctPkgRates;
}

public class FtChargeAcctPkgRate {
    private FtChargeAcctPkgRateId id;
}

(为简单起见,保留其他属性和设置器)。

我有一个本地查询:

<sql-query name="readSymbolsFtPackages">
    <return alias="pkgDtl" class="somepackage.FtChargeAcctPkgDtl"/>

    <return-join alias="pkgRate" property="pkgDtl.ftChargeAcctPkgRates"/>
    <![CDATA[
    SELECT {pkgDtl.*}, {pkgRate.*}

    FROM ft_charge_acct_pkg_dtl pkgDtl

    JOIN ft_charge_acct_pkg_rate pkgRate
      ON pkgRate.master_seq_no = pkgDtl.master_seq_no -- just primary key
        AND pkgRate.pkg_id = pkgDtl.pkg_id
]]>
</sql-query>

该查询应该(我希望它)为 pkgDtl 中的每个项目返回一行,并填写 FtChargeAcctPkgDtl#ftChargeAcctPkgRates。但实际上它为 ft_charge_acct_pkg_rate 中的每个项目返回一行。

假设主 (pkgDtl) 表中有 5 行,连接表中有 50 行(单个 pkgDtl 的平均 10 pkgRates)。当我使用

调用查询时
Query query = session.getNamedQuery("readSymbolsFtPackages");
query.list();

我得到 50 行。然而,其中 45 个是重复的。我想得到这 5 个 pkgDtls 并且每个都填入 pkdRates。有没有办法在休眠中做到这一点?

【问题讨论】:

  • 使用 select distict 没有帮助吗?为什么不修改查询以完全满足您的需求?
  • 嗨@Eduard,数据库不同将无济于事,因为数据库行不同。但是当 hibernate 将 DB 行转换为一组 java 对象时,存在重复。

标签: hibernate nativequery


【解决方案1】:

用途:

Query query = session.getNamedQuery("readSymbolsFtPackages");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
query.list();

问候

【讨论】:

  • 嗨,我似乎把我的问题简化得太多了。我在查询中有几个返回别名,因为 DISTINCT_ROOT_ENTITY 只返回最后一列,这对我没有帮助。
  • 不错的解决方案,但实际上方法 setResultTransformer 已被弃用。但是直到 Hibernate 6 将按原样工作。关注:vladmihalcea.com/2017/04/03/…
【解决方案2】:

受@manu-navarro 的启发,我带来了这个变压器:

/**
 * Transformer, that returns only distinct rows from the set.
 *
 * Distinction is based on all &lt;return alias/&gt; items.
 */
public class DistinctResultTransformer extends BasicTransformerAdapter {
    @Override
    public List transformList(List collection) {
        // set of objects already in the result
        Set<List<Object>> existingRows = new HashSet<List<Object>>();
        List result = new ArrayList();

        for (Object row : collection) {
            // array must be converted to list as array has equals() implemented using ==
            List<Object> rowAsList = Arrays.asList((Object[]) row);

            if (!existingRows.contains(rowAsList)) {
                existingRows.add(rowAsList);
                result.add(row);
            }
        }

        return result;
    }
}

然后使用注册它

Query query = session.getNamedQuery("readSymbolsFtPackages");
query.setResultTransformer(new DistinctResultTransformer());
query.list();

而且效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-22
    • 2012-02-04
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多