Embora a configuração tradicional do MyBatis utilize arquivos XML para mapear instruções SQL, o Spring Boot permite uma abordagem muito mais enxuta baseada inteiramente em anotações Java. Esta técnica elimina a necessidade de arquivos de configuração externos para o mapeamento de consultas, facilitando a manutenção e a legibilidade do código em projetos menores ou microserviços.
Dependências Necessárias
Para começar, é necessário incluir o mybatis-spring-boot-starter e o driver do banco de dados no seu arquivo pom.xml. Esta dependência gerencia automaticamente a configuração do SqlSessionFactory e do SqlSessionTemplate.
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
Configuração do Datasource
No arquivo application.yml, defina os parâmetros de conexão com o seu banco de dados MySQL:
spring:
datasource:
url: jdbc:mysql://localhost:3306/sistema_financeiro?useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: dev_user
password: senha_forte
Estrutura do Banco de Dados
Para este exemplo, utilizaremos uma tabela chamada user_account para gerenciar o saldo de usuários:
CREATE TABLE `user_account` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`owner_name` VARCHAR(50) NOT NULL DEFAULT '',
`balance` BIGINT NOT NULL DEFAULT '0',
`status` TINYINT(1) NOT NULL DEFAULT '1',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Modelo de Dados (Antity)
Crie uma classe Java que represente a estrutura da tabela. Utilizaremos tipos padrão do Java para o mapeamento:
public class UserAccount {
private Integer id;
private String ownerName;
private Long balance;
private Integer status;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
// Getters e Setters
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getOwnerName() { return ownerName; }
public void setOwnerName(String ownerName) { this.ownerName = ownerName; }
public Long getBalance() { return balance; }
public void setBalance(Long balance) { this.balance = balance; }
public Integer getStatus() { return status; }
public void setStatus(Integer status) { this.status = status; }
// ... demais métodos
}
Definição do Mapper com Anotações
A interface Mapper é onde definimos as operações CRUD. Em vez de XML, usamos anotações como @Insert, @Select, @Update e @Delete.
@Mapper
public interface UserAccountMapper {
@Insert("INSERT INTO user_account (owner_name, balance, status) VALUES (#{acc.ownerName}, #{acc.balance}, #{acc.status})")
@Options(useGeneratedKeys = true, keyProperty = "acc.id", keyColumn = "id")
int insertAccount(@Param("acc") UserAccount account);
@Select("SELECT * FROM user_account WHERE owner_name = #{name}")
@Results({
@Result(property = "id", column = "id", id = true),
@Result(property = "ownerName", column = "owner_name"),
@Result(property = "balance", column = "balance"),
@Result(property = "status", column = "status"),
@Result(property = "createdAt", column = "created_at"),
@Result(property = "updatedAt", column = "updated_at")
})
List<UserAccount> findByOwnerName(@Param("name") String name);
@Update("UPDATE user_account SET balance = balance + #{amount} WHERE id = #{id}")
int updateBalance(@Param("id") int id, @Param("amount") long amount);
@Delete("DELETE FROM user_account WHERE id = #{id}")
int removeAccount(@Param("id") int id);
@Select("<script>" +
"SELECT * FROM user_account " +
"<where>" +
" <if test='id != null'> AND id = #{id} </if>" +
" <if test='ownerName != null'> AND owner_name = #{ownerName} </if>" +
"</where>" +
"</script>")
@Results({
@Result(property = "ownerName", column = "owner_name"),
@Result(property = "balance", column = "balance")
})
List<UserAccount> searchDynamic(UserAccount filter);
}
Pontos importantes na impleemntação acima:
- @Options: Permite recuperar o ID gerado automaticamente pelo banco de dados e injetá-lo de volta no objeto Java.
- @Results: Mapeia manualmente as colunas do banco de dados para os atributos da classe, essencial quando os nomes não são idênticos (ex: snake_case para camelCase).
- SQL Dinâmico: Ao usar a tag
<script>dentro de uma enotação, é possível utilizar a sintaxe XML do MyBatis para criar consultas flexíveis com<if>e<where>.
Execução e Teste
Para validar a integração, podemos injetar o Mapper em um componente de serviço ou repositório:
@Service
public class AccountService {
@Autowired
private UserAccountMapper accountMapper;
public void processarExemplo() {
UserAccount novaConta = new UserAccount();
novaConta.setOwnerName("TechUser");
novaConta.setBalance(5000L);
novaConta.setStatus(1);
// Salvar
accountMapper.insertAccount(novaConta);
System.out.println("ID Gerado: " + novaConta.getId());
// Atualizar
accountMapper.updateBalance(novaConta.getId(), 1500L);
// Buscar
List<UserAccount> resultados = accountMapper.findByOwnerName("TechUser");
resultados.forEach(acc -> System.out.println("Saldo: " + acc.getBalance()));
// Remover
accountMapper.removeAccount(novaConta.getId());
}
}