JPA 2.0 + 一对一 + 未设置共享主键

Posted

技术标签:

【中文标题】JPA 2.0 + 一对一 + 未设置共享主键【英文标题】:JPA 2.0 + One to One + Shared Primary Key not being set 【发布时间】:2012-12-26 11:54:05 【问题描述】:

有两个表 Customer 和 Upload,我在其中跟踪客户上传的项目数量。它与共享主键CustomerID 是一对一的关系,这是一个唯一标识符。我正在努力让保存工作。我正在使用 Hibernates uuid2 策略来处理唯一标识符的创建/保存。在我包含上传实体之前,客户将使用 uuid 正确保存。基本上,我希望每当有人制作客户对象时创建上传。

客户:

@Entity
public class Upload implements Serializable 
    @Column(name="UPLOADCOUNT",    nullable=true,  unique=false)
    private Integer uploadCount = new Integer(0); 

    @MapsId ("CUSTOMERID")
    @OneToOne (optional=false)
    @JoinColumn(name="CUSTOMERID", referencedColumnName = "CUSTOMERID", nullable=false,  unique=true ) 
    private Customer customer;  

    @Id 
    @Column(name="CUSTOMERID", length=36, nullable=false, unique=true, insertable=false, updatable=false)
    private String customerId_;

     public Upload(Customer customer)     
         this.customer = customer;
     

上传:

@Entity
public class Customer implements Serializable 


    @Id
    @Column(name = "CUSTOMERID", unique = true)
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String customerId;

    @OneToOne(mappedBy = "customer", optional = false, cascade = CascadeType.ALL)
    private Upload upload ; 


    public Customer() 
        this.upload = new Upload(this);        
    

要保存的代码:

Customer customer = new Customer();
EntityManager em = EntityManagerUtil.getEntityManager();
EntityTransaction trans = em.getTransaction();

trans.begin();
em.persist(customer);
trans.commit();

例外:

 javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): Upload

【问题讨论】:

在您的“保存”代码中:entity 是什么? 是客户。我已经更新了代码 【参考方案1】:

你可以试试这个,而不是@JoinColumn

@PrimaryKeyJoinColumn(name="CUSTOMERID", referencedColumnName="CUSTOMERID")

更多详情here

或者另一种可能的解决方案:像这样更新您的 Upload 类。

@Id 
@Column(name="CUSTOMERID", length=36, nullable=false, unique=true, insertable=false, updatable=false)
@GeneratedValue(generator=”foreign”) 
@GenericGenerator(name=”foreign”, strategy = “foreign”, parameters =    @Parameter(name=”property”, value=”customer”))
private String customerId_;

【讨论】:

感谢您的快速响应,但我仍然遇到同样的错误。 @Nadin 刚刚用另一种可能的解决方案编辑了我的帖子(使用休眠特定的东西) 同样的结果。我会认为这是一个常见的情况。【参考方案2】:

创建自生成的 UUID 相关实体的重要一点是将 UUID 设置为 null 值。

如果我们对 uuid 进行硬编码,例如,一个 UUID.randomUUID(),我们会得到一个类似于 PSQLException: null value in column "second_table_uuid" violates not-null constraint 的 fk 错误

在创建对象时,确保相关实体的构造函数的默认值为null。如果它是包含 B 的实体 A,则只需要 B 的 uuid 中的 null 而不是 A 的 null。但以防万一,除非您已经知道 fk,否则您可以将 null 放入所有 UUID。

另一个重要的事情是使用@JoinColumn而不是@PrimaryKeyJoinColumn,这也会产生错误。

我附上了我制作的代码的 sn-p。

@Entity
@Table(name = "parent")
data class Parent(
        @Id
        @GeneratedValue
        @Column(name = "parent_uuid")
        val parentUUID: UUID? = null,

        @OneToOne(cascade = [CascadeType.ALL])
        @JoinColumn(name = "child_uuid", referencedColumnName = "child_uuid")
        var child: Child
) 
        constructor() : this(child = Child())


@Entity
@Table(name = "child")
data class Child(
        @Id 
        @GeneratedValue 
        @Column(name = "child_uuid") 
        val childUUID: UUID? = null,
    
        @Column(name = "name") 
        val name: String,
) 
        constructor() : this(name = "")

并且组合将在 UUID 中留下隐含的空值。

val child = Child(name = "test")
val parent = Parent(child = child)

GL

【讨论】:

以上是关于JPA 2.0 + 一对一 + 未设置共享主键的主要内容,如果未能解决你的问题,请参考以下文章

JPA映射关系

JPA关系映射之one-to-one

JPA的一对多,多对多用法

关于JPA一对一,一对多(多对一),多对多的详解

springdata_多表关系中的一对一__小案例

如何确保休眠 5 在与共享主键的一对一关系中保持正确的顺序