2

|AA| 多対多 |BB| 多対多 |CC|

結合テーブルでマップされた

|AA|--|AA_BB|--|BB|--|BB_CC|--|CC|

(画像載せれなくてごめんなさい、評判悪いです)

編集: 短い質問は、Aa 要素、Bb 要素、Cc 要素を作成して、Cc を Bb コレクションに追加し、Bb を Aa コレクションに追加する場合、Save(Aa) は正常に機能する (AA_BB が満たされている) のはなぜですか?

しかし、Bb 要素、Aa 要素、Cc 要素を作成すると、Bb コレクションに Aa を追加 Bb コレクションに Cc を追加 Save(Bb) (AA_BBが満たされていない?)

BB_CC は常に満たされます。

編集を終了

 CREATE TABLE BB_CC (
  BBIDBB number(10) NOT NULL, 
  CCIDCC number(10) NOT NULL, 
  PRIMARY KEY (BBIDBB, 
  CCIDCC));
CREATE TABLE AA_BB (
  AAIDAA number(10) NOT NULL, 
  BBIDBB number(10) NOT NULL, 
  PRIMARY KEY (AAIDAA, 
  BBIDBB));
CREATE TABLE CC (
  IDCC  number(10) NOT NULL, 
  DESCR varchar2(10) NOT NULL, 
  PRIMARY KEY (IDCC));
CREATE TABLE BB (
  IDBB  number(10) NOT NULL, 
  DESCR varchar2(10) NOT NULL, 
  PRIMARY KEY (IDBB));
CREATE TABLE AA (
  IDAA  number(10) NOT NULL, 
  DESCR varchar2(10) NOT NULL, 
  PRIMARY KEY (IDAA));
ALTER TABLE BB_CC ADD CONSTRAINT FKBB_CC976918 FOREIGN KEY (BBIDBB) REFERENCES BB (IDBB);
ALTER TABLE BB_CC ADD CONSTRAINT FKBB_CC529716 FOREIGN KEY (CCIDCC) REFERENCES CC (IDCC);
ALTER TABLE AA_BB ADD CONSTRAINT FKAA_BB470776 FOREIGN KEY (AAIDAA) REFERENCES AA (IDAA);
ALTER TABLE AA_BB ADD CONSTRAINT FKAA_BB23574 FOREIGN KEY (BBIDBB) REFERENCES BB (IDBB);

ハイバネート構成ファイル

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
<!--  ORACLE -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.url">jdbc:oracle:thin:@10.10.1.8:1521:GEROS</property>
        <property name="connection.username">xxxx</property>
        <property name="connection.password">xxxx</property>
        <property name="dialect">org.hibernate.dialect.OracleDialect</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup-->
        <property name="hbm2ddl.auto">create</property>

        <!-- Names the annotated entity class -->
        <mapping class="it.erreeffe.erreeffe2.Aa"/>
        <mapping class="it.erreeffe.erreeffe2.Bb"/>
        <mapping class="it.erreeffe.erreeffe2.Cc"/>
    </session-factory>
</hibernate-configuration>

また、テーブル Aa (Bb、Cc と同様) からの逆の jpa クラスには、いくつかの欠落部分があります。

@Entity
public class Aa implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="AA_IDAA_GENERATOR", sequenceName="SEQ_AA")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="AA_IDAA_GENERATOR")
    private long idaa;

    private String descr;

    //bi-directional many-to-many association to Bb
    @ManyToMany(cascade={CascadeType.ALL})
    @JoinTable(
        name="AA_BB"
        , joinColumns={
            @JoinColumn(name="AAIDAA")
            }
        , inverseJoinColumns={
            @JoinColumn(name="BBIDBB")
            }
        )
    private Set<Bb> bbs;

私のテストでは、最初の動作と 2 番目の動作はしません。

初め:

Session session;
        SessionFactory sf_ORA = new Configuration().configure(
                "hibernate.cfg.ora.xml").buildSessionFactory();
        session = sf_ORA.openSession();

//A
        Aa a = new Aa();
        a.setDescr("A1");
        a.setBbs(new HashSet<Bb>());
        //B
        Bb b1 = new Bb();
        b1.setCcs(new HashSet<Cc>());
        Bb b2 =new Bb();
        b2.setCcs(new HashSet<Cc>());
        b1.setDescr("B1");
        b2.setDescr("B2");
        //C
        Cc c1 = new Cc();
        Cc c2 = new Cc();
        Cc c3 = new Cc();
        c1.setDescr("C1");
        c2.setDescr("C2");
        c3.setDescr("C3");
        //FILL B
        b1.getCcs().add(c1);
        b1.getCcs().add(c2);
        b2.getCcs().add(c2);
        b2.getCcs().add(c3);
        //FILL A
        a.getBbs().add(b1);
        a.getBbs().add(b2);

session.beginTransaction();
        try
        {
            session.save(a);
            session.flush();
            session.getTransaction().commit();
        }
        catch(HibernateException ex)
        {
            session.getTransaction().rollback();
            throw ex;
        }

これは正しい仕事をします: Hibernate は私のために必要なすべてのステートメントを作成します:

Hibernate: insert into Aa (descr, idaa) values (?, ?)
Hibernate: insert into Bb (descr, idbb) values (?, ?)
Hibernate: insert into Cc (descr, idcc) values (?, ?)
Hibernate: insert into Cc (descr, idcc) values (?, ?)
Hibernate: insert into Bb (descr, idbb) values (?, ?)
Hibernate: insert into Cc (descr, idcc) values (?, ?)
Hibernate: insert into AA_BB (AAIDAA, BBIDBB) values (?, ?)
Hibernate: insert into AA_BB (AAIDAA, BBIDBB) values (?, ?)
Hibernate: insert into BB_CC (BBIDBB, CCIDCC) values (?, ?)
Hibernate: insert into BB_CC (BBIDBB, CCIDCC) values (?, ?)
Hibernate: insert into BB_CC (BBIDBB, CCIDCC) values (?, ?)
Hibernate: insert into BB_CC (BBIDBB, CCIDCC) values (?, ?)

結合された結果クエリは正しいです:

A1|B1|C1

A1|B1|C2

A1|B2|C2

A1|B2|C3

2番目 (たーだんここが問題) DBからB1を読み込み、新しいAa(A2)をB1.Aasコレクションに追加し、新しいCc(c4)をB1.Ccsコレクションに追加し、B1を更新。

Bb b1=null;
        session.beginTransaction();
        try
        {
            Query qGetB1=session.createQuery("Select id from Bb where DESCR ='B1'" );
            long idB1=(Long) qGetB1.list().get(0);
            b1=(Bb) session.load(Bb.class, idB1);
            session.flush();
            session.getTransaction().commit();
        }
        catch(HibernateException ex)
        {
            session.getTransaction().rollback();
            throw ex;
        }

        Aa a2 = new Aa();
        a2.setDescr("A2");
        Cc c4 = new Cc();
        c4.setDescr("C4");

        b1.getAas().add(a2);
        b1.getCcs().add(c4);


        session.beginTransaction();
        try
        {
            session.flush();
            session.saveOrUpdate(b1);
            session.flush();
            session.getTransaction().commit();
        }
        catch(HibernateException ex)
        {
            session.getTransaction().rollback();
            throw ex;
        }

Hibernate を生成します。

Hibernate: select bb0_.idbb as col_0_0_ from Bb bb0_ where DESCR='B1' //SEARCH B1 ID
Hibernate: select bb0_.idbb as idbb1_0_, bb0_.descr as descr1_0_ from Bb bb0_ where bb0_.idbb=? //GET B1
Hibernate: select aas0_.BBIDBB as BBIDBB1_1_, aas0_.AAIDAA as AAIDAA1_, aa1_.idaa as idaa0_0_, aa1_.descr as descr0_0_ from AA_BB aas0_, Aa aa1_ where aas0_.AAIDAA=aa1_.idaa and aas0_.BBIDBB=? GET B1.Aas
Hibernate: select ccs0_.BBIDBB as BBIDBB1_1_, ccs0_.CCIDCC as CCIDCC1_, cc1_.idcc as idcc2_0_, cc1_.descr as descr2_0_ from BB_CC ccs0_, Cc cc1_ where ccs0_.CCIDCC=cc1_.idcc and ccs0_.BBIDBB=? GET B1.Ccs
Hibernate: insert into Aa (descr, idaa) values (?, ?) //OK
Hibernate: insert into Cc (descr, idcc) values (?, ?) //OK
Hibernate: insert into BB_CC (BBIDBB, CCIDCC) values (?, ?) //OK


... What about AA_BB record???? //!!!!!!!!

joinTable AA_BB が満たされないのはなぜですか?

ご清聴ありがとうございました。よろしく、フランチェスコ。

4

1 に答える 1

6

双方向の関連付けの場合、一方が所有者側 (mappedBy属性のない側) であり、もう一方が逆側 (mappedBy属性のある側) です。

Hibernate は、所有者側のみが 2 つのエンティティ間に関連付けがあるかどうかを認識していると見なします。したがって、A と B の間の関係で A が所有者側である場合、B インスタンスを A のコレクションに追加して、関連付けを永続化する必要があります。A インスタンスを B のコレクションに追加しても効果はありません。

一般に、オブジェクト グラフの一貫性を維持する責任があるため、(少なくとも) 所有者側が常に更新されていることを確認する必要があります。

于 2012-03-09T14:50:13.013 に答える