15

This is the further question to this:

How to use JPA Criteria API in JOIN

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery<Company> criteria = criteriaBuilder.createQuery( Company.class );
Root<Company> companyRoot = criteria.from( Company.class );
Join<Company,Product> products = companyRoot.join("dentist");
Join<Company, City> cityJoin = companyRoot.join("address.city");//Company->Address->City-city
criteria.where(criteriaBuilder.equal(products.get("category"), "dentist"),      criteriaBuilder.equal(cityJoin.get("city"),"Leeds"));

A company has an address, inside the address there is City-pojo and Country-Pojo. How can I use it in JOIN? I tried to reference it with address.city but I got the error message:

The attribute [address.city] from the managed type [EntityTypeImpl@1692700229:Company [ javaType: class com.test.domain.Company descriptor: RelationalDescriptor(com.test.domain.Company --> [DatabaseTable(COMPANY)]), mappings: 16]] is not present.

Community
  • 1
  • 1
Sami
  • 2,311
  • 13
  • 46
  • 80

2 Answers2

31

If you use canonical Metamodel, you'll avoid this kind of errors. In your code you have misused the "dentist" keyword, that's probably the cause of your error, because "dentist" is not a field in Company entity.

However, looking at how you defined your class in the other question, the way to define that join using Metamodel is this:

SetJoin<Company,Product> products = companyRoot.join(Company_.products); 

As you can see, Metamodel avoids the use of strings, and so avoids a lot of runtime errors. If anyway you don't use Metamodel, try this:

SetJoin<Company,Product> products = companyRoot.join("products"); 

If you now want to add a predicate, i.e. something after the where, you'll write something like:

Predicate predicate = criteriaBuilder.equal(products.get(Product_.category), "dentist");
criteria.where(predicate);

If you want to add a join for the City entity:

Join<Company, City> city = companyRoot.join(Company_.city);
predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(city.get(City_.cityName), "Leeds");
criteria.where(predicate);

(supposing that the field cityName is the correct field name for your city).

perissf
  • 15,979
  • 14
  • 80
  • 117
  • 8
    Where is the symbol "Company_" with the trailing underscore come from? When I try these I get "Cannot resolve symbol 'Company_' – slashdottir Apr 12 '19 at 20:57
  • 1
    I don't feel comfortable editing because I don't know enough about the subject but In the second code line, you meant to use joinSet() correct? SetJoin products = companyRoot.joinSet("products"); – White_King Feb 15 '21 at 10:40
  • @White_King I think both versions should work, don't they? – perissf Feb 15 '21 at 18:13
0

Agree with @perissf.

I can't comment but the symbol "Company_" is the metadata class file which contains all the attribute name of the model class.

I strongly suggest to use metadata classes, you can autogenerate metadata classes using the maven processor plugin using org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor as processor in your configuration.

This example pom plugin xml should work it out :

  <plugin>
                <groupId>org.bsc.maven</groupId>
                <artifactId>maven-processor-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <phase>generate-sources</phase>
                        <configuration>
                            <processors>
                                <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
                            </processors>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.hibernate.orm</groupId>
                        <artifactId>hibernate-jpamodelgen</artifactId>
                        <version>${version.hibernate-jpamodelgen}</version>
                    </dependency>
                </dependencies>
            </plugin>
aldroid
  • 25
  • 1
  • 8