简体   繁体   English

使用JPA和Criteria API将通用类型联接

[英]Join generic type with JPA and Criteria API

i'm trying to map the following entity: 我正在尝试映射以下实体:

I have an Order entity that contains different types of OrderData(can also be shared between multiple Order entities), depending on the actual order(different produckts, product variants etc): 我有一个Order实体,其中包含不同类型的OrderData(也可以在多个Order实体之间共享),具体取决于实际的订单(不同的产品,产品变体等):

//Simplified example
@Entity
@IdClass(OrderPK.class)
@Table(name = "tablename"
public class Order<T extends OrderData> {
    @Id
    @ManyToOne
    @JoinColumn(name = "whatever")
    private T orderData;

    // Might be complicating stuff
    @Id
    @ManyToOne 
    @JoinColumn(name = "somecolumn")
    private Account buyerAccount;
    // ...
}

// OrderData base class
@Entity
@Table(name = "thatothertable"
@Inheritance(strategy=InheritanceType.JOINED)
public class OrderData {
    @Id
    @Column(name = "id")
    private Long id;

    // extra stuff
}

Now the problem is: how can i get this to join the right subclass of OrderData? 现在的问题是:我如何才能将其加入OrderData的正确子类? I want to be able to write something like this: List<Order<CustomOrderData>> ordersWithCustomOrderData = this.orderDAO.findAllOrders(); 我希望能够这样写: List<Order<CustomOrderData>> ordersWithCustomOrderData = this.orderDAO.findAllOrders(); and get all Order entities with CustomOrderDatas. 并使用CustomOrderDatas获取所有Order实体。 Is there a way to achieve this? 有没有办法做到这一点?

So far my DAO codes looks like this: 到目前为止,我的DAO代码如下所示:

public List<Order> findAllOrders() {
    CriteriaBuilder cb = this.em.getCriteriaBuilder();
    CriteriaQuery<Order> cq = cb.createQuery(Order.class);
    Root<Order> root = cq.from(Order.class):
    cq.select(root):
    return this.em.createQuery(cq).getResultList();
}

How would i have to change the DAO code to support the generic type? 我将如何更改DAO代码以支持通用类型? Is it actually possible? 真的有可能吗? If not, is there any alternative design to achieve a comparable structure and functionability (Orders with different OrderDatas, ability to search for Orders with specific subclass of OrderData)? 如果不是,是否有任何替代设计来实现可比的结构和功能(具有不同OrderData的订单,具有OrderData特定子类的Orders的搜索能力)?

// Not working pseudo code of what i want
public <T extends OrderData> List<Order<T>> findAllOrders() {
    CriteriaBuilder cb = this.em.getCriteriaBuilder();
    // With createQuery(Order.class) i will get CrtieriaQuery<Order>
    CriteriaQuery<Order<T>> cq = cb.createQuery(Order.class);
    // as above
    Root<Order<T>> root = cq.from(Order.class):
    cq.select(root):
    return this.em.createQuery(cq).getResultList();
}

1. Idea 1.想法

Why do you need a generic Attribute? 为什么需要通用属性? Generic entities are not possible in JPA but you could just put the reference to a Orderdata as: 通用实体在JPA中是不可能的,但是您可以将对Orderdata的引用放置为:

private OrderData orderData;

2. Idea 2.想法

You can save this enum in your entity and then compare OrderDataType.getClazz() to your OrderData1.getClass() and you can query for this types. 您可以将该枚举保存在您的实体中,然后将OrderDataType.getClazz()OrderData1.getClass()比较,然后可以查询此类型。 If you are using JPA 2.1 you can save the full classname in the database column with a custom Fieldconverter and then query for the class. 如果使用的是JPA 2.1,则可以使用自定义Fieldconverter将完整的类名保存在数据库列中,然后查询该类。

public enum OrderDataType {
    Order1(Order1.class);

    private Class<? extends OrderData> clazz;

    private OrderDataType(Clazz<? extends OrderData> clazz) {
        this.clazz = clazz;
    }

    public Class<? extends OrderData> getClazz() {
        return clazz;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM