虽然有 Composite Primary Key,但 Hibernate 在只有一个键唯一时报错
Although there is a Composite Primary Key, Hibernate gives an error when only one key is unique
我遇到了一个 Hibernate 错误,它说 找到了超过一行具有给定标识符的行,我一直坚持下去。
如果能提供任何帮助,我将不胜感激。
- 我想创建一个 table 作为 orderLine,其中包含特定销售订单的产品代码、数量等。
一个SalesOrder可以包含很多orderLines。
orderLine table 的复合键是 productCode + OrderNumber。 ProductCode 是 Product table 的主键,OrderNumber 是 SalesOrder table 的主键。
- 在一个 SalesOrder 中,特定产品应该只有一个订单行。
复合键正确生成,我得到休眠记录的以下 sql 语句。
Hibernate:创建table orderLine(orderNumber varchar(255) 不为空,productCode varchar(255) 不为空,status varchar(255) 不为空,数量整数不为空,totalPrice 双精度不为空, unitPrice double precision not null, primary key (orderNumber, productCode))
当 OrderLine table 包含如下数据时,我成功地向 OrderLine table 插入了一条新记录 OrderNumber ORD001 & 产品代码 BIS1003
当我尝试从 OrderLine 获取记录后,立即出现以下错误。
原因:org.hibernate.HibernateException:找到具有给定标识符的多行:BIS1003,对于 class:com.salesOrder_ws.entity.OrderLine
既然有组合键为主,为什么组合键只有一个键不唯一时hibernate抛出异常?
代码如下。
订单行实体:
@Entity
@Table(name = "orderLine")
public class OrderLine implements Serializable{
private static final long serialVersionUID = -851110991599534263L;
@AttributeOverrides(value =
{@AttributeOverride(column = @Column(name="productCode"), name = "productCode"),
@AttributeOverride(column = @Column(name="orderNumber"), name = "orderNumber")})
@EmbeddedId
private LineID pk;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "productCode", insertable = false, updatable = false)
private Product product;
private int quantity;
private double unitPrice;
private double totalPrice;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "orderNumber", nullable=false, insertable=false, updatable=false)
private SalesOrder salesOrder;
@Override
public boolean equals(Object obj) {
try {
LineID line = (LineID) obj;
return (this.getSalesOrder().getOrderNumber()
.equals(line.getOrderNumber()) && this.getProduct()
.getCode().equals(line.getProductCode()));
} catch (Exception e) {
return false;
}
}
@Override
public int hashCode() {
return (this.getProduct().getCode() + "" + this.getProduct().getCode()).hashCode();
}
}
销售订单实体
@Entity
@Table(name = "salesOrder")
public class SalesOrder extends BaseEntity{
@Id
private String orderNumber;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "customerCode", nullable = false)
private Customer customer;
private double totalPrice;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "salesOrder", cascade = CascadeType.ALL)
private List<OrderLine> lines;
@Override
public boolean equals(Object obj) {
try {
SalesOrder so = (SalesOrder) obj;
if (this.getOrderNumber().equals(so.getOrderNumber())) {
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
@Override
public int hashCode() {
return this.getOrderNumber().hashCode();
}
}
可嵌入Class
@Embeddable
public class LineID implements Serializable{
private static final long serialVersionUID = -4478828739881744452L;
@Basic(optional = false)
private String productCode;
@Basic(optional = false)
private String orderNumber;
@Override
public boolean equals(Object obj) {
try {
LineID l = (LineID) obj;
return this.productCode.equals(l.getProductCode()) && this.orderNumber.equals(l.getOrderNumber());
} catch (Exception e) {
return false;
}
}
@Override
public int hashCode() {
return (this.getOrderNumber() + "" + this.getProductCode()).hashCode();
}
}
更新
SQL 由 Hibernate 生成:
Hibernate: create table customer (code varchar(255) not null, status varchar(255) not null, address varchar(255), creditLimit double precision not null, currentCredit double precision not null, name varchar(255), phone1 varchar(255), phone2 varchar(255), primary key (code))
Hibernate: create table orderLine (orderNumber varchar(255), productCode varchar(255), status varchar(255) not null, quantity integer not null, totalPrice double precision not null, unitPrice double precision not null, primary key (orderNumber, productCode))
Hibernate: create table product (code varchar(255) not null, status varchar(255) not null, description varchar(255), price double precision not null, quantity integer not null, primary key (code))
Hibernate: create table salesOrder (orderNumber varchar(255) not null, status varchar(255) not null, totalPrice double precision not null, customerCode varchar(255) not null, primary key (orderNumber))
Hibernate: alter table orderLine add constraint UK_9gf3j9l0n1w7d2h4sso3voc77 unique (productCode)
Hibernate: alter table orderLine add index FK_9gf3j9l0n1w7d2h4sso3voc77 (productCode), add constraint FK_9gf3j9l0n1w7d2h4sso3voc77 foreign key (productCode) references product (code)
Hibernate: alter table orderLine add index FK_ojvge4lucwf2gtihxtmnav3u2 (orderNumber), add constraint FK_ojvge4lucwf2gtihxtmnav3u2 foreign key (orderNumber) references salesOrder (orderNumber)
Hibernate: alter table salesOrder add index FK_4lq8ynumala22y9t17ceawo81 (customerCode), add constraint FK_4lq8ynumala22y9t17ceawo81 foreign key (customerCode) references customer (code)
Hibernate: alter table orderLine 添加约束 UK_9gf3j9l0n1w7d2h4sso3voc77 unique (productCode)
以上SQL不打算生成。如果我能避开这个独特的约束,问题就迎刃而解了。
感谢解决此问题的任何帮助。
我认为您可能遗漏了 @MapsId 注释:
@Entity
@Table(name = "orderLine")
public class OrderLine implements Serializable{
private static final long serialVersionUID = -851110991599534263L;
@AttributeOverrides(value =
{@AttributeOverride(column = @Column(name="productCode"), name = "productCode"),
@AttributeOverride(column = @Column(name="orderNumber"), name = "orderNumber")})
@EmbeddedId
private LineID pk;
@ManyToOne(cascade = CascadeType.ALL)
@MapsId("productCode")
private Product product;
private int quantity;
private double unitPrice;
private double totalPrice;
@ManyToOne(fetch = FetchType.EAGER)
@MapsId("orderNumber")
private SalesOrder salesOrder;
@Override
public boolean equals(Object obj) {
try {
LineID line = (LineID) obj;
return (this.getSalesOrder().getOrderNumber()
.equals(line.getOrderNumber()) && this.getProduct()
.getCode().equals(line.getProductCode()));
} catch (Exception e) {
return false;
}
}
@Override
public int hashCode() {
return (this.getProduct().getCode() + "" + this.getProduct().getCode()).hashCode();
}
}
我遇到了一个 Hibernate 错误,它说 找到了超过一行具有给定标识符的行,我一直坚持下去。 如果能提供任何帮助,我将不胜感激。
- 我想创建一个 table 作为 orderLine,其中包含特定销售订单的产品代码、数量等。
一个SalesOrder可以包含很多orderLines。
orderLine table 的复合键是 productCode + OrderNumber。 ProductCode 是 Product table 的主键,OrderNumber 是 SalesOrder table 的主键。
- 在一个 SalesOrder 中,特定产品应该只有一个订单行。
复合键正确生成,我得到休眠记录的以下 sql 语句。
Hibernate:创建table orderLine(orderNumber varchar(255) 不为空,productCode varchar(255) 不为空,status varchar(255) 不为空,数量整数不为空,totalPrice 双精度不为空, unitPrice double precision not null, primary key (orderNumber, productCode))
当 OrderLine table 包含如下数据时,我成功地向 OrderLine table 插入了一条新记录 OrderNumber ORD001 & 产品代码 BIS1003
当我尝试从 OrderLine 获取记录后,立即出现以下错误。
原因:org.hibernate.HibernateException:找到具有给定标识符的多行:BIS1003,对于 class:com.salesOrder_ws.entity.OrderLine
既然有组合键为主,为什么组合键只有一个键不唯一时hibernate抛出异常?
代码如下。
订单行实体:
@Entity
@Table(name = "orderLine")
public class OrderLine implements Serializable{
private static final long serialVersionUID = -851110991599534263L;
@AttributeOverrides(value =
{@AttributeOverride(column = @Column(name="productCode"), name = "productCode"),
@AttributeOverride(column = @Column(name="orderNumber"), name = "orderNumber")})
@EmbeddedId
private LineID pk;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "productCode", insertable = false, updatable = false)
private Product product;
private int quantity;
private double unitPrice;
private double totalPrice;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "orderNumber", nullable=false, insertable=false, updatable=false)
private SalesOrder salesOrder;
@Override
public boolean equals(Object obj) {
try {
LineID line = (LineID) obj;
return (this.getSalesOrder().getOrderNumber()
.equals(line.getOrderNumber()) && this.getProduct()
.getCode().equals(line.getProductCode()));
} catch (Exception e) {
return false;
}
}
@Override
public int hashCode() {
return (this.getProduct().getCode() + "" + this.getProduct().getCode()).hashCode();
}
}
销售订单实体
@Entity
@Table(name = "salesOrder")
public class SalesOrder extends BaseEntity{
@Id
private String orderNumber;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "customerCode", nullable = false)
private Customer customer;
private double totalPrice;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "salesOrder", cascade = CascadeType.ALL)
private List<OrderLine> lines;
@Override
public boolean equals(Object obj) {
try {
SalesOrder so = (SalesOrder) obj;
if (this.getOrderNumber().equals(so.getOrderNumber())) {
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
@Override
public int hashCode() {
return this.getOrderNumber().hashCode();
}
}
可嵌入Class
@Embeddable
public class LineID implements Serializable{
private static final long serialVersionUID = -4478828739881744452L;
@Basic(optional = false)
private String productCode;
@Basic(optional = false)
private String orderNumber;
@Override
public boolean equals(Object obj) {
try {
LineID l = (LineID) obj;
return this.productCode.equals(l.getProductCode()) && this.orderNumber.equals(l.getOrderNumber());
} catch (Exception e) {
return false;
}
}
@Override
public int hashCode() {
return (this.getOrderNumber() + "" + this.getProductCode()).hashCode();
}
}
更新
SQL 由 Hibernate 生成:
Hibernate: create table customer (code varchar(255) not null, status varchar(255) not null, address varchar(255), creditLimit double precision not null, currentCredit double precision not null, name varchar(255), phone1 varchar(255), phone2 varchar(255), primary key (code))
Hibernate: create table orderLine (orderNumber varchar(255), productCode varchar(255), status varchar(255) not null, quantity integer not null, totalPrice double precision not null, unitPrice double precision not null, primary key (orderNumber, productCode))
Hibernate: create table product (code varchar(255) not null, status varchar(255) not null, description varchar(255), price double precision not null, quantity integer not null, primary key (code))
Hibernate: create table salesOrder (orderNumber varchar(255) not null, status varchar(255) not null, totalPrice double precision not null, customerCode varchar(255) not null, primary key (orderNumber))
Hibernate: alter table orderLine add constraint UK_9gf3j9l0n1w7d2h4sso3voc77 unique (productCode)
Hibernate: alter table orderLine add index FK_9gf3j9l0n1w7d2h4sso3voc77 (productCode), add constraint FK_9gf3j9l0n1w7d2h4sso3voc77 foreign key (productCode) references product (code)
Hibernate: alter table orderLine add index FK_ojvge4lucwf2gtihxtmnav3u2 (orderNumber), add constraint FK_ojvge4lucwf2gtihxtmnav3u2 foreign key (orderNumber) references salesOrder (orderNumber)
Hibernate: alter table salesOrder add index FK_4lq8ynumala22y9t17ceawo81 (customerCode), add constraint FK_4lq8ynumala22y9t17ceawo81 foreign key (customerCode) references customer (code)
Hibernate: alter table orderLine 添加约束 UK_9gf3j9l0n1w7d2h4sso3voc77 unique (productCode)
以上SQL不打算生成。如果我能避开这个独特的约束,问题就迎刃而解了。
感谢解决此问题的任何帮助。
我认为您可能遗漏了 @MapsId 注释:
@Entity
@Table(name = "orderLine")
public class OrderLine implements Serializable{
private static final long serialVersionUID = -851110991599534263L;
@AttributeOverrides(value =
{@AttributeOverride(column = @Column(name="productCode"), name = "productCode"),
@AttributeOverride(column = @Column(name="orderNumber"), name = "orderNumber")})
@EmbeddedId
private LineID pk;
@ManyToOne(cascade = CascadeType.ALL)
@MapsId("productCode")
private Product product;
private int quantity;
private double unitPrice;
private double totalPrice;
@ManyToOne(fetch = FetchType.EAGER)
@MapsId("orderNumber")
private SalesOrder salesOrder;
@Override
public boolean equals(Object obj) {
try {
LineID line = (LineID) obj;
return (this.getSalesOrder().getOrderNumber()
.equals(line.getOrderNumber()) && this.getProduct()
.getCode().equals(line.getProductCode()));
} catch (Exception e) {
return false;
}
}
@Override
public int hashCode() {
return (this.getProduct().getCode() + "" + this.getProduct().getCode()).hashCode();
}
}