使用JPA和Criteria API加入泛型类型

时间:2013-11-08 07:51:13

标签: java java-ee generics jpa join

我正在尝试映射以下实体:

我有一个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
}

现在的问题是:我怎样才能加入OrderData的正确子类? 我希望能够写出这样的东西:     List<Order<CustomOrderData>> ordersWithCustomOrderData = this.orderDAO.findAllOrders(); 并使用CustomOrderDatas获取所有Order实体。 有没有办法实现这个目标?

到目前为止,我的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();
}

我如何更改DAO代码以支持泛型类型? 它真的可能吗?如果没有,是否有任何替代设计来实现可比较的结构和功能(具有不同OrderDatas的订单,能够搜索具有OrderData特定子类的订单)?

// 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 个答案:

答案 0 :(得分:0)

<强> 1。想法

为什么需要通用属性? JPA中不可能使用通用实体,但您可以将对Orderdata的引用放在:

private OrderData orderData;

<强> 2。想法

您可以在实体中保存此枚举,然后将OrderDataType.getClazz()OrderData1.getClass()进行比较,您可以查询此类型。如果您使用的是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;
    }
}