A organização eficiente de um projeto MyBatis é fundamental para garantir a escalabilidade e facilitar a manutenção do código. Ao separar as configurações de banco de dados, os mapeamentos SQL e as classes Java, criamos um ambiente de desenvolvimento mais limpo e profissional.
Organização de Recursos e Configuração
Dentro do diretório src/main/resources, é recomendável agrupar os arquivos relacionados ao MyBatis em uma subpasta dedicada. Isso evita que as configurações se misturem com outros componentes do sistema. Dividimos a configuração em duas partes principais:
- Configuração Global (mybatis-config.xml): Define o ambiente, o gerenciamento de transações, o pool de conexões e os caminhos dos arquivos de mapeamento.
- Arquivos de Mapeamento (Mappers): Contêm as instruções SQL específicas da aplicação.
Veja um exemplo de como estruturar o mybatis-config.xml dentro de resources/mybatis/config/:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db_exemplo?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="usuario_app"/>
<property name="password" value="senha_segura"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis/mapper/UsuarioMapper.xml"/>
</mappers>
</configuration>
O arquivo de mapeamento SQL (UsuarioMapper.xml) define a relação entre os comandos do banco de dados e os métodos Java. O namespace deve corresponder exatamente ao pacote e nome da interface do Mapper correspondente.
<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="br.com.projeto.mapper.UsuarioMapper">
<select id="listarTodos" resultType="br.com.projeto.model.Usuario">
SELECT * FROM usuarios
</select>
<select id="buscarPorId" resultType="br.com.projeto.model.Usuario">
SELECT * FROM usuarios WHERE id_usuario = #{id}
</select>
</mapper>
Estrutura de Classes Java
Para interagir com o MyBatis de forma tipada, utilizamos dois componentes principais no código Java:
1. O Modelo de Dados (POJO)
Representa a entidade do banco de dados. É uma classe simples com atributos privados e métodos de acesso.
package br.com.projeto.model;
public class Usuario {
private int idUsuario;
public int getIdUsuario() {
return idUsuario;
}
public void setIdUsuario(int idUsuario) {
this.idUsuario = idUsuario;
}
}
2. A Interface Mapper
Esta interface atua como a ponte entre o Java e o XML. O MyBatis gera dinamicamente a implementação desta interface em tempo de execução.
package br.com.projeto.mapper;
import br.com.projeto.model.Usuario;
import java.util.List;
public interface UsuarioMapper {
List<Usuario> buscarPorId(int id);
List<Usuario> listarTodos();
}
Implementação de Testes Unitários
A melhor forma de validar a persistência é através de testes integrados. Utilizadno o JUnit, podemos configurar um ambiente que inicializa o SqlSessionFactory e executa operações de teste. Em vez de chamar os métodos via strings, utilizamos o método getMapper, que é mais seguro e fácil de refatorar.
package br.com.projeto;
import br.com.projeto.mapper.UsuarioMapper;
import br.com.projeto.model.Usuario;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UsuarioPersistenceTest {
private static SqlSessionFactory sessionFactory;
@BeforeAll
static void setup() throws IOException {
InputStream config = Resources.getResourceAsStream("mybatis/config/mybatis-config.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(config);
}
@Test
void deveBuscarUsuarioPorId() {
try (SqlSession session = sessionFactory.openSession()) {
UsuarioMapper mapper = session.getMapper(UsuarioMapper.class);
List<Usuario> resultado = mapper.buscarPorId(10);
if (resultado != null) {
resultado.forEach(u -> System.out.println("ID Localizado: " + u.getIdUsuario()));
}
}
}
@Test
void deveListarTodosUsuarios() {
try (SqlSession session = sessionFactory.openSession()) {
List<Usuario> usuarios = session.selectList("br.com.projeto.mapper.UsuarioMapper.listarTodos");
usuarios.forEach(u -> System.out.println("Usuário: " + u.getIdUsuario()));
}
}
}
Essa estrutura modularizada permite que o projeto cresça de forma organizada. A separação clara entre a lógica de negócio (Java) e a lógica de persistência (XML/SQL) facilita a depuração e a colaboração em equipe.