Home > Enterprise >  JPA Criteria Builder - getting an attribute that is a list
JPA Criteria Builder - getting an attribute that is a list

Time:07-05

I'm trying to access an attribute in one of my entity classes: "products" that is a list:

@Entity
@Table(name = "TRANSACTION")
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Transaction extends BaseTransaction {
    ...
    @OneToMany(mappedBy="transaction)
    private List<Product> products;
...
}

@Entity
@Table(name = "PRODUCT")
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Product {
    ....
    @ManyToOne
    @PrimaryKeyJoinColumn
    @Getter 
    @NonNull
    private Transaction transaction;
    ....
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "name", column = @Column(name = "seller_name")),
        @AttributeOverride(name = "country", column = @Column(name = "seller_country")) })
    private NameAndCountry seller;
    ...
}

@Embeddable
@AllArgsConstructor
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NameAndCountry {

    private String name;
    
    private String country;
}

Given a string: "myName", and by using JPA criteria builder, I'm trying to retrieve the name of the seller of the transaction, and this is what have when I'm trying to build the predicate:

Join<Object, Object> transactionProductJoin = root.join("products");
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("products").get("seller").get("name"), "myName");

However I'm facing an error which says:

Unable to locate Attribute with the the given name [products] on this ManagedType [work.my.domain.models.BaseTransaction]

Why is JPA criteria builder trying to retrieve the "products" attribute from the parent class of Transaction? What should be the correct way to construct the predicate?

CodePudding user response:

Following is the example where we map Parent and Child entity classes using JPA Annotations.

 @Entity
 @Table(name = "Parent")
 @Inheritance(strategy = InheritanceType.JOINED)
 public class Parent {

  // Getter and Setter methods 
 }

@Inheritance – Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy.

@InheritanceType – Defines inheritance strategy options.

  • Single table per class hierarchy strategy: a single table hosts all the instances of a class hierarchy

  • Joined subclass strategy: one table per class and subclass is present and each table persist the properties specific to a given subclass. The state of the entity is then stored in its corresponding class table and all its superclasses

  • Table per class strategy: one table per concrete class and subclass is present and each table persist the properties of the class and its superclasses. The state of the entity is then stored entirely in the dedicated table for its class.

     @Entity
     @Table(name="Child")
     public class Child extends Parent {
    
       //Getter and Setter methods, 
      }
    

@Inheritance(strategy = InheritanceType.JOINED) Should be added to the parent entity. (Depending on the InheritanceType required for your scenario.)

Check these links for reference:

Chapter 10. Inheritance mapping

5.1.6. Inheritance strategy

CodePudding user response:

The issue is solved, the problem was in the construction of the predicate: Wrong:

Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("products").get("seller").get("name"), "myName");

Correct:

Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("seller").get("name"), "myName");
  • Related