2011-10-23 12 views
9

私は2つの単純な豆、FatKidとHamburgersを持っています。今、私に知られていない理由のために、私は誰かが食べたハンバーガーを見上げるだけでなく、誰が特定のハンバーガーを食べたかを調べることができる必要があります。コード上に!HibernateとH2 OneToMany双方向マッピングのための "参照整合性制約違反"

FatKid.java

import java.util.List; 
import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 

@Table 
@Entity 
public class FatKid { 

    private int id; 
    private String name; 
    private List<Hamburger> hamburgers; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "FATKID_ID") 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 

    @Column 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name="HAMBURGER_ID") 
    public List<Hamburger> getHamburgers() { 
     return hamburgers; 
    } 
    public void setHamburgers(List<Hamburger> hamburgers) { 
     this.hamburgers = hamburgers; 
    } 

} 

Hamburger.java

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

@Table 
@Entity 
public class Hamburger { 

    private int id; 
    private String description; 
    private FatKid whoDoneAteMe; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "HAMBURGER_ID") 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 

    @Column 
    public String getDescription() { 
     return description; 
    } 
    public void setDescription(String description) { 
     this.description = description; 
    } 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name="FATKID_ID") 
    public FatKid getWhoDoneAteMe() { 
     return whoDoneAteMe; 
    } 
    public void setWhoDoneAteMe(FatKid whoDoneAteMe) { 
     this.whoDoneAteMe = whoDoneAteMe; 
    } 

} 

hibernate.cfg.xmlの

<?xml version='1.0' encoding='utf-8'?> 
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD//EN" 
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 

<hibernate-configuration> 
    <session-factory> 
     <property name="hibernate.connection.driver_class">org.h2.Driver</property> 
     <property name="hibernate.connection.url">jdbc:h2:~/routesetting</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property> 

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

     <!-- Enable Hibernate's automatic session context management --> 
     <property name="current_session_context_class">thread</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-drop</property> 

     <mapping class="FatKid" /> 
     <mapping class="Hamburger" /> 

    </session-factory> 
</hibernate-configuration> 

依存性

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-core</artifactId> 
    <version>3.6.7.Final</version> 
</dependency> 

<dependency> 
    <groupId>com.h2database</groupId> 
    <artifactId>h2</artifactId> 
    <version>1.3.160</version> 
</dependency> 

<dependency> 
    <groupId>javassist</groupId> 
    <artifactId>javassist</artifactId> 
    <version>3.9.0.GA</version> 
</dependency> 
私は、コードを実行したときに

クライアント

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.cfg.Configuration; 

public class OmNom { 

    private static final SessionFactory sessionFactory = buildSessionFactory(); 

    public static void main(String[] args) { 

     Session session = sessionFactory.openSession(); 

     session.beginTransaction(); 
     FatKid fk = new FatKid(); 
     fk.setName("Darrell"); 
     session.save(fk); 
     session.getTransaction().commit(); 

     session.beginTransaction(); 
     Hamburger hamburger_1 = new Hamburger(); 
     hamburger_1.setDescription("Juicy quarter pounder with cheese"); 
     hamburger_1.setWhoDoneAteMe(fk); 
     session.save(hamburger_1); 
     session.getTransaction().commit(); 

     session.beginTransaction(); 
     Hamburger hamburger_2 = new Hamburger(); 
     hamburger_2.setDescription("Ground buffalo burger topped with bacon and a sunny-side egg"); 
     hamburger_2.setWhoDoneAteMe(fk); 
     session.save(hamburger_2); 
     session.getTransaction().commit(); 

     sessionFactory.close(); 

    } 

    private static SessionFactory buildSessionFactory() { 
     try { 
      // Create the SessionFactory from hibernate.cfg.xml 
      return new Configuration().configure().buildSessionFactory(); 
     } 
     catch (Throwable ex) { 
      // Make sure you log the exception, as it might be swallowed 
      throw new ExceptionInInitializerError(ex); 
     } 
    } 

} 

は、だから私は、出力(および切り捨てスタックトレース)で終わる

Hibernate: insert into FatKid (FATKID_ID, name) values (null, ?) 
Hibernate: insert into Hamburger (HAMBURGER_ID, description, FATKID_ID) values (null, ?, ?) 
Hibernate: insert into Hamburger (HAMBURGER_ID, description, FATKID_ID) values (null, ?, ?) 
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not insert: [Hamburger] 
     ... 
Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK43797FE95067143: PUBLIC.HAMBURGER FOREIGN KEY(HAMBURGER_ID) REFERENCES PUBLIC.FATKID(FATKID_ID)"; SQL statement: 
insert into Hamburger (HAMBURGER_ID, description, FATKID_ID) values (null, ?, ?) [23506-160] 
     ... 

だから、最初のハンバーガーが保存されているが、それは、次に、第2の上に吹きます。どちらもFatKidのIDを外部キーとして使用できるはずですが、動作していないようです。どんな洞察力も大変高く評価されます。

おかげで、 ケビン

答えて

6

あなたのマッピングが私には奇妙に見えます。関係の両側に@JoinColumnがあり、それぞれが別のテーブルの主キーを指しています。それはOneToMany関係ではないようです。

@OneToMany(cascade = CascadeType.ALL, mappedBy = "whoDoneAteMe") 
public List<Hamburger> getHamburgers() { 
    return hamburgers; 
} 

し、他の側に:

@ManyToOne(cascade = CascadeType.ALL) 
@JoinColumn(name = "fatkid_id") 
public FatKid getWhoDoneAteMe() { 
    return whoDoneAteMe; 
} 

あなたはさらに、あまりにもあなたのコードを最適化することができるかもしれない

あなたのOneToManyは関係の所有者を教えてください。あなたのFatKidオブジェクトは、ハンバーガーオブジェクトを認識し、あなたがカスケードを構成している、あなたが行うことができたよう:

session.beginTransaction(); 
    FatKid fk = new FatKid(); 
    fk.setName("Darrell"); 

    Hamburger hamburger_1 = new Hamburger(); 
    hamburger_1.setDescription("Juicy quarter pounder with cheese"); 
    hamburger_1.setWhoDoneAteMe(fk); 
    fk.getHamburgers().add(hamburger1); 

    Hamburger hamburger_2 = new Hamburger(); 
    hamburger_2.setDescription("Ground buffalo burger topped with bacon and a sunny-side egg"); 
    hamburger_2.setWhoDoneAteMe(fk); 
    fk.getHamburgers().add(hamburger2); 

    session.save(fk); 
    session.getTransaction().commit(); 

    sessionFactory.close(); 

上記のコードはただ一つの操作をコミットし、単一のトランザクション内で完全なオブジェクトグラフを保存する必要があります。

+0

ありがとう、その余分な@JoinColumnを削除し、mappedByを追加すると動作しました。 – Kevin

関連する問題