AccessionRefRepositoryCustomImpl.java
package org.genesys.server.persistence;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.genesys.server.model.genesys.AccessionRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.collect.Iterables;
import com.querydsl.jpa.impl.JPAQueryFactory;
public abstract class AccessionRefRepositoryCustomImpl<X, Y extends AccessionRef<X>> implements AccessionRefCustomRepository<X, Y> {
private static final Logger LOG = LoggerFactory.getLogger(AccessionRefRepositoryCustomImpl.class);
private static final Predicate[] EMPTY_PREDICATE_ARRAY = new Predicate[] {};
@Autowired
protected JPAQueryFactory jpaQueryFactory;
@PersistenceContext
protected EntityManager em;
private final Class<Y> targetType;
protected abstract Class<Y> getAccessionRefType();
public AccessionRefRepositoryCustomImpl() {
this.targetType = getAccessionRefType();
}
@Override
public List<Y> findExisting(X list, Iterable<Y> accessionRefs) {
final CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
final AtomicInteger batchCounter = new AtomicInteger(0);
List<Y> results = new ArrayList<>();
Iterables.partition(accessionRefs, 1000).forEach(batch -> {
LOG.info("Batch {} with size {}", batchCounter.incrementAndGet(), batch.size());
CriteriaQuery<Y> cq = criteriaBuilder.createQuery(this.targetType);
Root<Y> root = cq.from(this.targetType);
cq.distinct(true);
// cq.select(root);
// Path<Object> theDoi = root.get("doi");
Path<Object> theList = root.get("list");
Path<Object> theInstCode = root.get("instCode");
Path<Object> theAcceNumb = root.get("acceNumb");
Path<Object> theGenus = root.get("genus");
// A lot of .. (instCode=? and acceNumb=? and genus=?)
List<Predicate> restrictions = new ArrayList<Predicate>();
for (Y ref : batch) {
restrictions.add(criteriaBuilder.and(criteriaBuilder.equal(theInstCode, ref
.getInstCode()), criteriaBuilder.equal(theAcceNumb, ref
.getAcceNumb()), criteriaBuilder.equal(theGenus, ref.getGenus())));
}
cq.where(criteriaBuilder.and(criteriaBuilder.equal(theList, list), criteriaBuilder.or(restrictions.toArray(EMPTY_PREDICATE_ARRAY))));
List<Y> existing = em.createQuery(cq).getResultList();
LOG.debug("Got {} existing records", existing.size());
for (Y aRef : batch) {
int indexOf = existing.indexOf(aRef);
if (indexOf != -1) {
results.add(existing.get(indexOf));
} else {
results.add(aRef);
}
}
});
LOG.info("Done finding {} {} batches", batchCounter.get(), this.targetType.getSimpleName());
return results;
}
}