2015-11-19 3 views
9

のは、私は次の2つの表があるとしましょう:JPQLの結合用にマップされた列のみをどのように参照しますか?

@Entity public class Foo { 
    @Id private int id; 
    @ManyToOne() 
    @JoinColumn(name = "bar_id") 
    private Bar bar; 
} 
@Entity public class Bar { 
    @Id private int id; 
    private Boolean flag; 
} 

そして私はFoo IDのコレクションに基づいていくつかのBar.flag値を変更JPQLクエリを書きたいです。

これはプレーンなSQLだったら、私はこのような何か書きたい:bar_id列は、エンティティのプロパティにマッピングされていないので、あなたは、しかし、JPQLにこれを翻訳することはできません

UPDATE Bar SET flag = true WHERE id IN (SELECT bar_id from FOO where id = 3); 

を。 bar_idとして

が直接Fooエンティティにマッピングされていない、はどのように私はJPQLで、クエリのこの種を達成することができますか?

+0

コレクションはどこですか? –

+0

これはこれに対応していませんか? http://stackoverflow.com/questions/3629259/how-do-i-do-a-jpql-subquery –

+0

@sashok_bg私はそれを試していないが、私はそれがないと思うエンティティにマッピングされた生の外部キー(例では 'p.country_id') – SCdF

答えて

3

あなたが働いて一括更新クエリをしたい場合は、次のように動作するはずです:

UPDATE Bar b SET flag = true WHERE b IN (SELECT f.bar from FOO f where id = 3);

アイデアは、あなたが副選択を行うとき、エンティティで動作するようです。

0

bar_idに直接アクセスすることはできません。 idの情報をBarエンティティから使用するには、FooBarの間の「余分な」結合を行う必要があります。 JPAの主要な機能の

UPDATE Bar bar SET bar.flag = true 
WHERE bar.id IN 
    (SELECT barFoo.id from FOO foo 
    JOIN foo.bar barFoo 
    WHERE foo.id = 3); 
2

一つをJavaコードから(外部キーのような)核心ザラザラデータベースの詳細を抽象化されています

だから、あなたのJPQLクエリは次のようになります。バルクで

@Transactional 
public void updateBarFlagForFoo(final int fooId, final boolean newFlagValue) { 
    final Foo foo = em.find(Foo.class, fooId); 
    foo.getBar().setFlag(newFlagValue); 
} 

または、::このような更新は、同じ以内に取得した任意のエンティティを変更しないことを

@Transactional 
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) { 
    final Query query = em.createQuery(
     "update Bar b set flag = :newFlagValue where b.id in " + 
      "(select f.bar.id from Foo f where f.id in (:fooIds))"); 
    query.setParameter("newFlagValue", newFlagValue); 
    query.setParameter("fooIds", fooIds); 
    query.executeUpdate(); 
} 

注意あなたが概説されているクエリを達成するための複数の方法がありますが、ここではカップルですトランザクション。 Doing

final Foo foo = em.find(Foo.class, 1); 
updateFlags(Arrays.asList(1), true); 

実際のFooオブジェクトは変更されません。あなたはもちろんbar_idをマップ@Columnを作成することもできますが、それは一種のの目的に反して、私は、このことをお勧めしません

@Transactional 
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) { 
    final List<Bar> bars = findBarsForFooIds(fooIds); 
    for (final Bar bar : bars) { 
     bar.setFlag(newFlagValue); 
    } 
} 

private List<Bar> findBarsForFooIds(final List<Integer> fooIds) { 
    final TypedQuery<Bar> q = 
      em.createQuery("select distinct b from Foo f join f.bar b where f.id in (:fooIds)", 
          Bar.class); 
    q.setParameter("fooIds", fooIds); 
    return q.getResultList(); 
} 

:これを行うの

私の好ましい方法は、このようなものになるだろうJPA

関連する問題