Usar el ejecutor por lotes es la forma recomendada, pero debe hacerlo correctamente.
Dos problemas que noté.
- Es importante establecer un tamaño de lote adecuado. La respuesta vinculada envía todos los datos al final, lo que no es muy eficiente.
- Usando
${}
hacer referencia a los parámetros hace que cada declaración sea única y evita que el controlador reutilice la declaración (básicamente, se pierde el beneficio del ejecutor por lotes). Consulte estas preguntas frecuentes por la diferencia entre#{}
y${}
.
Aquí hay una operación por lotes típica usando MyBatis.
Como el mejor batchSize
depende de varios factores, debe medir el rendimiento utilizando los datos reales.
int batchSize = 1000;
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
YourMapper mapper = sqlSession.getMapper(YourMapper.class);
int size = list.size();
for (int i = 0; i < size;) {
mapper.update(list.get(i));
i++;
if (i % batchSize == 0 || i == size) {
sqlSession.flushStatements();
sqlSession.clearCache();
}
}
sqlSession.commit();
}
Y aquí hay una versión eficiente de la declaración de actualización.
<update id="update">
UPDATE <include refid="tableName" />
SET
item_price = #{item.price},
update_time = #{item.updateTime}
WHERE id = #{item.id}
</update>