【问题标题】:Criteria API and Entity Graph标准 API 和实体图
【发布时间】:2015-05-26 13:25:00
【问题描述】:

我有两个具有单向惰性关系的实体。其中一个有一个命名实体图。以下是实体(由于可读性,getter 和 setter 未列出):

    @Entity
    @NamedEntityGraph (
            name = "Sms.fetchSims",
            attributeNodes = {
                    @NamedAttributeNode("sim")
            }
    )
    public class Sms {
        @Id
        @GeneratedValue (strategy = GenerationType.AUTO)
        private Long id;
        @NotNull
        private Timestamp date;
        @NotNull
        private String sender;
        @NotNull
        private String content;

        @NotNull
        private Direction direction;

        @NotNull
        @ManyToOne (fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
        private Sim sim;
    }

    @Entity
    public class Sim {
        @Id
        @GeneratedValue (strategy = GenerationType.AUTO)
        private long id;

        @NotNull
        private long IMSI;

        private String MSISDN;
        private String provider;
        private Timestamp lockedDate;
    }

当我使用实体管理器 find() 方法和这个实体图获取任何短信时,我会收到一个带有 sim 卡的短信。 但我希望能够通过 sim id 找到短信。这就是为什么我为此目的创建了一个标准 api 查询。

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();

    EntityGraph eg = entityManager.getEntityGraph("Sms.fetchSims");

    CriteriaQuery<Sms> cq = cb.createQuery(Sms.class);
    Root<Sms> smses = cq.from(Sms.class);
    Join<Sms, Sim> sims = smses.join(Sms_.sim);
    cq.where(cb.equal(sims.get(Sim_.id), simId));
    cq.orderBy(cb.desc(smses.get(Sms_.date)));

    return entityManager
        .createQuery(cq)
        .setHint("javax.persistence.fetchgraph", eg)
        .setMaxResults(1000)
        .getResultList();

如您所见,我在此处使用类型化查询的 setHint 方法设置实体图,但从不获取 sim,它的字段甚至没有在结果 sql 中列出。我该怎么做才能使实体图与标准 api 一起使用?

我知道我可以将 smses.fetch(Sms_.sim) 类型转换为 Join,但我收到了难看的警告,而且这种方法对我来说似乎是一种肮脏的 hack。

我正在使用 hibernate 和 wildfly-8.2.0.Final 应用程序服务器。

【问题讨论】:

  • 实体图和条件查询看起来都很好。当您使用本机 SQL 查询数据时,它是否有效?类似SELECT i.* FROM sms m INNER JOIN sim i ON m.sim_id = i.id ORDER BY m.date
  • @wypieprz,当然,如果我使用 sql,它确实可以按我的意愿工作。问题是当它不符合标准 api 时 :)

标签: jakarta-ee criteria-api jpa-2.1


【解决方案1】:

是的,伙计,对不起。 hibernate 中有一个 bug 在 4.3.9.Final 之后修复。 这是 4.3.9 生成的查询:

DEBUG - org.hibernate.SQL - 
select
    sms0_.id as id1_1_0_,
    sim1_.id as id1_0_1_,
    sms0_.content as content2_1_0_,
    sms0_.date as date3_1_0_,
    sms0_.direction as directio4_1_0_,
    sms0_.sender as sender5_1_0_,
    sms0_.sim_id as sim_id6_1_0_,
    sim1_.IMSI as IMSI2_0_1_,
    sim1_.MSISDN as MSISDN3_0_1_,
    sim1_.lockedDate as lockedDa4_0_1_,
    sim1_.provider as provider5_0_1_ 
from
    Sms sms0_ 
inner join
    Sim sim1_ 
        on sms0_.sim_id=sim1_.id 
where
    sim1_.id=1 
order by
    sms0_.date desc limit ?

这里是 4.3.8 查询:

DEBUG - org.hibernate.SQL - 
select
    sms0_.id as id1_1_,
    sms0_.content as content2_1_,
    sms0_.date as date3_1_,
    sms0_.direction as directio4_1_,
    sms0_.sender as sender5_1_,
    sms0_.sim_id as sim_id6_1_ 
from
    Sms sms0_ 
inner join
    Sim sim1_ 
        on sms0_.sim_id=sim1_.id 
where
    sim1_.id=1 
order by
    sms0_.date desc limit ?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-09
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多