使用Hibernate Criteria过滤Map

时间:2016-08-19 16:39:43

标签: 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;
    ...
}

我试图通过 propertiesMap 中的某些属性来获取代码列表(例如,属性名为&#34;颜色&#34;具有该值的代码&#34;绿色&#34;

我使用以下基本标准:

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

当我尝试执行收集过滤器时(建议here):

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

我收到以下错误:

org.hibernate.QueryException: could not resolve property: foo of: com.example.CodeValue

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

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

criteria.add(Restrictions.eq("properties.indeces", "foo"));
criteria.list();

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

could not resolve property: properties.indeces of: com.example.Code

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

您可以结帐the Github project that demonstrates this problem

由于

4 个答案:

答案 0 :(得分:2)

请确认您是否使用过indeces或index。正确用法如下:

criteria.createAlias("code.properties", "p");
criteria.add(Restrictions.eq("p.indices", "foo"));
criteria.list();

或者,您可以使用

eq("p." + CollectionPropertyNames.COLLECTION_INDICES)  
限制中的

如果它仍然不适合你,请告诉我。

答案 1 :(得分:1)

这可能不是你所期望的,但是在更高版本的hibernate中,别名没有得到解决我在使用别名引用时在Projections中遇到了问题 https://stackoverflow.com/questions/36607042/hibernate-criteria-query-using-projections-aggregate-function-alias-throws-sette

答案 2 :(得分:1)

您的方法存在各种问题: 在项目github中观察MapTest文件夹我可以建议您始终将变量名称作为列名称,并在Criteria中使用这些相同的名称。 Criteria是maps,其第一个参数是属性名称,第二个参数是attribute的值。 对于多对多关系,您可以尝试使用:

  @JoinTable(
      name="docente_classe",
      joinColumns=
          @JoinColumn(name="id_dipendente", referencedColumnName="id_dipendente"),
      inverseJoinColumns=
          @JoinColumn(name="id_classe", referencedColumnName="id_classe")
  )

这是JPA注释,我不知道你的项目是否编译。

https://github.com/tredue1/School_Manager/blob/master/code/SM/src/main/java/agc2/it/sm/gestioneDocente/DocenteJpa.java

对于多对多关系的查询,请看这篇文章:

jpa criteria for many to many relationship

答案 3 :(得分:0)

我不相信您可以使用传统的Hibernate Criteria API执行此操作,并且使用JPA条件API的Hibernate实现存在一个小的限制。解决这个问题的一种方法是:

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

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

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

// 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();

我尝试将这些结合使用:

query
  .select( root )
  .where ( cb.eq( mapRoot.key().get( "name" ), "foo" ) )

问题是导致NotYetImplemented例外:(。