Hibernate:保存一对二的强制性关系

时间:2013-08-09 14:23:06

标签: hibernate persistence

我有两个实体: A B B 使用与 A 实体相同的PK。 A B one-2-one 可选 = false assosiation相关联。

我做了什么:

//in session scope
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
session.save(a); 
session.flush(); //EXCEPTION!

例外:

org.postgresql.util.PSQLException:错误:表“B”上的插入或更新违反了外键约束“fk_A_pk”   细节:表“A”中没有键(id)=(5600)

出了什么问题:

由于 PS3 ,我无法使用null B 属性保存 A ,因为关系是强制性的。但我不能 使用非null属性保存 A ,因为 A 还没有aID, B 无法想象自己的ID。

问题:

我怎样才能保存 A& B 实体?

PS1 B.PK同时是FK到A.PK字段。

PS2 生成的sql ,我看到Hibernate在继续'插入A''插入B ...'查询>。

PS3

A class:

@Entity
@Table(name = "A")
@Inheritance(strategy= InheritanceType.JOINED)
public class A{

    @Id
    @SequenceGenerator(name = "a_sequence", sequenceName = "sq_a")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "a_sequence")
    @Column(name = "id")
    private long aID;

    @JsonIgnore
    @OneToOne(mappedBy="a", cascade = CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
    private B b;
}

B class:

@Entity
@Table(name="b")
public class B {
    @Id
    @Column(name="id", unique=true, nullable=false)
    @GeneratedValue(generator="gen")
    @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="a"))
    private long aID;

    @JsonIgnore
    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL)
    private A a;
}

ADDITION(PostgreSQL DDL):

CREATE TABLE A
(
  id bigint NOT NULL,
  CONSTRAINT pk_file PRIMARY KEY (id )
)

CREATE TABLE B
(
  id integer NOT NULL,
  CONSTRAINT pk_file PRIMARY KEY (id ),
  CONSTRAINT fk_a_pk FOREIGN KEY (id)
      REFERENCES A (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

1 个答案:

答案 0 :(得分:1)

optional = false上的

tl; dr:A告诉Hibernate首先插入B

使关联单向

JPA JavaDoc提供了one-to-one association that assumes both the source and target share the same primary key values的示例,但它使用了单向关联:

  1. A删除关联:

    @Entity
    public class A {
        @Id
        @SequenceGenerator(...)
        @GeneratedValue(...)
        private long aId;
    }
    
  2. 如果您使用的是支持JPA 2.0的Hibernate版本(最新版本),请在@MapsId上指定B属性,删除外部生成器:

    @Entity
    public class B {
        @Id
        private long aId;
    
        @OneToOne
        @MapsId
        private A a;
    }
    
  3. 保持协会双向

    您无法将optional = false放在@OneToOne中的A注释中。由于引用B.id的外键(A)是必需的,因此您应首先插入A

    INSERT INTO A (id) VALUES (1);
    -- there isn't a corresponding record in B,
    -- until we perform a second insert into B:
    INSERT INTO B (id) VALUES (1);
    

    知道这一点,让我们再次双向关联:

    @Entity
    public class A {
        @Id
        @SequenceGenerator(...)
        @GeneratedValue(...)
        private long aId;
    
        // should work without 'optional = false'
        @OneToOne(mappedBy = "a",  cascade = CascadeType.ALL, fetch = FetchType.LAZY)
        private B b;
    }
    

    另见Primary Keys through OneToOne and ManyToOne Relationships