2

我有两个实体:ABB使用与A实体相同的 PK 。ABone-2-one链接,可选= 错误关联。

我所做的:

//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,我无法使用空B属性保存A,因为关系是强制性的。但是我不能用非空属性保存A ,因为A还没有 aID,而B无法想象自己的 id。

问题:

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

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

PS2生成的 sql中,我看到 Hibernate 在继续'insert into A'之前尝试继续'insert into B ...'查询。

PS3

一类:

@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类:

@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;
}

添加(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
)
4

1 回答 1

1

tl; dr:optional = falseonA告诉 Hibernate 先插入B

使关联单向

JPA JavaDoc 提供了一个一对一关联的示例,假设源和目标共享相同的主键值,但它使用单向关联:

  1. 从 中删除关联A

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

    @Entity
    public class B {
        @Id
        private long aId;
    
        @OneToOne
        @MapsId
        private A a;
    }
    

保持关联双向

你不能把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;
}

另请参阅通过 OneToOne 和 ManyToOne 关系的主键

于 2013-08-09T15:23:37.117 回答