2015-11-19 14 views
9

en aşağıdaki iki tablo var diyelim:Yalnızca JPQL'deki birleştirme için eşlenen sütunlara nasıl başvurabilirim?

@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; 
} 

Ve Foo kimlikleri bir koleksiyon dayalı bazı Bar.flag değerlerini değiştiren bir JPQL sorgu yazmak istiyorum. bar_id kolon varlığın bir özelliği eşleştirilmiş olmadığından,

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

Bununla birlikte JPQL için bu tercüme edemez: Bu sade SQL olsaydı

böyle bir şey yazmak istiyorum.

bar_idFoo Entity, 'da doğrudan eşleştirilmemiş JPQL'de bu tür sorgulamayı nasıl yapabilirim?

+0

Koleksiyon nerede? –

+0

buna cevap vermiyor mu? http://stackoverflow.com/questions/3629259/how-do-i-do-a-jpql-subquery –

+0

@sashok_bg Denemedim, ama bunun olacağını sanmıyorum çünkü öğede eşlenen ham yabancı anahtarlar (örneklerinde p.country_id) – SCdF

cevap

3

aşağıdaki çalışması gerekir:

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

fikri alt seçim yaparken, varlıklarla çalışmaktır.

0

Doğrudan bar_id'a erişemezsiniz. Bar öğesinden id bilgilerini kullanmak için Foo ve Bar arasında "fazladan" birleştirme yapmanız gerekir. JPA en önemli özelliklerinden

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

One Java kodundan (yabancı tuşları gibi) asıl mesele veritabanı ayrıntıları uzakta abstracting edilir:

Yani, JPQL sorgu böyle olacak. Toplu olarak

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

ya,: Böyle bir güncelleme aynı dahilinde alınan herhangi bir kuruluş değişmeyeceğini

@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(); 
} 

Not özetleyen olan sorguyu ulaşma birden çok yolu vardır, burada bir çift işlem. Gerçek Foo nesnesini değiştirmeyecektir. .

Bunu yapmanın Tercih ettiğim yolu böyle bir şey olurdu:

@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(); 
} 

Elbette bar_id eşleştiren bir @Column oluşturabilir, ama bu tür amacı yendi gibi bu tavsiye etmem JPA. Çalışan bir toplu güncelleme sorgusu istiyorsanız

İlgili konular