2009-04-20 6 views
46

主キー/ Idが含まれていない(JPAが注釈付きのHibernate @Entityから)テーブルを作成することはできますか?HibernateとPKなし

これは良い考えではありません。テーブルには主キーが必要です。

+0

「シーケンス」(またはOracleを使用していない場合は同等)から自動挿入されるサロゲート・キーを作成できます。古いデータの場合は、新しく作成したキーに実行番号を設定できます。 –

答えて

10

私はそれができないことを発見しました。レガシーシステムで働いている人にとっては幸運です。

リバースエンジニアリング(既存のJDBC接続からJPAアノテーション付きエンティティを作成する場合)は、1つのエンティティと1つのフィールドを持つ2つのJavaクラスを作成します。 idと、あなたの関係からのすべての列を含む1つの埋め込み可能なID。

+0

本当ですか?下の@ awiedのソリューションはどうですか?それはWFMです。 – javamonkey79

+0

javamonkey79、@ awiedのソリューションと上記のソリューションは同じものです。 –

49

ロジャーの自己解答が正しい。 (私が最初にそれに明確ではありませんでしたし、これは役立つだろう考え出し)を意味しているものに少し詳しく説明します

はあなたのようなテーブルはFooを持っているとしましょう:

TABLE Foo (
bar varchar(20), 
bat varchar(20) 
) 

通常は、このテーブルで作業するための注釈付きのクラスを書くことができます:

..しかし、ダーン。この表にはIDとして使用できるものは何もありません。また、[重要なビジネス機能を挿入する]ために使用するレガシーデータベースです。彼らは私が休止状態を使用するためにテーブルを修正し始めるとは思わない。

代わりに、オブジェクト全体をキーとして使用できる休止状態で実行可能な構造にオブジェクトを分割できます。 (当然のことながら、これは、行が一意であることを前提としています。)

分割thusly 2にFooのオブジェクトは:

@Entity 
@Table(name = "FOO") 
class Foo { 

    @Id 
    private FooKey id; 

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

    public void getId() { 
    return id; 
    } 
} 

@Embeddable 
class FooKey implements Serializable { 
    private String bar; 
    private String bat; 

    @Column(name = "bar") 
    public String getBar() { 
    return bar;  
    } 

    public void setBar(String bar) { 
    this.bar = bar;  
    } 

    @Column(name = "bat") 
    public String getBat() { 
    return bat;  
    } 

    public void setBat(String bat) { 
    this.bat = bat;  
    } 

}

..それがあるべきですそれ。 Hibernateはその必要なアイデンティティのための組み込みのキーを使用すると、あなたは通常どおり電話をかけることができます。

Query fooQuery = getSession().createQuery("from Foo"); 

希望は、これは、この作業を取得して最初のタイマーを助けます。

+16

私はちょうどこの問題があったので、コンポジットキーに使用しているカラムのいずれかがNULLの場合は、Hibernateがnullオブジェクトを返すよりも、私はViewからすべてを引っ張っていましたが、列の1つがすべてnullだったので、休止状態は正しい数の項目を含むリストを返していましたが、すべての項目がnullでした。私の場合はフィールドを変更できませんでしたので、キーから削除しました。 – Casey

3

@Idまたは主キーとして別のクラスを作成する必要はありません。ちょうど整数(または何でも)を使用してください。また、偽のキーを公開しないでください。偽のキーを使用している開発者は、それが実際のものだと思うかもしれないし、そうでなければそれを使用しようとします。最後に、これはVIEWで最もよく使用されます。私は以前の投稿に同意します。すべてのケースではなくても、ほとんどの場合、テーブルには主キーが必要です。例:

@Entity 
@Table(name = "FOO") 
class Foo { 

    @SuppressWarnings("unused") 
    @Id 
    private Integer id; 

    @Column(name = "REAL_COLUMN") 
    private String realColumn; 

    public String getRealColumn() { 
    return realColumn;  
    } 

    public void setRealColumn(String realColumn) { 
    this.realColumn= realColumn;  
    } 


} 
+3

これは動作しません。これを追加した後、いくつかの列が見つかりませんでした。 – Jeremy

+0

これは動作します。あなたはビューでそれを行う必要があります。もちろん、メンバーをデータベースの列に変更してください。 「realColumn」を使用した場合、もちろん動作しません。私は実際のシステムでこのアプローチを使用しました。 –

+3

org.hibernate.HibernateExceptionの取得:ビューでこれを使用しようとすると、View_Blablaの列が見つからない – StefanTo

37

次のコードを使用してください。日食で既存のリバースエンジニアリングの方法を使用する - Hibernateはすべての問題がテーブルからPOJOを作成するには、このアプローチ

@Entity @IdClass(Foo.class) 
class Foo implements Serializable { 
    @Id private String bar; 
    @Id private String bat; 

    public String getBar() { 
    return bar;  
    } 

    public void setBar(String bar) { 
    this.bar = bar; 
    } 


    public String getBat() { 
    return bat;  
    } 

    public void setBat(String bat) { 
    this.bat = bat;  
    } 
} 
+2

これは最良の答えです。それは、2つの別々のクラスを行うことなく、それ自身をIDクラスとして使用します。彼らが必要なColumnマッピングを持っていたので、Idアノテーションをゲッタに移しました。完璧に動作していて、キャッシュを中断しません。 +1 –

+1

@JohnStrickler:このアプローチの欠点はありますか?それはハックのように見える –

+0

これまで私は誰も見つけ出していない。一意のプロパティに注釈を付ける必要があります(一意でない場合はすべてのプロパティが可能です)。私はそれをハックとして分類しないでしょう - JPAアノテーションを使用する意味で使用しています。 –

1

であるかどうか、私に教えてください重複レコード

を区別するための独自のロジックを持っていません。 非主キー・テーブルの場合、eclipseは2つのPojoクラスを生成します。

eclipse generated class and hbm.xml - 
--- 
Foo.java 
// 

public class Foo implements java.io.Serializable { 

    private FooId id; 

    public Foo() { 
    } 

    public Foo(FooId id) { 
     this.id = id; 
    } 

    public FooId getId() { 
     return this.id; 
    } 

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

} 
--- 
FooId.java 
// 

public class FooId implements java.io.Serializable { 

    private String bar; 
    private String bat; 

    public FooId() { 
    } 

    public FooId(String bar, String bat) { 
     this.bar = bar; 
     this.bat = bat; 
    } 

    public String getBar() { 
     return this.bar; 
    } 

    public void setBar(String bar) { 
     this.bar = bar; 
    } 

    public String getBat() { 
     return this.bat; 
    } 

    public void setBat(String bat) { 
     this.bat = bat; 
    } 

    public boolean equals(Object other) { 
     if ((this == other)) 
      return true; 
     if ((other == null)) 
      return false; 
     if (!(other instanceof FooId)) 
      return false; 
     FooId castOther = (FooId) other; 

     return ((this.getBar() == castOther.getBar()) || (this.getBar() != null 
       && castOther.getBar() != null && this.getBar().equals(
       castOther.getBar()))) 
       && ((this.getBat() == castOther.getBat()) || (this.getBat() != null 
         && castOther.getBat() != null && this.getBat().equals(
         castOther.getBat()))); 
    } 

    public int hashCode() { 
     int result = 17; 

     result = 37 * result 
       + (getBar() == null ? 0 : this.getBar().hashCode()); 
     result = 37 * result 
       + (getBat() == null ? 0 : this.getBat().hashCode()); 
     return result; 
    } 

} 
--- 
Foo.hbm.xml 

<hibernate-mapping> 
    <class name="com.Foo" table="foo" schema="public" catalog="hibernate_poc"> 
     <composite-id name="id" class="com.FooId"> 
      <key-property name="bar" type="string"> 
       <column name="bar" length="20" /> 
      </key-property> 
      <key-property name="bat" type="string"> 
       <column name="bat" length="20" /> 
      </key-property> 
     </composite-id> 
    </class> 
</hibernate-mapping> 

--- 
entry in the Hibernate.cfg.xml - 

<mapping class="com.poc.Foo" resource="Foo.hbm.xml"/> 

--- 
Fetch the Data from table - 
FooDataFetch.java 
// 

import java.util.List; 

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

public class FooDataFetch { 
     private static Session session = null; 

    public static void main(String[] args) { 
      try{    
      Configuration cfg = new Configuration(); 
      cfg.configure("/hibernate.cfg.xml"); 
      SessionFactory sf = cfg.buildSessionFactory(); 
      session = sf.openSession(); 

      session.beginTransaction(); 
       queryPerson(session); 
      session.close(); 

      }catch (Throwable ex) { 
      System.err.println("Failed to create sessionFactory object." + ex); 
      ex.printStackTrace(); 
      throw new ExceptionInInitializerError(ex); 
      }  
     }  

     private static void queryPerson(Session session) { 
      Query query = session.createQuery("from Foo");     
      List <Foo>list = query.list(); 
      java.util.Iterator<Foo> iter = list.iterator(); 
      while (iter.hasNext()) { 
       Foo foo = iter.next(); 
       System.out.println("Foo Details: \"" + foo.getId().getBar() +"\", " + foo.getId().getBat()); 
      } 
     }  
} 
1

Awiedのコメントに追加します。 バーを検索する場合は、次のHQLを使用します。

<id column="ROWID" type="string" /> 
6

私はこのトリックが働くことがわかりました。これはOracle DB上で動作します。他のDBにも同様のものがあるかもしれません。

  1. あなたはPOJOクラスの新しい主キーを作成する必要があります

    @Id @Column(名前= "ID") プライベート整数IDを;

この

getEntityManager().createNativeQuery("select rownum as id, ..... 

ようcreateNativeQueryを使用するには、ネイティブクエリは、主キーが生成され、あなたはユニークな結果を得ることができます。

+0

あなたはとても激しく揺れます!それは完璧な解決策でした! –

+0

ここで、最初のhbm.xmlファイルの上記のコード –

+0

を最初のキーの定義のように維持する必要があります。 – RudiDudi

0

私は値と主キーのないテーブルのためのソリューションとはnullを発見した:

Query fooQuery = getSession().createQuery("from Foo.id.bar = '<barName>'"); 
関連する問題