使用Hibernate Criteria过滤Map中的键和值

mic*_*car 11 java hibernate hibernate-criteria

我有以下持久化课程:

public class Code {

  @ElementCollection(targetClass = CodeValue.class)
  @MapKeyClass(CodeProperty.class)
  @JoinTable(name="code_properties")
  @CreateIfNull( value = false )
  private Map<CodeProperty,CodeValue> propertiesMap =
      new HashMap<CodeProperty, CodeValue>();

  ...
}

public class CodeProperty {
    private String name;
    ...
}

public class CodeValue {
    private String value;
    ...
}
Run Code Online (Sandbox Code Playgroud)

而我试图让一些性质我有过滤代码列表propertiesMap(例如,其中一个名为"颜色"属性的值为"绿色"的代码.

我使用以下基本标准:

Criteria criteria = currentSession()
    .createCriteria(Code.class, "code")
    .setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
Run Code Online (Sandbox Code Playgroud)

当我尝试执行收集过滤器时(如此处所示):

criteria.createAlias("code.properties", "p");
criteria.add(Restrictions.eq("p.foo", "test1"));
criteria.setFetchMode("code.properties", FetchMode.JOIN);
criteria.list();
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

org.hibernate.QueryException: could not resolve property: foo of: com.example.CodeValue
Run Code Online (Sandbox Code Playgroud)

这意味着,我真的不明白为什么,hibernate正在考虑code.propertiesCodeValue而不是地图!

我也尝试在不创建别名的情况下访问此字段,这样hibernate似乎可以访问正确的Code类.我使用了properties.indeces(这里建议):

criteria.add(Restrictions.eq("properties.indeces", "foo"));
criteria.list();
Run Code Online (Sandbox Code Playgroud)

但是有了这个,我得到以下错误:

could not resolve property: properties.indeces of: com.example.Code
Run Code Online (Sandbox Code Playgroud)

有人可以帮我理解什么是错的吗?正确的Criteria查询将找到绿色代码?

您可以签出演示此问题的Github项目.

谢谢

Nar*_*ros 0

我不相信您可以使用旧的 Hibernate Criteria API 来做到这一点,并且使用 JPA criteria API 的 Hibernate 实现有一个小限制。解决这个问题的一种方法是:

List<CodeProperty>通过直接使用您的谓词要求查询该实体来获取 a 。

List<CodeProperty> propertyKeys = entityManager
  .createQuery( "FROM CodeProperty p WHERE p.name = :name" )
  .setParameter( "name", "foo" )
  .getResultList();
Run Code Online (Sandbox Code Playgroud)

Code使用 JPA 标准查询您的实体。

// setup the query
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Code> query = cb.createQuery( Code.class );
Root<Code> root = query.from( Code.class );
MapJoin<Code, CodeProperty, CodeValue> mapRoot = root.joinMap( "propertiesMap" );
query.select( root ).where( mapRoot.key().in( propertyKeys ) );

// get results
List<Code> results = entityManager.createQuery( query ).getResultList();
Run Code Online (Sandbox Code Playgroud)

我尝试使用以下方法将它们结合起来:

query
  .select( root )
  .where ( cb.eq( mapRoot.key().get( "name" ), "foo" ) )
Run Code Online (Sandbox Code Playgroud)

问题是这会导致NotYetImplemented异常:(。