Etiquetas Essenciais em Arquivos de Mapeamento do MyBatis

O MyBatis é uma estrutura de persistência que utiliza arquivos XML para definir o mapeamento entre as consultas SQL e os métodos da interface Java. Estes arquivos, conhecidos como mapeamentos de Mapper, utilizam uma variedade de etiquetas para expressar operações de banco de dados complexas de forma declarativa.

Reutilização e Nomenclatura

Para evitar a duplicação de colunas SQL, a etiqueta <sql> permite definir um fragmento reutilizável. Este fragmento é então inserido em consultas maiores usando a etiqueta <include>, promovendo a manutenibilidade. O atributo id do fragmento é referenciado pelo atributo refid da inclusão.

<sql id="Campos_Departamento">
    id, nome, codigo, gerente_id, data_criacao
</sql>

<select id="buscarDepartamento" resultType="Departamento">
    SELECT <include refid="Campos_Departamento"/> FROM departamento
</select>

A etiqueta raiz <mapper> encapsula todos os mapeamentos e define o namespace, que deve corresponder à interface Java associada.

<mapper namespace="com.mapeamento.DepartamentoMapper">
    ...
</mapper>

Operações CRUD Básicas

As operações fundamentais de banco de dados são representadas por etiquetas específicas.

<!-- SELECT -->
<select id="listarTodos" resultType="com.modelo.Funcionario">
    SELECT matricula, nome, email FROM funcionario
</select>

<!-- INSERT -->
<insert id="adicionarFuncionario" useGeneratedKeys="true" keyProperty="matricula">
    INSERT INTO funcionario (nome, email, departamento_id)
    VALUES (#{nome}, #{email}, #{departamentoId})
</insert>

<!-- UPDATE -->
<update id="atualizarProjeto">
    UPDATE projeto SET nome = #{novoNome}, data_fim = #{novaDataFim} WHERE id = #{idProjeto}
</update>

<!-- DELETE -->
<delete id="excluirRegistroPorId">
    DELETE FROM log_auditoria WHERE id = #{idLog}
</delete>

Para cenários onde o valor gerado pelo banco (como uma chave primária sequencial) precisa ser preenchido no objeto Java após a inserção, a etiqueta <selectKey> é utilizada dentro do <insert>.

<insert id="inserirOrdemServico">
    <selectKey keyProperty="idOrdem" resultType="long" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
    INSERT INTO ordem_servico (descricao, status) VALUES (#{descricao}, #{status})
</insert>

Mapeamento de Resultados Complexos

Para mapear colunas de banco de dados para propriedades de objetos com nomes diferentes, ou para estruturas aninhadas, utiliza-se <resultMap>. A relação de um-para-muitos (ex.: um departamento com vários projetos) é gerida pela etiqueta <collection>.

<resultMap id="MapaDepartamento" type="com.modelo.Departamento">
    <id column="departamento_id" property="id"/>
    <result column="departamento_nome" property="nome"/>
    <collection property="projetos" ofType="com.modelo.Projeto"
        select="buscarProjetosPorDepartamento" column="departamento_id"/>
</resultMap>

<select id="buscarProjetosPorDepartamento" resultType="com.modelo.Projeto">
    SELECT id, titulo, prazo FROM projeto WHERE departamento_id = #{departamento_id}
</select>

SQL Dinâmico

Construir consultas com cláusulas condicionais é facilitado por etiquetas dinâmicas. <if> adiciona uma cláusula se a condição for verdadeira.

<select id="filtrarAtividades" resultType="com.modelo.Atividade">
    SELECT id, titulo, responsavel FROM atividade
    WHERE status = 'PENDENTE'
    <if test="responsavelId != null">
        AND responsavel_id = #{responsavelId}
    </if>
</select>

A etiqueta <where> envolve condições opcionais, automaticamente removendo operadores AND/OR iniciais indesejados.

<select id="buscarComFiltros" resultType="com.modelo.Pedido">
    SELECT * FROM pedido
    <where>
        <if test="dataInicio != null"> AND data_pedido >= #{dataInicio} </if>
        <if test="status != null"> AND status = #{status} </if>
        <if test="valorMinimo != null"> AND valor_total >= #{valorMinimo} </if>
    </where>
</select>

De maneira similar, <set> constrói dinamicamente a lista de colunas para atualizar em um UPDATE, adicionando as vírgulas necessárias.

<update id="atualizarDadosUsuario">
    UPDATE usuario
    <set>
        <if test="nome != null"> nome = #{nome}, </if>
        <if test="email != null"> email = #{email}, </if>
        <if test="telefone != null"> telefone = #{telefone} </if>
    </set>
    WHERE id = #{id}
</update>

Para uma lógica condicional exclusiva (executar apenas a primeira condição verdadeira), a combinação <choose>, <when> e <otherwise> é equivalente a uma estrutura if-else if-else em SQL.

<select id="obterRegraDesconto" resultType="java.math.BigDecimal">
    SELECT desconto FROM regra_comercial
    <where>
        <choose>
            <when test="clienteTipo == 'VIP'"> cliente_tipo = 'VIP' </when>
            <when test="pedidoValor > 1000"> valor_minimo <= #{pedidoValor} </when>
            <otherwise> ativo = true </otherwise>
        </choose>
    </where>
</select>

Finalmente, a etiqueta <foreach> itera sobre uma coleção, sendo extremamente útil para cláusulas IN ou para operações em lote. Seus atributos controlam o item da iteração, o caractere separador e os delimitadores de abertura e fechamento.

<delete id="excluirPorLoteIds">
    DELETE FROM item_estoque WHERE id IN
    <foreach collection="listaIds" item="idItem" open="(" separator="," close=")">
        #{idItem}
    </foreach>
</delete>

Tags: MyBatis Mapper XML SQL Dinâmico Mapeamento Objeto-Relacional Java Persistence

Publicado em 6-14 18:42 por Thomas