AbstractHibernateCurator { protected int bulkSQLUpdate(String table, String column, Map<Object, Object> values, Map<String, Object> criteria) { if (values == null || values.isEmpty()) { return 0; } Iterable<List<Map.Entry<Object, Object>>> blocks = Iterables.partition(values.entrySet(), getCaseBlockSize()); int count = 0; int lastBlock = -1; Session session = this.currentSession(); NativeQuery query = null; for (List<Map.Entry<Object, Object>> block : blocks) { if (block.size() != lastBlock) { int param = 0; boolean whereStarted = false; StringBuilder builder = new StringBuilder("UPDATE ").append(table).append(" SET ") .append(column).append(" = "); if (block.size() > 1) { builder.append("CASE"); for (int i = 0; i < block.size(); ++i) { builder.append(" WHEN ").append(column).append(" = :param").append(++param) .append(" THEN :param").append(++param); } builder.append(" ELSE ").append(column).append(" END "); } else { builder.append(":param").append(++param).append(" WHERE ").append(column) .append(" = :param").append(++param).append(' '); whereStarted = true; } if (criteria != null && !criteria.isEmpty()) { for (Map.Entry<String, Object> criterion : criteria.entrySet()) { if (criterion.getValue() instanceof Collection) { if (((Collection) criterion.getValue()).size() > 0) { int inBlocks = (int) Math.ceil((((Collection) criterion.getValue()).size() / (float) getInBlockSize())); builder.append(whereStarted ? " AND " : " WHERE "); whereStarted = true; if (inBlocks > 1) { builder.append('('); for (int i = 0; i < inBlocks; ++i) { if (i != 0) { builder.append(" OR "); } builder.append(criterion.getKey()).append(" IN (:param") .append(++param).append(')'); } builder.append(')'); } else { builder.append(criterion.getKey()).append(" IN (:param").append(++param) .append(')'); } } } else { builder.append(whereStarted ? " AND " : " WHERE "); whereStarted = true; builder.append(criterion.getKey()).append(" = :param").append(++param); } } } query = session.createNativeQuery(builder.toString()); } int param = 0; if (block.size() > 1) { for (Map.Entry<Object, Object> entry : block) { query.setParameter("param" + String.valueOf(++param), entry.getKey()) .setParameter("param" + String.valueOf(++param), entry.getValue()); } } else { Map.Entry<Object, Object> entry = block.get(0); query.setParameter("param" + String.valueOf(++param), entry.getValue()) .setParameter("param" + String.valueOf(++param), entry.getKey()); } if (block.size() != lastBlock && criteria != null && !criteria.isEmpty()) { for (Object criterion : criteria.values()) { if (criterion instanceof Collection) { Iterable<List> inBlocks = this.partition((Collection) criterion); for (List inBlock : inBlocks) { query.setParameterList("param" + String.valueOf(++param), inBlock); } } else { query.setParameter("param" + String.valueOf(++param), criterion); } } } int blockUpdates = query.executeUpdate(); if (count == 0) { count = blockUpdates; } lastBlock = block.size(); } return count; } AbstractHibernateCurator(Class<E> entityType); Class<E> entityType(); int getInBlockSize(); int getCaseBlockSize(); int getBatchBlockSize(); int getQueryParameterLimit(); E getSingleResult(TypedQuery<E> query); void enableFilter(String filterName, String parameterName, Object value); void enableFilterList(String filterName, String parameterName, Collection value); @Transactional E secureGet(Serializable id); @Transactional E get(Serializable id); @Transactional boolean exists(Serializable id); String getPrimaryKeyName(); @Transactional E create(E entity); @Transactional E create(E entity, boolean flush); CandlepinQuery<E> listAll(); CandlepinQuery<E> listAllByIds(Collection<? extends Serializable> ids); @SuppressWarnings("unchecked") @Transactional Page<List<E>> listAll(PageRequest pageRequest, boolean postFilter); @SuppressWarnings("unchecked") @Transactional Page<List<E>> listAll(PageRequest pageRequest); @SuppressWarnings("unchecked") Page<ResultIterator<E>> paginateResults(CandlepinQuery<E> query, PageRequest pageRequest); @SuppressWarnings("unchecked") @Transactional List<E> listByCriteria(Criteria query); @Transactional List<E> listByCriteria(CriteriaQuery<E> query); @SuppressWarnings("unchecked") @Transactional Page<List<E>> listByCriteria(Criteria query, PageRequest pageRequest, boolean postFilter); @SuppressWarnings("unchecked") @Transactional Page<List<E>> listByCriteria(Criteria c, PageRequest pageRequest); @Transactional Page<List<E>> listByCriteria(Root<E> root, CriteriaQuery<E> criteria, PageRequest pageRequest,
        int maxRecords); @Transactional void delete(E entity); @Transactional void bulkDelete(Collection<E> entities); void detach(E entity); void batchDetach(Collection<E> entities); @Transactional void bulkDeleteTransactional(Collection<E> entities); @Transactional E merge(E entity); @Transactional E saveOrUpdate(E entity); void flush(); void clear(); Session currentSession(); Session openSession(); EntityManager getEntityManager(); EntityTransaction getTransaction(); org.candlepin.util.Transactional<O> transactional(
        org.candlepin.util.Transactional.Action<O> action); @Transactional Collection<E> saveAll(Collection<E> entities, boolean flush, boolean evict); Collection<E> updateAll(Collection<E> entities, boolean flush, boolean evict); Iterable<E> saveOrUpdateAll(Iterable<E> entities, boolean flush, boolean evict); Collection<E> mergeAll(Collection<E> entities, boolean flush); void refresh(Iterable<E> entities); void refresh(E... entities); E evict(E entity); void evictAll(Iterable<E> collection); List<E> takeSubList(PageRequest pageRequest, List<E> results); Collection<E> lock(Iterable<E> entities); Collection<E> lock(E... entities); E lock(E entity); E lock(E entity, LockModeType lockMode); E lockAndLoad(Serializable id); Collection<E> lockAndLoad(Iterable<? extends Serializable> ids);  }
@Test public void testBulkSQLUpdate() throws Exception { Cdn c1 = this.createCdn("c1", "http: Cdn c2 = this.createCdn("c2", "http: Cdn c3 = this.createCdn("c3", "http: Map<Object, Object> values = new HashMap<>(); values.put("c1", "c1updated"); values.put("c2", "c2updated"); values.put("content ?", "should not exist"); int result = this.cdnCurator.bulkSQLUpdate(Cdn.DB_TABLE, "name", values, null); assertEquals(3, result); this.getEntityManager().refresh(c1); this.getEntityManager().refresh(c2); this.getEntityManager().refresh(c3); assertEquals("c1updated", c1.getName()); assertEquals("c2updated", c2.getName()); assertEquals("c3", c3.getName()); }