标准 Jpa 选择外国实体

Posted

技术标签:

【中文标题】标准 Jpa 选择外国实体【英文标题】:Criteria Jpa Select foreign entity 【发布时间】:2015-11-27 06:52:07 【问题描述】:

谁能帮忙把这个hsql翻译成标准,请:

Select S From Player P Inner Join P.setting S Where P.id = :pid

我在处理这个查询时感到困惑。

【问题讨论】:

可能重复的外观跟随问题:***.com/questions/12512705/… 您显示的语句不是有效的 SQL 语句。 【参考方案1】:

即使您正在执行 JOIN,从您的变量名来看,在我看来,您在 PlayerSetting 之间建模了 @OneToOne 关系,是吗?

如果您为@OneToOne 关系建模Setting 将在Player 加载时立即加载。这意味着你可以做一个简单的em.find(Player.class, pid) 并使用player.getSetting() 来访问它。如果您仍想使用标准 API 进行此操作,请继续使用

public Player findByPlayerId(Long pid)
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Player> cq = cb.createQuery(Player.class);
    Root<Player> playerRoot = cq.from(Player.class);
    cq.select(playerRoot);
    cq.where(cb.equal(playerRoot.<Long>get("id"),cb.parameter((Long.class), "playerId")));
    TypedQuery<Player> tq = em.createQuery(cq);
    tq.setParameter("playerId", pid);
    return tq.getSingleResult();        

如果您对从 Player 指向 Setting@OneToMany 关系建模,您可以执行 JOIN,因为映射是 LAZY 加载的。在您使用标准 API 的情况下,可以这样完成:

public List<Setting> getSettingsByPlayerId(Long pid)
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Setting> cq = cb.createQuery(Setting.class);
    Root<Player> playerRoot = cq.from(Player.class);
    Join<Player, Setting> joinedSettings = playerRoot.join("setting"); //or better settings with an 's'
    cq.select(joinedSettings);
    cq.where(cb.equal(playerRoot.<Long>get("id"),cb.parameter((Long.class), "playerId")));      
    TypedQuery<Setting> tq = em.createQuery(cq);
    tq.setParameter("playerId", pid);
    return tq.getResultList();

但是,可以通过优化 CriteriaQuery 来优化翻译后的 SQL 以使用更少的 JOINS。因此,您需要选择映射的拥有方(Setting)而不是非拥有方(Player)。

public List<Setting> getSettingByPlayerId(Long pid)
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Setting> cq = cb.createQuery(Setting.class);
    Root<Setting> settingRoot = cq.from(Setting.class);
    cq.select(settingRoot);
    cq.where(cb.equal(settingRoot.<Player>get("player").<Long>get("id"),cb.parameter((Long.class), "playerId")));   
    TypedQuery<Setting> tq = em.createQuery(cq);
    tq.setParameter("playerId", pid);
    return tq.getResultList();

【讨论】:

以上是关于标准 Jpa 选择外国实体的主要内容,如果未能解决你的问题,请参考以下文章

使用 JPA 原生查询时是不是必须选择所有实体属性?

JPA双向实体:在查询父实体时仅选择子实体的子集

在所有嵌套实体中选择几个:SPRING JPA

JPA 选择查询以返回带有 @ManyToOne 映射的实体

JPA,实体管理器,选择多列并获取结果列表自定义对象

Spring Data Jpa:保存方法仅返回选择,但不执行插入