Una delle caratteristiche chiave di APP è astraendo i database dettagli essenziali (come chiavi esterne) dal vostro codice Java. Ci sono diversi modi di raggiungere la query che si sta delineando, qui ci sono un paio:
@Transactional
public void updateBarFlagForFoo(final int fooId, final boolean newFlagValue) {
final Foo foo = em.find(Foo.class, fooId);
foo.getBar().setFlag(newFlagValue);
}
o, alla rinfusa:
@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();
}
Si noti che tale aggiornamento non cambierà qualsiasi entità recuperata all'interno della stessa transazione. Fare
final Foo foo = em.find(Foo.class, 1);
updateFlags(Arrays.asList(1), true);
non cambierà l'oggetto Foo effettivo.
Il mio modo preferito di fare questo sarebbe qualcosa di simile:
@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();
}
Si potrebbe comunque creare un @Column
che mappa il bar_id
, ma io non consiglierei questo, come che tipo di sconfitte lo scopo di JPA
.
dov'è la collezione? –
non risponde? http://stackoverflow.com/questions/3629259/how-do-i-do-a-jpql-subquery –
@sashok_bg Non l'ho provato, ma non penso che lo farebbe perché non ho il chiavi esterne grezzi mappate nell'entità ('p.country_id' nel loro esempio) – SCdF