【问题标题】:Select object from joined table with JPA Criteria-API使用 JPA Criteria-API 从连接表中选择对象
【发布时间】:2012-03-08 21:31:58
【问题描述】:

我正在与以下问题作斗争大约两天,希望您能推动我朝着正确的方向前进。我在研究过程中发现的教程和示例始终只展示了如何在标准 api 中轻松加入。首先我有两个类:

@Entity
public class Offer {

  private String name;
  @ManyToOne private Location location;
  private String tags;
}

@Entity
public class Location {
  private String name;
  private string tags;
}

因为我需要避免循环引用,所以这些类之间的连接只是单向的。这些类中有很多附加属性,我想根据我的搜索过滤器构建动态查询。下面的 SQL 语句将解释我喜欢做什么:

SELECT l 
FROM Offer o 
JOIN o.location l
WHERE o.tags LIKE :sometag AND l.tags LIKE :someothertag

在使用标准 api 实现这个之后,我得到了这段代码:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Location> criteriaQuery = criteriaBuilder.createQuery(Location.class);
criteriaQuery = criteriaQuery.distinct(true);
Join location;
ArrayList<Predicate> whereList = new ArrayList<Predicate>();

// if filter by offer, use offer as main table and join location table
if (filter.getOfferTags() != null) {
  Root<Offer> offer = criteriaQuery.from(Offer.class);

  location = offer.join("location");


  // limit to offering tags
  Path<String> tagPath = offer.get("tags");

  for (String tag : filter.getOfferTags()) {
    Predicate whereTag = criteriaBuilder.like(tagPath, "%" + tag + "%");
    whereList.add(whereTag);
  }

} else {
  // else use location table as base
  location = (Join<Location, Location>) criteriaQuery.from(Location.class);
}

但如果我执行此操作,我会从我的 H2 数据库中收到以下错误消息:

Column "LOCATION.ID" not found; SQL statement: 
SELECT DISTINCT LOCATION.ID, LOCATION.NAME
FROM OFFER t0, LOCATION t1 
WHERE t0.TAGS LIKE ? AND t1.TAGS LIKE ?

数据库在 select 子句中需要 t1.IDt1.NAME,而不是 LOCATION.IDLOCATION.NAME。我如何告诉 JPA 创建“正确”请求?我的代码中是否缺少某些内容?

我正在使用带有 Eclipse Link 和 H2 数据库的 Glassfish 3.1.1。

【问题讨论】:

    标签: java jpa criteria-api


    【解决方案1】:

    我认为您不需要在查询中明确指定联接 - 毕竟所有商品都已映射到位置。

    这样就足够了:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Location> cq = criteriaBuilder.createQuery(Location.class);
    Root<Offer> offer = criteriaQuery.from(Offer.class);
    cq.select(offer.get("location"));
    cq.where(... )
    

    【讨论】:

      【解决方案2】:

      我认为您只是在查询中错过了一个选择:

      criteriaQuery.select(location);
      

      【讨论】:

        猜你喜欢
        • 2020-10-02
        • 1970-01-01
        • 2015-02-15
        • 2015-04-04
        • 2011-03-30
        • 1970-01-01
        • 2012-09-19
        • 2019-11-10
        • 2022-12-21
        相关资源
        最近更新 更多