update statement preparedstatement prepared executeupdate executebatch example batchupdate batch addbatch java sql oracle mybatis

java - statement - MyBatis Batch Insert/Update para Oracle



mybatis select example (2)

Recientemente empecé a aprender a usar myBatis. Ahora me enfrento a un escenario de este tipo, necesito buscar constantemente una nueva lista de Objetos a través del Servicio Web, luego, para esta lista, debo insertar / actualizar cada objeto en la tabla de Oracle DB a través de MyBatis.

La parte difícil es que no puedo simplemente hacer una inserción por lotes cada vez, porque algunos de los objetos ya pueden existir en DB, para estos registros, necesito actualizar los campos de ellos en lugar de una nueva inserción.

Mi solución actual puede ser muy estúpida, al usar Java, compilar la lista de Objetos desde el servicio web, recorrer cada uno de ellos, hacer una selección de myBatis, si no es un nulo (ya existe en la base de datos), luego hacer una actualización de myBatis; de lo contrario, haga una inserción myBatis para este nuevo objeto.

La función se logra. Pero mi líder técnico dice que es muy poco eficiente, ya que hacer un bucle for usando Java e insertar / actualizar uno por uno consumirá una gran cantidad de recursos del sistema. Me aconsejó que hiciera la inserción por lotes usando myBatis al pasar una lista de objetos.

Sin embargo, la inserción de lotes en myBatis es sencilla, ya que no estoy puramente insertando (para los registros existentes que necesito actualizar), no creo que la inserción de lotes sea apropiada aquí. Busqué en Google por un tiempo para esto, y me di cuenta de que quizás deba usar "fusionar" en lugar de "insertar" (para Oracle).

Los ejemplos que busqué en Google para combinar en myBatis son solo para un objeto, no para un lote. ¿Por lo tanto, quiero saber si los expertos podrían ofrecerme algunos ejemplos sobre cómo hacer una combinación de lotes en MyBatis (la forma correcta de escribir un asignador)?


En mi caso también hay el mismo escenario. Usé el bucle para verificar si este registro existe en la base de datos o no, y luego, de acuerdo con eso, agregué este objeto a dos listas de arrays para insertar o actualizar. Y luego usé el lote para insertar y actualizar después del bucle para que aparezca en la lista.

aqui esta el ex para actualizar de acuerdo a diferentes condiciones donde

1] esto es para actualizar

<foreach collection="attendingUsrList" item="model" separator=";"> UPDATE parties SET attending_user_count = #{model.attending_count} WHERE fb_party_id = #{model.eid} </foreach>

2] esto es para insertar

<insert id="insertAccountabilityUsers" parameterType="AccountabilityUsersModel" useGeneratedKeys="false"> INSERT INTO accountability_users ( accountability_user_id, accountability_id, to_username, record_status, created_by, created_at, updated_by, updated_at ) VALUES <foreach collection="usersList" item="model" separator=","> ( #{model.accountabilityUserId}, #{model.accountabilityId}, #{model.toUsername}, ''A'', #{model.createdBy}, #{model.createdAt}, #{model.updatedBy}, #{model.updatedAt} ) </foreach> </insert>

En el método dao declara como

void insertAccountabilityUsers(@Param("usersList") List<AccountabilityUsersModel> usersList);

Actualizar

Aquí está mi código de sesión por lotes

public static synchronized SqlSession getSqlBatchSession() { ConnectionBuilderAction connection = new ConnectionBuilderAction(); sf = connection.getConnection(); SqlSession session = sf.openSession(ExecutorType.BATCH); return session; } SqlSession session = ConnectionBuilderAction.getSqlSession();

De hecho ya he dado el ejemplo completo aquí para esta pregunta.


La respuesta aceptada no es la forma recomendada de manejar las operaciones por lotes. No muestra las verdaderas instrucciones por lotes, ya que el modo de ejecutor por lotes debe utilizarse al abrir una sesión. Consulte esta post en la que un colaborador de código recomendó que la forma correcta de actualizar (o insertar) por lotes es abrir una sesión en modo por lotes y llamar repetidamente a la actualización (o insertar) para un solo registro.

Esto es lo que funciona para mí:

public void updateRecords(final List<GisObject> objectsToUpdate) { final SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH); try { final GisObjectMapper mapper = sqlSession.getMapper(GisObjectMapper.class); for (final GisObject gisObject : objectsToUpdate) { mapper.updateRecord(gisObject); } sqlSession.commit(); } finally { sqlSession.close(); } }

No use foreach en su actualización / inserción y asegúrese de que solo actualice / inserte un solo registro. Me encontraba con errores de Oracle sin solución al hacerlo de acuerdo con la respuesta aceptada (carácter no válido, declaración no finalizada, etc.). Como indica la publicación vinculada, la actualización (o inserción) que se muestra en la respuesta aceptada es en realidad solo una declaración de SQL gigante.