11

I have the following persisted class:

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;
    ...
}

And I'm trying to get a list of Code filtered by some properties I have in propertiesMap (e.g. the codes where the property named "color" has the value "green".

I'm using the following base criteria:

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

When I try to perform a collection filter (as suggested here):

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

I get the following error:

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

Which means that, I don't really understand why, hibernate is considering that code.properties is a CodeValue instead of a map!!!

I also tried to access this field without creating the alias, and this way hibernate seems to access the correct Code class. I used properties.indeces (as suggested here):

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

But with this I get the following error:

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

Can someone help me out understanding whats wrong? What would the correct Criteria query be to find the Codes with color green?

You can checkout the Github project that demonstrates this problem.

Thanks

Community
  • 1
  • 1
micdcar
  • 181
  • 1
  • 11
  • I notice you're using JPA 2.1 features with @MapKeyClass. Are you bound to using the deprecated Hibernate Criteria API rather than the JPA Criteria API? – Naros Aug 19 '16 at 19:06
  • @Naros answering on behalf of micdcar - yes, unfortunately that would mean switching the entire sessionfactory configuration to entitymanager, which can be explored but not on such short notice.so we're bound to createCriteria, which returns an hibernate criteria. – mmalmeida Aug 20 '16 at 13:59

4 Answers4

2

Please confirm if you've used indeces or indices. The correct usage is as follows:

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

Alternatively, you can use

eq("p." + CollectionPropertyNames.COLLECTION_INDICES)  

in the Restriction.

Please let me know if it still doesn't work for you.

Akash Mishra
  • 682
  • 1
  • 5
  • 13
1

This may not be what you are expecting, but in higher version of hibernate the alias is not being resolved i had an issue in Projections when using the alias refer https://stackoverflow.com/questions/36607042/hibernate-criteria-query-using-projections-aggregate-function-alias-throws-sette

Community
  • 1
  • 1
Tim
  • 1,321
  • 1
  • 22
  • 47
1

There are various problems with your approach: Watching MapTest folder in your project github I can advise you to always call the variable names as column names, and to use those same names in the Criteria. The Criteria are maps, whose first argument is the attribute name and the second argument is the value of attribute. For many to many relationship you can try to use :

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

This is JPA annotation , I don't know if this compile on your project.

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

For query on many to many relationship watch this post :

jpa criteria for many to many relationship .

Community
  • 1
  • 1
pioardi
  • 181
  • 2
  • 7
  • I'm sorry, I am not following. Your examples don't have any Map. Querying a many-to-many implemented via Sets is different thing. Could you clarify your answer using the GitHub example (or a project fork)? – mmalmeida Sep 01 '16 at 15:37
  • Have you try to check link : http://stackoverflow.com/questions/8135612/jpa-criteria-for-many-to-many-relationship ???? This is a good example. – pioardi Sep 01 '16 at 15:59
0

I don't believe you can do this with the legacy Hibernate Criteria API and there is a small limitation with Hibernate's implementation using the JPA criteria API. One way to solve this would be:

Get a List<CodeProperty> by querying that entity directly with your predicate requirements.

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

Query your Code entity using JPA criteria.

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

I tried to combine these using:

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

The problem is this results in a NotYetImplemented exception :(.

Naros
  • 19,928
  • 3
  • 41
  • 71
  • Thing is, OP's question was about a non-entity query. Also, replacing Hibernate Classic Criteria queries with JPA queries tends to force a change in the entire persistence implementation (SessionFactory to EntityManager), and that's way more trouble than it's worth. – Gwaptiva Aug 27 '18 at 13:12
  • 1
    @Gwaptiva Understand but I believe that is an inevitable change that users will need to consider particularly when upgrading from Hibernate 5 to 6. – Naros Sep 10 '18 at 16:36
  • Fair point. I guess I may have been projecting my own fears related to this change in my application :( – Gwaptiva Sep 11 '18 at 08:05