@OneToMany单向映射的替代设计方法在OpenJPA中不起作用

时间:2015-07-11 16:53:06

标签: database database-design openjpa

Hello数据库专家,

考虑以下表格:

CREATE TABLE customers (
    id INTEGER NOT NULL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    order_id INTEGER NOT NULL,
    CONSTRAINT customers_ibfk_1 FOREIGN KEY (order_id) REFERENCES   orders (id) ON DELETE CASCADE,
);

CREATE TABLE orders (
    id INTEGER NOT NULL PRIMARY KEY,
    date VARCHAR(100) NOT NULL,
    ...
);

由于我在应用程序中的大多数查询和需求只需要访问与客户关联的订单,因此我决定从客户到订单进行单向一对多映射,因为多个订单可以与客户关联。我按如下方式安排了实体类:

public class Customer implements Serializable {
...
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "id", referencedColumnName = "order_id")
    private Set<Order>   orders;
....
}

使用JPA 2.0和OpenJPA 2.4.0进行编译。但是,在运行时抛出以下异常:

 ...
 nested exception is <openjpa-2.4.0-r422266:1674604 fatal general error> org.apache.openjpa.persistence.PersistenceException: The transaction has been rolled back.  See the nested exceptions for details on the errors that occurred.] with root cause
 org.apache.openjpa.persistence.ArgumentException: You cannot join on column "customers.order_id".  It is not managed by a mapping that supports joins.

当我环顾四周时,看起来已知错误:https://issues.apache.org/jira/browse/OPENJPA-1607

我在这里错过了什么或这个映射看起来没问题吗?为了解决这个问题,据我所知,我有两种方法:

  1. 使映射成双向。但是,正如我所读到的,在OneToMany双向映射中,ManyToOne是所有者。因此,在这种情况下,订单表将是所有者,从设计的角度来看,情况并非如此。没有客户就没有订单。
  2. 从订单到客户表添加ManyToOne单向映射,对于特定客户的所有订单的任何查询,只需使用客户ID查询订单表。当然,这将意味着应该对单个查询进行多次查询。
  3. 所以关于设计的问题是:您认为哪种方法更清洁,更有效?是否有更好的不同方法?使用单向映射而不是双向映射是否有任何性能或任何其他好处?我环顾四周,但找不到很多文章。不确定我是否错过了它。如果没有多少好处,那么我可能会采用方法1做得更好。

    如果我错过了什么,我道歉。任何指针都非常感谢。感谢您提前的时间。

    感谢,

    爱丽丝

1 个答案:

答案 0 :(得分:0)

得到了这个工作,发布答案,因为它可能有助于其他人。

只要指定了Join表,就可以在OpenJPA中使用一对多单向映射。我也看到了错误中指定的问题:https://issues.apache.org/jira/browse/OPENJPA-1607。但是,一旦我添加了一个Join表,它就像一个魅力。当然,它确实意味着我将不得不添加一个额外的表,但它大大减少了更新和删除的代码量和错误。一旦我们达到性能,我将看到它的表现。但就目前而言,这对我而言。以下是摘录:

public class Customer implements Serializable {
    ...
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(name = "customers_orders", 
        joinColumns = { @JoinColumn(name = "customer_id", referencedColumnName = "id") }, 
        inverseJoinColumns = { @JoinColumn(name = "order_id", referencedColumnName = "id") })
    private Set<Order>   orders;
    ....
}