Mapowanie JPA <KEY, VALUE> zapytanie JPQL nie powiodło się
Przechowuję mapę w JPA, która przechowuje tłumaczenie słów kluczowych w każdym języku. takie jak jeden sklep z obiektamiLocale.ENGLISH -> "Father" , Locale.CHINESE -> "PaPa"
. I kolejny sklep z przedmiotamiLocale.ENGLISH -> "Mother" , Locale.CHINESE -> "MaMa"
;
Oto mój działający projekt:
public class Relation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ElementCollection
@MapKeyColumn(name="locale")
@Column(name="value")
@CollectionTable(name = "RelationName", joinColumns = @JoinColumn(name = "relation_id"))
private Map<Locale, String> langMap = new HashMap<>();
// other fields skipped
}
Działa dobrze, mogę przechowywać wiele tłumaczeń słów kluczowych w DB. Ale gdy zapytanie z JPQL ma pewne problemy:
Na przykład chcę dowiedzieć się, która relacja ma klucz angielski z wartością „Ojciec”:
To jest mój kod:
Relation r = em.createQuery("select r from Relation r join r.langMap m where ( KEY(m) = :locale and VALUE(m) = :value ) " , Relation.class)
.setParameter("locale" , locale)
.setParameter("value" , value)
.getSingleResult();
Generuje ten dziwny / nie działający SQL:
Hibernate:
select
relation0_.id as id1_18_
from
Relation relation0_
inner join
RelationName langmap1_
on relation0_.id=langmap1_.relation_id
where
langmap1_.locale=?
and (
select
langmap1_.value
from
RelationName langmap1_
where
relation0_.id=langmap1_.relation_id
)=?
00:16:12.038 WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1242, SQLState: 21000
00:16:12.038 ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Subquery returns more than 1 row
Nie wiem, dlaczego generuje to dziwne podzapytanie.
Mogę rozwiązać ten problem według kryteriów:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Relation> criteria = builder.createQuery(Relation.class);
Root<Relation> root = criteria.from(Relation.class);
criteria.select(root);
MapJoin<Relation , Locale , String> mapJoin = root.joinMap("langMap");
criteria.where(builder.and(
builder.equal(mapJoin.key(), locale) ,
builder.equal(mapJoin.value() , value))
);
return em.createQuery(criteria).getSingleResult();
Generuje poprawny SQL (where langmap1_.locale=? and langmap1_.value=?
) i działa dobrze.
Ale czuję, że kryteria są zbyt skomplikowane. I zastanawiam się, dlaczego JPQL nie powiódł się? Jak poprawić JPQL?
Dzięki.
Env:
JPA2, Hibernate 4.2.3, dialekt MySQL