春季 JPA - @OneToOne/@MapsId - 具有共享密钥的父/子:我得到这个 生成异常:试图从空一对一属性



添加具有相同键的@OneToOne关系的父项和子项时,我不断收到此错误。建议使用@MapsId。

id

.标识符生成异常:尝试从空一对一属性分配 id

我尝试了通常的解决方案,但这并没有解决问题。

  • 让父项和子项相互指向
  • 正确的事务性(是 springframework 的(
  • 使用所有者的存储库进行保存。由于违反了上限限制,这不起作用。

我的父实体是(名称有目的(:

@Entity
@Table(name = "JOHAN_SHARED_SUPPLIER")
public class EntitySharedSupplier {
@Id
@Column(name = "supplier_shared_id")
private Long javaSharedSupplierId;
@Column(name = "supplier_shared_name")
private String javaSharedSupplierName;
@Column(name = "contact_shared_name")
private String javaSharedSupplierContactName;
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY,
mappedBy = "supplierSharedRef", orphanRemoval = true)
private EntitySharedProduct javaSharedProduct;

孩子是:

@Entity
@Table(name = "JOHAN_SHARED_PRODUCTS")
public class EntitySharedProduct {
@Id
@Column(name = "shared_supplier_id")
private Long javaSupplierSharedId;
@MapsId
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="shared_supplier_id")
private EntitySharedSupplier supplierSharedRef;
@Column(name = "prod_supplier_name")
private String javaSharedProductName;

父级的存储库是:

@Repository
@Transactional
public interface SupplierSharedRepo extends JpaRepository<EntitySharedSupplier, Long> {
}

服务代码:

@Transactional
public void saveSupplier(int sup) {
EntitySharedSupplier supplier = new EntitySharedSupplier();
supplier.setJavaSharedSupplierId((long) sup);
supplier.setJavaSharedSupplierName("SharedSupplier-" + sup);
supplier.setJavaSharedSupplierContactName("SharedSupplier-contact-" + sup);
EntitySharedProduct product = new EntitySharedProduct();
product.setJavaSharedProductName("SharedSupplier-Book-" + sup);
product.setSupplierSharedRef(supplier);
supplier.setJavaSharedProduct( product);
supplierSharedRepo.save(supplier);
}

在这种情况下,解决方案有点困难。

解决方案是通过更改父对象中的设置 id/key 方法:

public void setJavaSharedSupplierId(Long javaSupplierId) {
this.javaSharedSupplierId = javaSupplierId;
if( javaSharedProduct != null) {
javaSharedProduct.setJavaSupplierSharedId( javaSupplierId);
}
}

注意

  • 在大多数情况下,在休眠/jpa 保存过程的后期,您会自动生成父级的 ID/密钥。那时,父母和孩子之间的联系已经完成。
  • 在这种情况下,解决方案有效,因为首先在父级和子级之间建立连接,然后设置父级的手动 ID/密钥

在那之前,我一直得到原始错误(如问题所示(或未设置 id 的 id。

该解决方案需要在创建父/子对象时进行少量更改。

@Transactional
public void saveSupplier(int sup) {
EntitySharedSupplier supplier = new EntitySharedSupplier();
supplier.setJavaSharedSupplierName("SharedSupplier-" + sup);
supplier.setJavaSharedSupplierContactName("SharedSupplier-contact-" + sup);
EntitySharedProduct product = new EntitySharedProduct();
product.setJavaSharedProductName("SharedSupplier-Book-" + sup);
product.setSupplierSharedRef(supplier);
supplier.setJavaSharedProduct( product);
// The next statement has to be put after the previous
supplier.setJavaSharedSupplierId((long) sup);
supplierSharedRepo.save(supplier);
}

该解决方案有效且易于理解。我也有软件不需要在父 ID 中手动设置子 ID。到目前为止,我还没有找到该软件为什么有效。

如果您有更好的解决方案,请告诉我/我们!

相关内容

最新更新