0

1対多の関係を持つ2つのテーブルAとBがあります。両方のテーブルには、自動インクリメントされる id フィールドがあります。テーブル B には、テーブル A の id フィールドを参照する外部キー フィールドもあります。

MySQL DB のテーブル スキーマは次のとおりです。

CREATE TABLE A (
  `id` INT NOT NULL AUTO_INCREMENT,
  `afield` varchar(255),
  PRIMARY KEY  (`id`)
) ;

CREATE TABLE B (
  `id` INT NOT NULL AUTO_INCREMENT,
  `aId` INT NOT NULL,
  `bfield` varchar(255),
  PRIMARY KEY  (`id`),
  FOREIGN KEY (`aId`)REFERENCES A(`id`) ON DELETE CASCADE
) ;

クラス:

@Entity
@Table(name = "A")
public class A implements java.io.Serializable {

    private Integer id;
    private String aField;

    private List b;

    public A() {}

    public A(Integer id) {
        this.id = id;
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GenericGenerator(name = "generator", strategy = "native")
    @GeneratedValue(generator = "generator")
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "AFIELD", length = 50)
    public String getAField() {
        return this.aField;
    }

    public void setAField(String aField) {
        this.aField = aField;
    }

    //mapped by = "a" a is a field in B. Case sensetive @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "a") 
    public List getB() {
        return b;
    }

    public void setB(List b) {
        this.b = b;
    }
}

@Entity
@Table(name = "B")
public class B implements java.io.Serializable {

    private String bField;
    private Integer id;
    private Integer aId;

    private A a;

    public B() {}

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GenericGenerator(name = "generator", strategy = "native")
    @GeneratedValue(generator = "generator")
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "aId")
    public Integer getAId() {
        return this.aId;
    }

    public void setAId(Integer aId) {
        this.aId = aId;
    }

    @Column(name = "BFIELD", length = 50)
    public String getBField() {
        return this.bField;
    }

    public void setBField(String bField) {
        this.bField = bField;
    }

    @ManyToOne
    @JoinColumn(name = "aId", insertable = false, updatable = false)
    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }
}

以下は私のテスト方法です:

public static void main(String[] args) {
    try {
        Configuration cfg = new Configuration().configure();
        SessionFactory factory = cfg.buildSessionFactory();
        Session sess = factory.getCurrentSession();
        Transaction tx = sess.beginTransaction();
        A a = new A();
        a.setAField("afield");
        // sess.save(a);
        // sess.flush();

        List < B > bs = new ArrayList < B > ();
        a.setB(bs);
        B b = new B();
        b.setBField("bfield");
        // b.setAId(a.getId());
        bs.add(b);

        sess.saveOrUpdate(a);
        tx.commit();
        factory.close();
    } catch (Throwable ex) {
        throw new ExceptionInInitializerError(ex);
    }
}

コメントアウトされた 3 行を有効にすると、正常に動作します。基本的に、オブジェクト a から ID を取得し、それをオブジェクト b に設定します。

しかし、b オブジェクトのリストを保存する前にオブジェクトを保存する必要があることに満足していません。とにかく、コメントアウトされた3行がなくても機能するということはありますか? シナリオは、他の人がオブジェクト a を作成し、リスト オブジェクト b を設定してから、2 つのオブジェクトの関係の詳細を知らず、スキーマも知らないため、オブジェクト a を保存する可能性があるというものです。

どんな助けでも大歓迎です!

4

1 に答える 1

0

送信する前に、質問の形式を整えてください。

つまりaId、テーブル B の列は 2 回マップされます。1 回はaIdフィールド用、もう 1 回は ですa。このaId列は消えるはずです。B から A への関連付けのみが必要です。A フォーム B の ID が必要な場合は、 を呼び出すだけb.getA().getId()です。

もう 1 つの重要な点は、双方向の関連付けがあることです。エンティティ グラフが一貫していることを確認する必要があります。A の B のリストに B を追加する場合は、 B の A フィールドも設定する必要があります。

a.getBs().add(b);
b.setA(a);

Hibernate は、アソシエーションの片側のみを見て、何を永続化するかを判断します。mappedByこちら側は属性を持たない側です。これは、b.setA(a)それを機能させるために絶対に呼び出す必要があることを意味します。

于 2011-10-21T21:39:29.733 に答える