@OneToMany 单向映射的替代设计方法在 OpenJPA 中不起作用
Alternate design approach to @OneToMany unidirectional mapping not working in OpenJPA
您好数据库专家,
考虑以下 tables:
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。
我是不是漏掉了什么或者这个映射看起来没问题?为了解决这个问题,据我所知,我有两种方法:
- 使映射成为双向的。但是,正如我所读,在 OneToMany 双向映射中,ManyToOne 是所有者。所以在这种情况下,订单 table 将是所有者,从设计的角度来看实际上并非如此。没有客户就没有订单。
- 添加从订单到客户的 ManyToOne 单向映射 table,对于特定客户的所有订单的任何查询,只需使用客户 ID 查询订单 table。当然,这将意味着对本应是单个查询的内容进行多次查询。
所以我的设计问题是:您认为哪种方法更清洁、更高效?是否有更好的不同方法?使用单向映射而不是双向映射是否有任何性能或任何其他好处?我环顾四周,但找不到很多关于它的文章。不确定我是否错过了它。如果没有太多好处,那么我可能会用方法 1 更好。
如果我遗漏了什么,我深表歉意。非常感谢任何指针。感谢您提前抽出时间。
谢谢,
爱丽丝
解决了这个问题,发布答案可能会对其他人有所帮助。
事实证明,只要您指定连接 table,一对多单向映射就可以在 OpenJPA 中工作。我也看到了错误中指定的问题: https://issues.apache.org/jira/browse/OPENJPA-1607 。然而,一旦我添加了一个 Join table,它就像一个魅力。当然,这确实意味着我将不得不添加一个额外的 table,但它大大减少了更新和删除的代码量和错误。一旦我们开始表演,我将看看它的表现如何。但就目前而言,这就是我的。以下是片段:
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;
....
}
您好数据库专家,
考虑以下 tables:
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。
我是不是漏掉了什么或者这个映射看起来没问题?为了解决这个问题,据我所知,我有两种方法:
- 使映射成为双向的。但是,正如我所读,在 OneToMany 双向映射中,ManyToOne 是所有者。所以在这种情况下,订单 table 将是所有者,从设计的角度来看实际上并非如此。没有客户就没有订单。
- 添加从订单到客户的 ManyToOne 单向映射 table,对于特定客户的所有订单的任何查询,只需使用客户 ID 查询订单 table。当然,这将意味着对本应是单个查询的内容进行多次查询。
所以我的设计问题是:您认为哪种方法更清洁、更高效?是否有更好的不同方法?使用单向映射而不是双向映射是否有任何性能或任何其他好处?我环顾四周,但找不到很多关于它的文章。不确定我是否错过了它。如果没有太多好处,那么我可能会用方法 1 更好。
如果我遗漏了什么,我深表歉意。非常感谢任何指针。感谢您提前抽出时间。
谢谢,
爱丽丝
解决了这个问题,发布答案可能会对其他人有所帮助。
事实证明,只要您指定连接 table,一对多单向映射就可以在 OpenJPA 中工作。我也看到了错误中指定的问题: https://issues.apache.org/jira/browse/OPENJPA-1607 。然而,一旦我添加了一个 Join table,它就像一个魅力。当然,这确实意味着我将不得不添加一个额外的 table,但它大大减少了更新和删除的代码量和错误。一旦我们开始表演,我将看看它的表现如何。但就目前而言,这就是我的。以下是片段:
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;
....
}