Corrección del mapeo camelCase en MyBatis con múltiples fuentes de datos en Spring Boot

Al configurar múltiples fuentes de datos en Spring Boot, la sección de MyBatis en application.yml puede no aplicarse, ya que no se indica explícitamente a qué fuente de datos debe vincularse.

Configuración de ejemplo en application.yml

server:
  port: 8080

spring:
  datasource:
    primaria:
      jdbc-url: jdbc:mysql://localhost:3306/base_principal?useSSL=false&serverTimezone=UTC
      username: usuario
      password: clave
      driver-class-name: com.mysql.cj.jdbc.Driver
    secundaria:
      jdbc-url: jdbc:mysql://localhost:3306/base_secundaria?useSSL=false&serverTimezone=UTC
      username: usuario
      password: clave
      driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  type-aliases-package: com.example.modelo
  mapper-locations: classpath*:mappers/**/*.xml
  configuration:
    map-underscore-to-camel-case: true

Primera solución: Configuración global

Se mantiene la configuración de camelCase en application.yml y se define un bean para la configuración global de MyBatis.

@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration configuracionMybatis() {
    return new org.apache.ibatis.session.Configuration();
}

Luego, se asigna esta connfiguración al crear el SqlSessionFactory:

@Primary
@Bean(name = "fabricaSesionPrimaria")
public SqlSessionFactory crearFabricaSesion(@Qualifier("fuenteDatosPrimaria") DataSource fuenteDatos, 
                                            org.apache.ibatis.session.Configuration configuracionMybatis) throws Exception {
    SqlSessionFactoryBean fabricaBean = new SqlSessionFactoryBean();
    fabricaBean.setDataSource(fuenteDatos);
    fabricaBean.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath*:mappers/*.xml"));
    fabricaBean.setTypeAliasesPackage("com.example.modelo");
    fabricaBean.setConfiguration(configuracionMybatis);
    return fabricaBean.getObject();
}

Código completo de configuración para la fuente de datos primaria:

package com.example.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = {"com.example.repositorio"}, sqlSessionFactoryRef = "fabricaSesionPrimaria")
public class ConfiguracionDatosPrimarios {

    @Bean(name = "fuenteDatosPrimaria")
    @ConfigurationProperties(prefix = "spring.datasource.primaria")
    public DataSource fuenteDatos() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public PlatformTransactionManager gestorTransacciones() {
        return new DataSourceTransactionManager(this.fuenteDatos());
    }

    @Bean
    @ConfigurationProperties(prefix = "mybatis.configuration")
    public org.apache.ibatis.session.Configuration configuracionMybatis() {
        return new org.apache.ibatis.session.Configuration();
    }

    @Primary
    @Bean(name = "fabricaSesionPrimaria")
    public SqlSessionFactory fabricaSesionPrimaria(@Qualifier("fuenteDatosPrimaria") DataSource fuenteDatos,
                                                   org.apache.ibatis.session.Configuration configuracionMybatis) throws Exception {
        SqlSessionFactoryBean fabricaBean = new SqlSessionFactoryBean();
        fabricaBean.setDataSource(fuenteDatos);
        fabricaBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mappers/*.xml"));
        fabricaBean.setTypeAliasesPackage("com.example.modelo");
        fabricaBean.setConfiguration(configuracionMybatis);
        return fabricaBean.getObject();
    }
}

Segunda solución: Configuración directa en SqlSessionFactory

Se establece el mapeo camelCase directamente al obtener el objeto SqlSessionFactory:

sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);

Ejemplo de implementación en el método del bean:

@Primary
@Bean(name = "fabricaSesionPrimaria")
public SqlSessionFactory fabricaSesionPrimaria(@Qualifier("fuenteDatosPrimaria") DataSource fuenteDatos) throws Exception {
    SqlSessionFactoryBean fabricaBean = new SqlSessionFactoryBean();
    fabricaBean.setDataSource(fuenteDatos);
    fabricaBean.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath*:mappers/*.xml"));
    fabricaBean.setTypeAliasesPackage("com.example.modelo");
    fabricaBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
    return fabricaBean.getObject();
}

Esta solución no requiere un bean separado para la configuración de MyBatis y se integra directamente en la creación de la fábrica de sesiones.

Etiquetas: Spring Boot MyBatis java DataSource MySQL

Publicado el 6-2 20:50