Как запросить базовый класс с помощью Criteria API? - PullRequest
0 голосов
/ 05 августа 2020

Сущности выглядят так:

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

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id", unique = true, nullable = false)
    private Long id;

    @Column(name = "username", unique = true, nullable = false)
    private String username;

    @Column(name = "password", unique = false, nullable = false)
    private String password;

    @Enumerated(EnumType.STRING)
    @Column(name = "role", nullable = false)
    private UserRole userRole;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public UserRole getUserRole() {
        return userRole;
    }

    public void setUserRole(UserRole userRole) {
        this.userRole = userRole;
    }

}
@Entity
@Table(name = "customer")
public class Customer extends User {

    @Column(name = "address", unique = false, nullable = false)
    private String address;

    @Column(name = "consent_given", unique = false, nullable = false)
    private boolean consentGiven;

    @OneToOne(mappedBy = "customer",
            cascade = CascadeType.ALL,
            fetch = FetchType.LAZY)
    private Cart cart;

    @OneToMany(mappedBy = "customer",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Order> orders = new ArrayList<>();

    @OneToOne(mappedBy = "customer", cascade = CascadeType.ALL,
            fetch = FetchType.LAZY)
    private Favorites favorites;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public boolean isConsentGiven() {
        return consentGiven;
    }

    public void setConsentGiven(boolean consentGiven) {
        this.consentGiven = consentGiven;
    }

    public void setCart(Cart cart) { this.cart = cart; }

    public Cart getCart() { return cart; }

    @Override
    public String toString() {
        return "Customer{" +
                "address='" + address + '\'' +
                ", consentGiven=" + consentGiven +
                ", cart=" + cart +
                ", orders=" + orders +
                ", favorites=" + favorites +
                '}';
    }

}
@Entity
@Table(name = "cart")
public class Cart {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cart_id", unique = true, nullable = false)
    private long id;

    @OneToMany(cascade = CascadeType.ALL,
            orphanRemoval = true,
            fetch = FetchType.LAZY)
    @JoinColumn(name = "cart_id")
    private List<CartItem> listOfCartItems = new ArrayList<>();

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id")
    private Customer customer;

    @Column(name = "cart_total_price", unique = false)
    private double price;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public List<CartItem> getListOfCartItems() {
        return listOfCartItems;
    }

    public void setListOfCartItems(List<CartItem> listOfCartItems) {
        this.listOfCartItems = listOfCartItems;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double totalPrice) {
        this.price = totalPrice;
    }

}

Мне нужно использовать Criteria API, чтобы получить корзину по идентификатору клиента. Дело в том, что, как я видел, первичный ключ от базового класса будет унаследован классом Customer в MySQL, даже если он не записан в классе Customer. У меня вопрос: как мне запросить 3 таблицы, чтобы получить корзину определенного c клиента по его идентификатору, если клиент наследует первичный ключ от базового класса? Я сделал запрос (даже если он бесполезен), если первичный ключ находится в классе Customer:

Cart resultedCart;

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Cart> query = criteriaBuilder.createQuery(Cart.class);
Root<Cart> cart = query.from(Cart.class);
Join<Cart, Customer> customer = cart.join("customer");
ParameterExpression<Long> idParameter = criteriaBuilder.parameter(Long.class);
       
query.select(cart).where(criteriaBuilder.equal(customer.get("id"), idParameter));
TypedQuery<Cart> typedQuery = entityManager.createQuery(query);

try {
     resultedCart = typedQuery.setParameter(idParameter, id).getSingleResult();
} catch (NoResultException noResultException) {
     throw new NoCartFoundException("The searched cart does not exist!", noResultException);
} finally {
     entityManager.close();
}

return resultedCart;

, и я попытался на основе этого кода сделать то, что мне нужно, но, к сожалению, безуспешно .

1 Ответ

0 голосов
/ 07 августа 2020

Попробуйте следующее:

Cart resultedCart;

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Cart> query = criteriaBuilder.createQuery(Cart.class);
Root<Cart> cart = query.from(Cart.class);

query.select(cart).where(criteriaBuilder.equal(cart.get("customer").get("id"), idParameter));

TypedQuery<Cart> typedQuery = entityManager.createQuery(query);

try {
     resultedCart = typedQuery.getSingleResult();
} catch (NoResultException noResultException) {
     throw new NoCartFoundException("The searched cart does not exist!", noResultException);
} finally {
     entityManager.close();
}

return resultedCart;
...