【问题标题】:jpa set where-clause in query for fields over 2 mapjoinsjpa 在查询中设置 where-clause 查询超过 2 个 mapjoins 的字段
【发布时间】:2012-03-05 09:34:37
【问题描述】:

我正在尝试构建一个复杂的查询。我的实体如下所示:

@Entity
public class Configuration{

   @Id
   @Column(name="CONF_ID")
   protected Long configurationId;

   @ManyToMany
   @MapKey(name="componentType")
   @JoinTable(name="CONF_COMP",
      joinColumns={@JoinColumn(name="CONF_ID", referencedColumnName="CONF_ID")},
      inverseJoinColumns={@JoinColumn(name="COMP_ID", referencedColumnName="componentId")})
   protected Map<String, Component> components;
}

还有

@Entity
public class Component {

    @Id
    protected long componentId; 
    @ElementCollection
    protected Map<String, String> properties;

    @ManyToMany(mappedBy="components")
    private List<Configuration> configurations;

    @Column(name="COMP_TYPE")
    protected String componentType;
 }

我的问题在于正确查询properties 字段。我似乎无法创建查询来获取组件 A 具有属性 Prop1 = 1 且组件 B 具有属性 Prop2 = 2 的所有配置。 我尝试了以下但没有成功。

Root<Configuration> conf = cq.from(Configuration.class);    
MapJoin<Configuration, String, Component> compJoin = conf.join(Configuration_.components, JoinType.LEFT);
MapJoin<Component, String, String> propJoin = compJoin.join(Component_.properties, JoinType.LEFT); 

    Predicate p1 = cb.and(
                cb.equal(mapJoin.key(), "A"),
                cb.equal(propJoin.key(), "Prop1"), cb.equal(propJoin.value(), "1"));
    Predicate p2 = cb.and(
                cb.equal(mapJoin.key(), "B"),
                cb.equal(propJoin.key(), "Prop2"), cb.equal(propJoin.value(), "2"));

Predicate[] pArray = new Predicate[]{p1, p2};
cq.where(pArray);
cq.select(conf).distinct(true);

编辑:记录器输出的查询如下所示:

SELECT DISTINCT  t2.CONF_ID, t2.DTYPE, t2.TOTALPRICE, t2.NAME
 FROM CONFIGURATION t2 
 LEFT OUTER JOIN (CONF_COMP t3 JOIN COMPONENT t1 ON (t1.COMPONENTID = t3.COMP_ID)) ON (t3.CONF_ID = t2.CONF_ID) LEFT OUTER JOIN Component_PROPERTIES t0 ON (t0.Component_COMPONENTID = t1.COMPONENTID) 
WHERE (((((t1.COMP_TYPE = ?) AND (t0.PROPERTIES_KEY = ?)) AND t0.PROPERTIES LIKE ?) AND (((t1.COMP_TYPE = ?) AND (t0.PROPERTIES_KEY = ?)) AND t0.PROPERTIES LIKE ?)) AND (t2.DTYPE = ?))
bind => [7 parameters bound]

我猜它正在尝试找到所有条件都适用于 SAME 组件的配置?如果我只对一个组件应用限制,它会起作用,但是当应用 2 个或更多时,我得到一个空的结果列表,尽管数据库中有满足条件的条目。

更新

在听从 Pimgd 的建议后,我得到了一个如下所示的查询:

SELECT DISTINCT t1.CONF_ID, t1.DTYPE, t1.TOTALPRICE, t1.NAME
FROM CONFIGURATION t1 LEFT OUTER JOIN (CONF_COMP t2 JOIN COMPONENT t0 ON (t0.COMPONENTID = t2.COMP_ID)) ON (t2.CONF_ID = t1.CONF_ID) 
WHERE ((( 
    t0.COMPONENTID IN (SELECT t3.COMPONENTID 
                        FROM COMPONENT t3 LEFT OUTER JOIN Component_PROPERTIES t4 ON (t4.Component_COMPONENTID = t3.COMPONENTID) 
                        WHERE ((t4.PROPERTIES_KEY = Brand) AND (t4.PROPERTIES = Intel)))) 

    AND 
    t0.COMPONENTID IN (SELECT t6.COMPONENTID 
                        FROM COMPONENT t6 LEFT OUTER JOIN Component_PROPERTIES t7 ON (t7.Component_COMPONENTID = t6.COMPONENTID) 
                        WHERE ((t7.PROPERTIES_KEY = Capacity) AND t7.PROPERTIES LIKE 4GB%))))

一个标准有效,两个没有结果。

非常感谢任何帮助!

【问题讨论】:

  • cb.equal(mapJoin.key() mapJoin?你在哪里声明了 mapJoin?你确定你不是在找 compJoin?
  • 我在 Maps as Entity 领域的经验不是很丰富,原因是我几乎找不到在实体中使用地图的正当理由。能否请您澄清这一点,或者添加对其用途的简短描述?
  • 一个配置由几个组件组成。就像现在使用主板、cpu、ram 等构建的计算机一样,每个组件都有一个属性图,比如品牌、容量等。我想获得所有具有的配置,比如以英特尔为品牌的 cpu和 4GB 容量的内存。
  • 我的猜测是您必须将查询拆分为不同的查询,每个组件一个
  • 你知道有奖励赏金的徽章吗?下一次,考虑自己发放赏金,而不是让社区来做。

标签: jpa jpa-2.0 criteria criteria-api


【解决方案1】:

我会这么说 mapJoin.key() 应该是 compJoin.key()

除此之外,我没有发现任何问题。

如果我提供的解决方案不起作用,这里有一些额外的问题供您参考:

  • 您得到了什么结果?
  • 是否可以显示生成的查询?

我发现了一个有趣的地方: WHERE (((((t1.COMP_TYPE = ?) AND (t0.PROPERTIES_KEY = ?)) AND t0.PROPERTIES LIKE ?) AND (((t1.COMP_TYPE = ?) AND (t0.PROPERTIES_KEY = ?)) AND t0.PROPERTIES LIKE ?)) AND (t2.DTYPE = ?))

如果,我把这一段删掉……只是为了澄清一下。 ((t1.COMP_TYPE = ?) AND (t0.PROPERTIES_KEY = ?))

WHERE (((SNIP AND t0.PROPERTIES LIKE ?) AND (SNIP AND t0.PROPERTIES LIKE ?)) AND (t2.DTYPE = ?))

所以是的... 现在您将如何修复您的查询? 可悲的是,我不是专家。 但我所知道的是,如果您使用 WHERE t2.CONF_ID IN (Subselect for criteria A) AND t2.CONF_ID IN (Subselect for criteria B) 进行查询。

我的建议是查找子选择并滥用它们。 JPA 2.0, Criteria API, Subqueries, In Expressions 解释它并且似乎足够相关。

【讨论】:

  • 更新了我的答案。我对条件 API 的了解不足以提供代码 - 我现在没有时间提供完整的查询,但我希望这会有所帮助。
  • 即使在使用子查询时我也有同样的问题。一个标准有效,两个或更多没有结果。我已经更新了我的问题。再次。
  • 运行子选择的输出是什么?而t5去哪儿了?
  • 没有t5。子查询本身就很好,因为如果我只使用其中一个,我会得到正确的结果。问题是查询的结构是否正确?如果条件 api 和 jpa 接受多个这样的子查询?
  • 好的,这有帮助。我想到了。正如您在查询中看到的那样,我检查的是组件 ID 而不是配置 ID。这么愚蠢的错误。也花了我一整天的时间:|感谢您的所有帮助和耐心:)
猜你喜欢
  • 2014-01-08
  • 2015-01-30
  • 2018-09-30
  • 2022-01-21
  • 2020-06-27
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 2021-04-19
相关资源
最近更新 更多