刷新单向实体时不违反空约束
Posted
技术标签:
【中文标题】刷新单向实体时不违反空约束【英文标题】:Not null constraint violation when flushing unidirectional entities 【发布时间】:2020-11-06 12:23:51 【问题描述】:我正在使用 @OneToMany
和 @ManyToOne
注释进行单向和双向映射,但在持久化实体并将它们刷新到数据库时,我无法打破单向映射的障碍。
所以,两个表delivery_company
可能有很多delivery
:
SQL(甲骨文):
CREATE TABLE delivery (
delivery_id NUMBER(6) NOT NULL,
price NUMBER(5, 2) NOT NULL,
delivery_time DATE NOT NULL,
delivery_company_id NUMBER(2) NOT NULL
);
ALTER TABLE delivery ADD CONSTRAINT delivery_pk PRIMARY KEY ( delivery_id );
CREATE TABLE delivery_company (
delivery_company_id NUMBER(2) NOT NULL,
delivery_company_name VARCHAR2(15 CHAR) NOT NULL
);
ALTER TABLE delivery_company ADD CONSTRAINT delivery_company_pk PRIMARY KEY ( delivery_company_id );
ALTER TABLE delivery
ADD CONSTRAINT delivery_delivery_company_fk FOREIGN KEY ( delivery_company_id )
REFERENCES delivery_company ( delivery_company_id );
单向映射:
@Entity
@Table(name = "Delivery")
class DeliveryUniDirectional
@Id
@SequenceGenerator(name = "delivery_id_sequence", sequenceName = "delivery_id_sequence", allocationSize = 1)
@GeneratedValue(generator = "delivery_id_sequence", strategy = GenerationType.SEQUENCE)
@Column(name = "delivery_id")
public Long deliveryId;
public BigDecimal price;
@Temporal(TemporalType.DATE)
public Date deliveryTime;
// setters, getters
@Entity
@Table(name = "delivery_company")
class DeliveryCompanyUniDirectional
@Id
@Column(name = "delivery_company_id")
@SequenceGenerator(name = "delivery_company_id_sequence", sequenceName = "delivery_company_id_sequence", allocationSize = 1)
@GeneratedValue(generator = "delivery_company_id_sequence", strategy = GenerationType.SEQUENCE)
private Long deliveryCompanyId;
@Column(unique = true)
private String deliveryCompanyName;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "delivery_id", nullable = false, insertable = false, updatable = false)
private List<DeliveryUniDirectional> deliveries = new LinkedList<>();
// setters getters
当我运行@DataJpaTest
测试时:
@Test
public void insertDeliveryUniDirectional()
DeliveryCompanyUniDirectional deliveryCompany = new DeliveryCompanyUniDirectional();
deliveryCompany.setDeliveryCompanyName("aa");
DeliveryUniDirectional delivery = new DeliveryUniDirectional();
delivery.setPrice(BigDecimal.ONE);
delivery.setDeliveryTime(new Date());
deliveryCompany.getDeliveries().add(delivery);
entityManager.persist(deliveryCompany);
entityManager.flush();
我收到
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute batch ...
//
Caused by: java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("TESTUSER"."DELIVERY"."DELIVERY_COMPANY_ID")
当entityManager.flush();
.
我尝试在 DeliveryCompanyUniDirectional
中使用 @JoinColumn
而不可插入和更新,但在这种情况下 hibernate 抱怨:
Error creating bean with name 'entityManagerFactory' defined in class path resource ...
// ...
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: wieczorek.jakub.shop.business.spring.model.domain.DeliveryUniDirectional column: delivery_id (should be mapped with insert="false" update="false")
delivery
表中外键的NOT NULL
约束肯定有问题。当我尝试使用双向映射时,持久化和刷新效果非常好,但我想使用单向实现同样的效果。
感谢阅读
【问题讨论】:
【参考方案1】:你的@JoinColumn 应该是delivery_company_id
,因为它是你的外键
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="delivery_company_id", referencedColumnName="delivery_company_id", nullable = false)
private List<DeliveryUniDirectional> deliveries = new LinkedList<>();
【讨论】:
我当时正准备不同意 Eklavya 的观点,因为此时 delivery_company_id 是您所在的表中的一列。但那是因为我略读并意识到你没有遵循我认为的约定:任何表中的 id 列都只是命名为 id,只有外键命名为nullable = false
,因为非空约束)。感谢@Zag 的有用评论。以上是关于刷新单向实体时不违反空约束的主要内容,如果未能解决你的问题,请参考以下文章