複数列 ID を持つエンティティの場合、DB にまだ存在していない特定のリスト内のすべてのオブジェクトを永続化する必要があります。チェックするオブジェクトの数が多く、ストレージ内のオブジェクトの数が非常に多くなる可能性があるため、複数列の秘密鍵と "WHERE ... IN (. ..)" 条件 API を使用して構築された type ステートメントであり、永続化する前にリストから削除できます。
これを試みるコードは次のとおりです。
public void persistUnique(List<CdrEntity> cdrs) {
// find all the CDRs in the collection that are already in the DB
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<CdrEntity> query = criteriaBuilder.createQuery(CdrEntity.class);
Root<CdrEntity> cdrRoot = query.from(CdrEntity.class);
query.select(cdrRoot).where(cdrRoot.in(cdrs));
List<CdrEntity> nonUnique = entityManager.createQuery(query).getResultList();
// remove nonUnique elements from crds and persist
...
}
ただし、少なくともEclipseLink 2.4.1を使用すると、これは実際にDBに送信されるものです(読みやすくするために一部の出力は省略されています):
[EL Fine]: sql:...--SELECT SUBINDEX, ... FROM CDRS WHERE ((?, ?, ?, ?) IN ((?, ?, ?, ?), (?, ?, ?, ?), ...))
bind => [null, null, null, null, 2, 1362400759, 19415, 176, ...]
基本的に、主キー列の適切な列名があるべき場所に、いくつかのパラメーターが追加され、後で (値が null で) バインドされます。それとは別に、クエリは問題なく、最初の 4 つの ?s が実際の列名に置き換えられれば、目的の結果で実行されます。
.in(...)
ただし、 a を直接呼び出すとRoot
、望ましい結果が得られないようです。エンティティを直接使用できない場合は、複数の列を表すことができる何らかの種類があり、Expression
それが への呼び出しの受信者になる可能性があると予想され.in(...)
ますが、見つけることができませんでした。
問題は、これを適切に行うにはどうすればよいかということです。または、JPAではまったく不可能ですか?それとも、EclipseLink に単にバグがあるのでしょうか?