如何使用 Hibernate 和 JPA 定义外键映射的字段顺序?
How to define the order of fields on foreign key mapping using Hibernate and JPA?
我在 hibernate 部署我的应用程序时遇到了一些问题。
我在日志中看到一些错误,说 hibernate 无法更新 tables 因为发现外键违规,如下所示:
Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "order" violates foreign key constraint "fk1w50d63tw42cwgrb7pjn11crs"
Detail: Key (id_office_o, id_period)=(2, 1) is not present in table "office".
但在我的 table 定义中,我将 FK fk_order_office_o
作为 (id_period, id_office_o)
关系。
这是我的 table 定义。
CREATE TABLE period (
id_period INTEGER PRIMARY KEY NOT NULL,
initial_date TIMESTAMP,
final_date TIMESTAMP
);
CREATE TABLE office (
id_period INTEGER NOT NULL,
id_office INTEGER NOT NULL,
large_name VARCHAR(50) NOT NULL,
code_name VARCHAR(2) NOT NULL,
CONSTRAINT pk_office PRIMARY KEY (id_periodo, id_office),
CONSTRAINT fk_office_period FOREIGN KEY (id_period) REFERENCES period (id_period)
);
CREATE UNIQUE INDEX uk_office_id_office ON office (id_office);
CREATE TABLE order (
id_order INTEGER PRIMARY KEY NOT NULL,
id_period INTEGER,
id_office_o INTEGER,
id_office_d INTEGER,
status INTEGER,
CONSTRAINT fk_order_office_o
FOREIGN KEY (id_period, id_office_o)
REFERENCES office (id_period, id_office)
MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_order_office_d
FOREIGN KEY (id_period, id_office_d)
REFERENCES office (id_period, id_office),
MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_order_period
FOREIGN KEY (id_period)
REFERENCES period (id_period)
MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT
);
这些是我 table 上的数据。
Period.
+------------+--------------+------------+
| id_period | initial_date | final_date |
|------------|--------------|------------+
| 1 | 2016-01-01 | 2017-12-31 |
+------------+--------------+------------+
Office.
+------------+-----------+------------+-----------+
| id_period | id_office | large_name | code_name |
|------------|-----------|------------|-----------|
| 1 | 1 | Sales | SL |
| 1 | 2 | Billing | BL |
| 1 | 3 | Shipments | SH |
| 1 | 4 | Returns | RT |
+------------+-----------+------------+-----------+
Order.
+------------+-----------+--------------+--------------+-----------+
| id_order | id_period | id_office_o | id_office_d | status |
+------------+-----------+--------------+--------------+-----------+
| 1 | 1 | 2 | 3 | 1 |
| 2 | 1 | 2 | 3 | 1 |
| 1 | 1 | 3 | 4 | 1 |
| 1 | 1 | 1 | 2 | 1 |
+------------+-----------+--------------+--------------+-----------+
如您所见,与订单 table 相关的 office
table 的 FK 有一个名为 fk_order_office_o
的约束,使用 id_period
和 id_office
,就是这样。
实体映射在这里:
@Embeddable
public class OfficePK implements Serializable {
@Column(name = "id_period")
private Integer idPeriod;
@Column(name="id_office")
private Integer idOffice;
public OfficePK() {
}
public OfficePK(Integer idPeriod, Integer idOffice) {
this.idPeriod = idPeriod;
this.idOffice = idOffice;
}
...
}
@Entity
@Table(schema="enterprise", name="office")
public class Office {
@EmbeddedId
private OfficePK idOffice;
private String largeName;
private String codeName;
public Office() {
}
public OfficePK getIdOffice() {
return this.idOffice;
}
public void setIdOffice(OfficePK idOffice) {
this.idOffice = idOffice;
}
...
}
@Entity
@Table(schema="operation", name = "order")
public class Order {
@Column(name="id_order")
private Integer idOrder;
@ManyToOne
@JoinColumns(
value = {
@JoinColumn(name="id_period",
referencedColumnName = "id_period",
nullable = false, insertable = false,
updatable = false),
@JoinColumn(name="id_office_o",
referencedColumnName = "id_office",
nullable = false, insertable = false,
updatable = false)
},
foreignKey = @ForeignKey(name = "fk_order_office_o")
)
private Office officeO;
@ManyToOne
@JoinColumns(
value = {
@JoinColumn(name="id_period",
referencedColumnName = "id_period",
nullable = false, insertable = false,
updatable = false),
@JoinColumn(name="id_office_d",
referencedColumnName = "id_office",
nullable = false, insertable = false,
updatable = false)
},
foreignKey = @ForeignKey(name = "fk_order_office_d")
)
private Office officeD;
public Order() {
}
...
}
部署应用程序时,我看到了一些引起我注意的错误:
- 我没有按照日志文件中显示的顺序定义外键,日志文件正在查找
(id_office_o, id_period)
对,但外键在table 并在映射中。
- 我正在设置外键的名称,但是 hibernate 正在设置一个随机名称,例如
fk1w50d63tw42cwgrb7pjn11crs
如何定义实体外键映射字段的顺序?可能吗?..或者应该如何定义或映射外键字段?
我正在使用
- 休眠 5.2.6.Final
- Spring-JPA 1.10.6.RELEASE
谢谢大家
与 @ForeignKey
名称相关的部分可能与 HHH-11180 相关。
关于外键顺序的部分,你可以通过提供一个自定义的org.hibernate.boot.model.naming.ImplicitNamingStrategy
实现来解决它,它从默认的org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
扩展并覆盖determineForeignKeyName
方法,以便它按照您需要的顺序生成包含列的外键。
现在,您正在经历的所有这些努力都让人觉得您没有正确管理架构。你不应该在生产中使用自动 HBM2DDL 模式生成。 You should use Flyway instead。这是您环境中的根本问题。
我在 hibernate 部署我的应用程序时遇到了一些问题。
我在日志中看到一些错误,说 hibernate 无法更新 tables 因为发现外键违规,如下所示:
Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "order" violates foreign key constraint "fk1w50d63tw42cwgrb7pjn11crs"
Detail: Key (id_office_o, id_period)=(2, 1) is not present in table "office".
但在我的 table 定义中,我将 FK fk_order_office_o
作为 (id_period, id_office_o)
关系。
这是我的 table 定义。
CREATE TABLE period (
id_period INTEGER PRIMARY KEY NOT NULL,
initial_date TIMESTAMP,
final_date TIMESTAMP
);
CREATE TABLE office (
id_period INTEGER NOT NULL,
id_office INTEGER NOT NULL,
large_name VARCHAR(50) NOT NULL,
code_name VARCHAR(2) NOT NULL,
CONSTRAINT pk_office PRIMARY KEY (id_periodo, id_office),
CONSTRAINT fk_office_period FOREIGN KEY (id_period) REFERENCES period (id_period)
);
CREATE UNIQUE INDEX uk_office_id_office ON office (id_office);
CREATE TABLE order (
id_order INTEGER PRIMARY KEY NOT NULL,
id_period INTEGER,
id_office_o INTEGER,
id_office_d INTEGER,
status INTEGER,
CONSTRAINT fk_order_office_o
FOREIGN KEY (id_period, id_office_o)
REFERENCES office (id_period, id_office)
MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_order_office_d
FOREIGN KEY (id_period, id_office_d)
REFERENCES office (id_period, id_office),
MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_order_period
FOREIGN KEY (id_period)
REFERENCES period (id_period)
MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT
);
这些是我 table 上的数据。
Period.
+------------+--------------+------------+
| id_period | initial_date | final_date |
|------------|--------------|------------+
| 1 | 2016-01-01 | 2017-12-31 |
+------------+--------------+------------+
Office.
+------------+-----------+------------+-----------+
| id_period | id_office | large_name | code_name |
|------------|-----------|------------|-----------|
| 1 | 1 | Sales | SL |
| 1 | 2 | Billing | BL |
| 1 | 3 | Shipments | SH |
| 1 | 4 | Returns | RT |
+------------+-----------+------------+-----------+
Order.
+------------+-----------+--------------+--------------+-----------+
| id_order | id_period | id_office_o | id_office_d | status |
+------------+-----------+--------------+--------------+-----------+
| 1 | 1 | 2 | 3 | 1 |
| 2 | 1 | 2 | 3 | 1 |
| 1 | 1 | 3 | 4 | 1 |
| 1 | 1 | 1 | 2 | 1 |
+------------+-----------+--------------+--------------+-----------+
如您所见,与订单 table 相关的 office
table 的 FK 有一个名为 fk_order_office_o
的约束,使用 id_period
和 id_office
,就是这样。
实体映射在这里:
@Embeddable
public class OfficePK implements Serializable {
@Column(name = "id_period")
private Integer idPeriod;
@Column(name="id_office")
private Integer idOffice;
public OfficePK() {
}
public OfficePK(Integer idPeriod, Integer idOffice) {
this.idPeriod = idPeriod;
this.idOffice = idOffice;
}
...
}
@Entity
@Table(schema="enterprise", name="office")
public class Office {
@EmbeddedId
private OfficePK idOffice;
private String largeName;
private String codeName;
public Office() {
}
public OfficePK getIdOffice() {
return this.idOffice;
}
public void setIdOffice(OfficePK idOffice) {
this.idOffice = idOffice;
}
...
}
@Entity
@Table(schema="operation", name = "order")
public class Order {
@Column(name="id_order")
private Integer idOrder;
@ManyToOne
@JoinColumns(
value = {
@JoinColumn(name="id_period",
referencedColumnName = "id_period",
nullable = false, insertable = false,
updatable = false),
@JoinColumn(name="id_office_o",
referencedColumnName = "id_office",
nullable = false, insertable = false,
updatable = false)
},
foreignKey = @ForeignKey(name = "fk_order_office_o")
)
private Office officeO;
@ManyToOne
@JoinColumns(
value = {
@JoinColumn(name="id_period",
referencedColumnName = "id_period",
nullable = false, insertable = false,
updatable = false),
@JoinColumn(name="id_office_d",
referencedColumnName = "id_office",
nullable = false, insertable = false,
updatable = false)
},
foreignKey = @ForeignKey(name = "fk_order_office_d")
)
private Office officeD;
public Order() {
}
...
}
部署应用程序时,我看到了一些引起我注意的错误:
- 我没有按照日志文件中显示的顺序定义外键,日志文件正在查找
(id_office_o, id_period)
对,但外键在table 并在映射中。 - 我正在设置外键的名称,但是 hibernate 正在设置一个随机名称,例如
fk1w50d63tw42cwgrb7pjn11crs
如何定义实体外键映射字段的顺序?可能吗?..或者应该如何定义或映射外键字段?
我正在使用
- 休眠 5.2.6.Final
- Spring-JPA 1.10.6.RELEASE
谢谢大家
与 @ForeignKey
名称相关的部分可能与 HHH-11180 相关。
关于外键顺序的部分,你可以通过提供一个自定义的org.hibernate.boot.model.naming.ImplicitNamingStrategy
实现来解决它,它从默认的org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
扩展并覆盖determineForeignKeyName
方法,以便它按照您需要的顺序生成包含列的外键。
现在,您正在经历的所有这些努力都让人觉得您没有正确管理架构。你不应该在生产中使用自动 HBM2DDL 模式生成。 You should use Flyway instead。这是您环境中的根本问题。