2

私はEJB、JPAを学んでいて、非常に基本的な疑問があります

私は3つのテーブルA、B、Cを持っています

A - ID、名前

B - ID、名前

C - ID、A_ID、B_ID

データベースからエンティティ クラスを作成すると、JPA を含む 3 つの EJB クラスが取得されます。

マネージド Bean で A.Name または B.Name を取得し、C を使用して一致するエントリを見つける必要があります。

通常の SQL クエリは次のようになります (最適なクエリではない可能性があります)

SELECT a.name FROM schema.A a, schema.B b, schema.C c where b.Name='ABC' and c.B_ID=b.ID and a.ID = c.A_ID;

さて、クラスのどこで上記のクエリを実行しますか。

@SecondaryTable に出くわしましたが、その使用方法を正確に理解できませんでした。

em.createQuery( SQL query).getResultList() も見ました。

上記が最善の方法です。または、EJB/JPA で利用できるより優れた方法があります。

更新 1:

em.CreateQuery でクエリを実行しようとしていました

em.CreateQuery(SELECT a.name FROM A a, B b, C c where b.Name='ABC' and c.B_ID=b.ID and a.ID = c.A_ID).getResultList();

しかし、GlassFishサーバーで次のエラーが発生します(EclipeLink JPAを使用しています)

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
  Position: 
Error Code: 0
Call: SELECT t0.given_name FROM test.a t3, test.a_b t2, test.b t1, test.a t0 WHERE ((((t1.Name = ?) AND (t2.b_id = t1.id.t1.id)) AND (t0.id = )) AND (t3.id = t2.a_id))
bind => [1 parameter bound]
Query: ReportQuery(referenceClass=Consultant sql="SELECT t0.given_name FROM test.a t3, test.a_b t2, test.b t1, test.a t0 WHERE ((((t1.Name = ?) AND (t2.b_id = t1.id.t1.id)) AND (t0.id = )) AND (t3.id = t2.a_id))")

SQL ステートメントがエラー ログでめちゃくちゃになっているのはなぜですか

1.追加のエントリーテストがあります.a t0

2.t2.b_id = t1.id.t1.id

3.t0.id=

エラー ログの SQL ステートメントはどのように生成されますか。

4

1 に答える 1

1

C は A と B の間の多対多の関係であるため、エンティティであってはなりません。ただし、結合テーブル(C)に独自のID列があることをJPAが気に入っているとは思いません。可能であれば、C から ID 列を削除し、A_ID と B_ID の組み合わせを主キーにします。

次に、エンティティ クラス A は次のようになります。

@JoinTable(name = "C",
    joinColumns = { @JoinColumn(name = "A_ID", referencedColumnName = "ID") },
    inverseJoinColumns = { @JoinColumn(name = "B_ID", referencedColumnName = "ID") })
@ManyToMany
private Collection<B> bCollection;

これらすべての注釈が何を意味するかは明らかだと思います。クラス B は次のようになります。

@ManyToMany(mappedBy = "bCollection") 
private Collection<A> aCollection;

MappedBy 属性は、A::bCollection の JoinTable 定義を使用するよう JPA に指示します (A は、フィールドの型 Collection<A> から推定されます)。

A のインスタンスがある場合、プロパティを取得することで、その A のすべての B を簡単に取得できます。SQL/JPQL は必要ありません。

クエリの実行に関しては、JPQL と SQL があることを知っておく必要があります。JPQL は Java Persistence Query Language であり、JPA の言語です。SQL はデータベースのネイティブ言語です。SQL を実行するには、関数の createNativeQuery ファミリーを使用する必要があります。createQuery 関数は JPQL 用です。

SQL よりも JPQL を優先する必要があります。この 2 つの最も重要な違いは、JPQL がエンティティに対して機能し、すべての識別子がクラスとプロパティに使用される名前に対応していることを期待することです。たとえば、Name 列 (最初の文字は大文字) が name (小文字) というプロパティにマップされている場合、JPQL クエリでは name (小文字) を使用する必要があります。エンティティ クラス名と対応するテーブル名についても同様です。JPQLには、多対多のリレーションシップの結合テーブルのサポートも組み込まれています.JPQLクエリは、あなたが望むものになるでしょう

SELECT a
FROM B b JOIN b.aCollection a
WHERE b.name='ABC'

すべての結合条件を指定する必要はありません。JPA はクラスのアノテーションからそれらを認識します。

@SecondaryTable はここでは関係ありません。単一のエンティティが複数のテーブルに分割されている場合に使用されます。

于 2012-08-19T06:23:56.687 に答える