MyBatis: Inserção de Dados com Retorno de Chave Primária e Inserção em Lote

No MyBatis, a operação de inserção é geranciada pelo elemento <insert>. Os atributos principais incluem:

  • parameterType: classe ou apelido do parâmetro de entrada.
  • keyColumn: especifica a coluna de chave primária auto-gerada, necessário para bancos de dados como PostgreSQL onde a chave não é o primeiro campo.
  • keyProperty: define a propriedade do modelo de domínio onde o valor da chave gerada será atribuído.
  • useGeneratedKeys: habilita o uso do método JDBC getGeneratedKeys para obter chaves auto-geradas (suportado por MySQL, SQL Server).
  • statementType: tipo de instrução SQL (STATEMENT, PREPARED ou CALLABLE).
  • flushCache: controla se o cache secundário e local deve ser limpo após a operação.
  • timeout: tempo limite para a execução da operação.
  • databaseId: identifica o fabricante do banco de dados para instruções SQL específicas.

Para uma inserção básica que retorna o número de registros afetados, a interface do mapper pode ser definida como:

int inserirAluno(Aluno aluno);

No arquivo XML correspondente:

<insert id="inserirAluno" parameterType="Aluno">
  INSERT INTO alunos(nome, idade) VALUES(#{nome}, #{idade})
</insert>

Para obter a chave primária após a inserção, existem diferentes abordagens dependendo do banco de dados.

Para bancos de dados que spuortam chaves auto-geradas (ex.: MySQL):

<insert id="inserirAluno" parameterType="Aluno" useGeneratedKeys="true" keyProperty="id">
  INSERT INTO alunos(nome, idade) VALUES(#{nome}, #{idade})
</insert>

Alternativamente, usando <selectKey>:

<insert id="inserirAluno" parameterType="Aluno">
  <selectKey resultType="long" keyProperty="id" order="AFTER">
    SELECT @@IDENTITY AS id
  </selectKey>
  INSERT INTO alunos(nome, idade) VALUES(#{nome}, #{idade})
</insert>

Para bancos de dados que não suportam chaves auto-geradas (ex.: Oracle):

<insert id="inserirAluno" parameterType="Aluno">
  <selectKey keyProperty="id" resultType="long" order="BEFORE">
    SELECT CAST(RANDOM() * 100000 AS INTEGER) FROM DUAL
  </selectKey>
  INSERT INTO alunos(id, nome, idade) VALUES(#{id}, #{nome}, #{idade})
</insert>

Nestes casos, o retorno da interface do mapper ainda é o número de registros inseridos, mas a chave primária é atribuída à propriedade id do objeto.

O sub-elemento <selectKey> permite executar uma consulta para obter valores de chave antes ou depois da inserção. Seus atributos incluem:

  • keyProperty: propriedade do modelo onde o resultado será atribuído.
  • resultType: tipo do resultado da consulta.
  • order: determina se a consulta é executada BEFORE ou AFTER a instrução INSERT.
  • statementType: tipo da instrução SQL.

Para inserção em lote, várias técnicas podem ser usadas.

Usando <foreach> para múltiplas inserções individuais:

<insert id="inserirAlunos" parameterType="list">
  <foreach collection="lista" item="aluno" separator=";">
    INSERT INTO alunos(nome, idade) VALUES(#{aluno.nome}, #{aluno.idade})
  </foreach>
</insert>

Este método executa inserções separadas, o que pode não garantir atomicidade e o retorno é apenas o resultado da última inserção.

Abordagem otimizada para SQL Server:

<insert id="inserirAlunos" parameterType="list">
  WITH temporario AS
  <foreach collection="lista" item="aluno" open="(" close=")" separator="UNION ALL">
    SELECT #{aluno.nome} AS nome, #{aluno.idade} AS idade
  </foreach>
  INSERT INTO alunos(nome, idade) SELECT nome, idade FROM temporario
</insert>

Método genérico para inserção em lote:

INSERT INTO alunos(nome, idade)
<foreach collection="lista" item="aluno" open="(" close=")" separator="UNION ALL">
  SELECT #{aluno.nome}, #{aluno.idade} FROM DUAL
</foreach>

Este código funciona em bencos como Oracle, ajustando a cláusula FROM conforme necessário para outros sistemas.

Tags: MyBatis java SQL insert Chave Primária

Publicado em 7-7 04:42