Java MyBatis Framework
Librerías de uso común en Java
MyBatis es un excelente framework de capa de persistencia que simplifica la interacción entre las aplicaciones Java y las bases de datos relacionales. MyBatis mapea sentencias SQL con objetos Java mediante XML o anotaciones, evitando gran cantidad de código repetitivo (boilerplate) en la programación tradicional con JDBC.
Características principales de MyBatis
1. Separación de SQL y código
MyBatis permite a los desarrolladores separar las sentencias SQL del código Java, almacenándolas en archivos XML o anotaciones, lo que hace que el código sea más claro y fácil de mantener.2. Mapeo automático
MyBatis puede mapear automáticamente los resultados de las consultas de la base de datos a objetos Java, reduciendo considerablemente el trabajo de conversión de datos.3. SQL dinámico
MyBatis proporciona potentes funciones de SQL dinámico, que permiten generar diferentes sentencias SQL según distintas condiciones.4. Mecanismo de caché
MyBatis incluye caché de primer nivel y caché de segundo nivel, lo que puede mejorar eficazmente el rendimiento de la aplicación.Arquitectura básica de MyBatis
1. Componentes principales
- SqlSessionFactory: clase de fábrica que crea SqlSession
- SqlSession: interfaz principal para ejecutar comandos SQL
- Interfaz Mapper: define los métodos de operación de la base de datos
- Mapper XML: archivo de configuración que contiene sentencias SQL
2. Flujo de trabajo
- La aplicación crea SqlSessionFactory mediante SqlSessionFactoryBuilder
- SqlSessionFactory crea SqlSession
- SqlSession obtiene la instancia de la interfaz Mapper
- Llame a los métodos del Mapper para ejecutar operaciones de base de datos
- Confirmar la transacción y cerrar SqlSession
Configuración de MyBatis
1. Archivo de configuración principal (mybatis-config.xml)
Ejemplo
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment>
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_db"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2. Ejemplo de archivo Mapper
Ejemplo
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="getUserById" parameterType="int" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="com.example.model.User">
INSERT INTO users(name, email) VALUES(#{name}, #{email})
</insert>
</mapper>
Uso básico de MyBatis
1. Obtener SqlSession
Ejemplo
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
2. Ejecutar consulta
Ejemplo
User user = session.selectOne("com.example.mapper.UserMapper.getUserById", 1);
// Método 2: a través de la interfaz Mapper
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
3. Ejecutar inserción
Ejemplo
newUser.setName("Zhang San");
newUser.setEmail("[email protected]");
int rows = mapper.insertUser(newUser);
session.commit(); // Confirmar la transacción
SQL dinámico de MyBatis
MyBatis proporciona varios elementos de SQL dinámico que pueden generar dinámicamente sentencias SQL según diferentes condiciones:
1. Elemento if
Ejemplo
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
2. Elementos choose/when/otherwise
Ejemplo
SELECT * FROM users
WHERE status = 'ACTIVE'
<choose>
<when test="name != null">
AND name like #{name}
</when>
<when test="email != null">
AND email = #{email}
</when>
<otherwise>
AND 1=1
</otherwise>
</choose>
</select>
3. Elemento foreach
Ejemplo
SELECT * FROM users
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>
Consultas de asociación en MyBatis
1. Asociación uno a uno
Ejemplo
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
<association property="address" javaType="Address">
<id property="id" column="address_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
</association>
</resultMap>
<select resultMap="userWithAddress">
SELECT
u.id as user_id, u.name as user_name,
a.id as address_id, a.street, a.city
FROM users u
LEFT JOIN addresses a ON u.address_id = a.id
WHERE u.id = #{id}
</select>
2. Asociación uno a muchos
Ejemplo
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<result property="orderDate" column="order_date"/>
<result property="amount" column="amount"/>
</collection>
</resultMap>
<select resultMap="userWithOrders">
SELECT
u.id as user_id, u.name as user_name,
o.id as order_id, o.order_date, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = #{id}
</select>
Mecanismo de caché de MyBatis
1. Caché de primer nivel
La caché de primer nivel es una caché a nivel de SqlSession, habilitada de forma predeterminada. En el mismo SqlSession, la misma consulta solo ejecuta SQL una vez.
Características:
Alcance:
SqlSessionNivel (activado por defecto, no se puede desactivar)Ciclo de vida: asociado a la
SqlSessioncreación de SqlSession, y se destruye con suSqlSessioncierre.Situaciones que desencadenan la limpieza:
Ejecutar
INSERT/UPDATE/DELETEla operaciónLlamar
sqlSession.clearCache()Ejecutar el rollback de la transacción
Configurar un SqlSession diferente
Statement ID(incluso si el SQL es el mismo)
Notas:
Ejemplo
User user1 = sqlSession.selectOne("getUserById", 1); // Ejecutar SQL
User user2 = sqlSession.selectOne("getUserById", 1); // Obtener de la caché
2. Caché de segundo nivel
La caché de segundo nivel es una caché a nivel de Mapper y varios SqlSession pueden compartirla. Debe habilitarse en el archivo de configuración:
<settings>
<setting name="cacheEnabled" value="true"/> <!-- 默认true可省略 -->
</settings>
y configurarse en el archivo Mapper:
<cache eviction="LRU" <!-- 淘汰策略(默认LRU) --> flushInterval="60000" <!-- 刷新间隔(毫秒) --> size="512" <!-- 缓存对象数量 --> readOnly="true"/> <!-- 只读模式(性能更优) -->
Comparación de estrategias de caché:
| Estrategia | Descripción | Escenario aplicable |
|---|---|---|
| LRU | Menos usado recientemente | Uso habitual |
| FIFO | Primero en entrar, primero en salir | Acceso en orden fijo |
| SOFT | Referencia suave | Escenarios sensibles a la memoria |
| WEAK | Referencia débil | Extremadamente sensible a la memoria |
Integración de MyBatis con Spring
1. Configuración de dependencias (recomendado para Spring Boot moderno)
Ejemplo
<dependencies>
<!-- Solución de integración Spring Boot Starter (recomendada) -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- O usar en un proyecto Spring tradicional -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.3</version>
</dependency>
<!-- Elija el controlador de la base de datos según el caso real -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
2. Esquemas de configuración (tres métodos principales)
Opción 1: Configuración automática de Spring Boot (la más sencilla)
Ejemplo
mybatis:
mapper-locations: classpath*:mapper/**/*.xml
type-aliases-package: com.example.model
configuration:
map-underscore-to-camel-case: true # Conversión automática a camelCase
Opción 2: Configuración completa con Java Config (control detallado)
Ejemplo
public class MyBatisConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setTypeAliasesPackage("com.example.model");
// Configuración personalizada (ejemplo)
org.apache.ibatis.session.Configuration config = new Configuration();
config.setMapUnderscoreToCamelCase(true);
config.setDefaultFetchSize(100);
factory.setConfiguration(config);
// Configuración de plugins (ejemplo)
factory.setPlugins(
new MyBatisInterceptor(),
new PaginationInterceptor()
);
return factory.getObject();
}
@Bean
public MapperScannerConfigurer mapperScanner() {
MapperScannerConfigurer scanner = new MapperScannerConfigurer();
scanner.setBasePackage("com.example.mapper");
scanner.setAnnotationClass(Repository.class); // Restringir el escaneo de anotaciones
return scanner;
}
}
Opción 3: Configuración tradicional con XML (compatible con proyectos antiguos)
Ejemplo
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>
3. Configuración de la gestión de transacciones
Ejemplo
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
// Se puede definir una plantilla de transacción
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager manager) {
return new TransactionTemplate(manager);
}
}
4. Normas de uso y mejores prácticas
Definición de la interfaz Mapper:
Ejemplo
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectById(@Param("id") int id);
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("INSERT INTO users(name) VALUES(#{name})")
int insert(User user);
}
Ejemplo de la capa Service:
Ejemplo
@Transactional(readOnly = true) // Por defecto, solo lectura
public class UserService {
private final UserMapper userMapper;
@Autowired // Se recomienda la inyección por constructor
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Transactional // Abrir transacción separada para operaciones de escritura
public User createUser(String name) {
User user = new User();
user.setName(name);
userMapper.insert(user);
return userMapper.selectById(user.getId());
}
}
5. Integración de funciones avanzadas
Configuración dinámica de fuente de datos:
Ejemplo
@Primary
public DataSource dynamicDataSource() {
DynamicDataSource ds = new DynamicDataSource();
ds.setDefaultTargetDataSource(primaryDataSource());
ds.setTargetDataSources(Map.of(
"master", primaryDataSource(),
"slave", secondaryDataSource()
));
return ds;
}
Gestión de transacciones con múltiples fuentes de datos:
Ejemplo
public PlatformTransactionManager transactionManager() {
return new ChainedTransactionManager(
new JpaTransactionManager(entityManagerFactory()),
new DataSourceTransactionManager(dataSource())
);
}
Mejores prácticas de MyBatis
- Usar interfaces Mapper en lugar de usar SqlSession directamente: Esto hace que el código sea más seguro en cuanto a tipos y más fácil de mantener.
- Usar SQL dinámico de forma razonable: Evitar el riesgo de inyección SQL y mantener la legibilidad del SQL.
- Operaciones por lotes: Para operaciones con grandes volúmenes de datos, utilice el procesamiento por lotes para mejorar el rendimiento.
- Usar caché de forma razonable: Configure una estrategia de caché adecuada según las necesidades del negocio.
- Optimización de SQL: Escriba sentencias SQL eficientes en el XML del Mapper.
MyBatis es un marco ORM flexible y potente. Su uso adecuado puede mejorar enormemente la eficiencia del desarrollo y el rendimiento de las aplicaciones. Espero que este artículo te ayude a comprender y utilizar el marco MyBatis.
Otras extensiones