3.5 MyBatis 与 Spring 集成


文档摘要

3.5 MyBatis 与 Spring 集成 3.5 MyBatis 与 Spring 集成 MyBatis 与 Spring 集成是构建企业级 Java 应用的常见模式。Spring 提供了强大的依赖注入、事务管理和 AOP 等功能,而 MyBatis 则专注于数据持久化。将两者结合,可以充分发挥各自的优势,简化开发,提高效率。 3.5.1 集成优势 简化配置: Spring 容器负责管理 MyBatis 的 SqlSessionFactory 和 Mapper 接口,减少了 XML 配置文件的复杂性。 事务管理: Spring 的事务管理机制可以方便地应用于 MyBatis 的数据访问操作,保证数据的一致性。

3.5 MyBatis 与 Spring 集成

3.5 MyBatis 与 Spring 集成

MyBatis 与 Spring 集成是构建企业级 Java 应用的常见模式。Spring 提供了强大的依赖注入、事务管理和 AOP 等功能,而 MyBatis 则专注于数据持久化。将两者结合,可以充分发挥各自的优势,简化开发,提高效率。

3.5.1 集成优势

  • 简化配置: Spring 容器负责管理 MyBatis 的 SqlSessionFactory 和 Mapper 接口,减少了 XML 配置文件的复杂性。

  • 事务管理: Spring 的事务管理机制可以方便地应用于 MyBatis 的数据访问操作,保证数据的一致性。

  • 依赖注入: Mapper 接口可以通过 Spring 的依赖注入直接注入到 Service 层,无需手动创建实例。

  • AOP 支持: Spring 的 AOP 功能可以应用于 MyBatis 的数据访问操作,实现日志记录、性能监控等横切关注点。

3.5.2 集成方式

MyBatis 与 Spring 集成主要通过 mybatis-spring 模块实现。该模块提供了以下核心组件:

  • SqlSessionFactoryBean 用于创建 SqlSessionFactory 实例,并将其注册到 Spring 容器中。

  • MapperFactoryBean 用于创建 Mapper 接口的代理对象,并将其注册到 Spring 容器中。

  • SqlSessionTemplate 用于执行 SQL 语句,并管理 SqlSession 的生命周期。

  • @MapperScan 用于自动扫描 Mapper 接口,并将其注册到 Spring 容器中。

3.5.3 集成步骤

  1. 添加依赖: 在 Maven 或 Gradle 项目中,添加 mybatis-spring 依赖。

    <!-- Maven --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.1.0</version> </dependency> <!-- Gradle --> implementation 'org.mybatis:mybatis-spring:2.1.0'

    同时,确保已经添加了 mybatis 和 Spring 相关的依赖。

  2. 配置数据源: 在 Spring 配置文件中,配置数据源。可以使用 Spring 提供的 DriverManagerDataSource 或第三方数据源,如 DruidDataSourceHikariCP

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_db?useSSL=false&amp;serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean>
  3. 配置 SqlSessionFactoryBean: 创建 SqlSessionFactoryBean 实例,并设置数据源、MyBatis 配置文件路径(可选)、Mapper 接口所在的包路径等属性。

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 可选 --> <property name="mapperLocations" value="classpath:mapper/*.xml"/> <!-- 可选 --> </bean>

    如果省略 configLocation 属性,则 MyBatis 将使用默认配置。如果省略 mapperLocations 属性,则需要在 mybatis-config.xml 文件中配置 Mapper 接口。

  4. 配置 MapperScannerConfigurer 或使用 @MapperScan: 使用 MapperScannerConfigurer 扫描 Mapper 接口,并将其注册到 Spring 容器中。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean>

    或者,可以使用 @MapperScan 注解,更加简洁。在 Spring 配置类上添加 @MapperScan 注解,并指定 Mapper 接口所在的包路径。

    @Configuration @MapperScan("com.example.mapper") public class AppConfig { // ... }
  5. 注入 Mapper 接口: 在 Service 层或其他需要使用 Mapper 接口的地方,通过 Spring 的依赖注入,直接注入 Mapper 接口。

    @Service public class UserService { @Autowired private UserMapper userMapper; public User getUserById(Long id) { return userMapper.selectByPrimaryKey(id); } }

3.5.4 代码实践

以下是一个简单的 MyBatis 与 Spring 集成的示例:

1. 项目结构:

mybatiss-spring-integration/ ├── pom.xml ├── src/main/java/ │ └── com/example/ │ ├── model/ │ │ └── User.java │ ├── mapper/ │ │ └── UserMapper.java │ ├── service/ │ │ └── UserService.java │ └── config/ │ └── AppConfig.java ├── src/main/resources/ │ ├── applicationContext.xml │ ├── mybatis-config.xml │ └── mapper/ │ └── UserMapper.xml └── ...

2. User.java (Model):

package com.example.model; public class User { private Long id; private String username; private String email; // Getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

3. UserMapper.java (Mapper Interface):

package com.example.mapper; import com.example.model.User; public interface UserMapper { User selectByPrimaryKey(Long id); }

4. UserMapper.xml (Mapper XML):

<?xml version="1.0" encoding="UTF-8"?> <!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="selectByPrimaryKey" parameterType="java.lang.Long" resultType="com.example.model.User"> SELECT id, username, email FROM user WHERE id = #{id} </select> </mapper>

5. UserService.java (Service):

package com.example.service; import com.example.model.User; import com.example.mapper.UserMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private UserMapper userMapper; public User getUserById(Long id) { return userMapper.selectByPrimaryKey(id); } }

6. applicationContext.xml (Spring Configuration):

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.example"/> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_db?useSSL=false&amp;serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> </beans>

7. mybatis-config.xml (MyBatis Configuration):

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <typeAliases> <package name="com.example.model"/> </typeAliases> </configuration>

8. AppConfig.java (Java Configuration - alternative to applicationContext.xml):

package com.example.config; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; @Configuration @ComponentScan("com.example") @MapperScan("com.example.mapper") public class AppConfig { @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_db?useSSL=false&serverTimezone=UTC"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource()); factoryBean.setConfigLocation(new org.springframework.core.io.ClassPathResource("mybatis-config.xml")); factoryBean.setMapperLocations(new org.springframework.core.io.ClassPathResource("mapper/*.xml")); return factoryBean.getObject(); } }

9. 测试代码 (Example Usage):

import com.example.model.User; import com.example.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(com.example.config.AppConfig.class); UserService userService = context.getBean(UserService.class); User user = userService.getUserById(1L); // Assuming user with ID 1 exists if (user != null) { System.out.println("User ID: " + user.getId()); System.out.println("Username: " + user.getUsername()); System.out.println("Email: " + user.getEmail()); } else { System.out.println("User not found."); } } }

解释:

  • User: 一个简单的 Java Bean,表示数据库中的用户。

  • UserMapper: MyBatis Mapper 接口,定义了数据库操作方法。

  • UserMapper.xml: MyBatis Mapper XML 文件,配置了 SQL 语句。

  • UserService: Spring Service 类,注入了 UserMapper,并提供了业务逻辑。

  • applicationContext.xmlAppConfig.java: Spring 配置文件,配置了数据源、SqlSessionFactoryBeanMapperScannerConfigurerAppConfig.java 展示了使用 Java Config 的方式替代 XML 配置。

  • mybatis-config.xml: MyBatis 配置文件,可以配置 MyBatis 的全局设置,如驼峰命名转换。

  • Main: 测试类,从 Spring 容器中获取 UserService,并调用 getUserById 方法。

注意事项:

  • 确保数据库连接信息正确。

  • 确保 mybatis-config.xml 和 Mapper XML 文件在 classpath 下。

  • 可以根据实际情况调整包名和类名。

  • 使用 Spring Boot 可以进一步简化配置。

3.5.5 事务管理

Spring 提供了声明式事务管理,可以方便地应用于 MyBatis 的数据访问操作。

  1. 配置事务管理器: 在 Spring 配置文件中,配置事务管理器。

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
  2. 开启事务注解: 在 Spring 配置文件中,开启事务注解。

    <tx:annotation-driven transaction-manager="transactionManager"/>

    或者,在 Spring 配置类上添加 @EnableTransactionManagement 注解。

    @Configuration @EnableTransactionManagement public class AppConfig { // ... }
  3. 添加事务注解: 在需要事务管理的方法上,添加 @Transactional 注解。

    @Service public class UserService { @Autowired private UserMapper userMapper; @Transactional public void createUser(User user) { userMapper.insert(user); // ... } }

    @Transactional 注解可以应用于类级别或方法级别。应用于类级别时,该类中的所有 public 方法都将具有事务性。

3.5.6 使用 SqlSessionTemplate

SqlSessionTemplate 是 MyBatis-Spring 提供的线程安全、可以被多个 DAO 或者 Mapper 类所共享的类。

@Repository public class UserRepository { @Autowired private SqlSessionTemplate sqlSessionTemplate; public User findById(Long id) { return sqlSessionTemplate.selectOne("com.example.mapper.UserMapper.selectByPrimaryKey", id); } }

虽然 SqlSessionTemplate 简化了 SqlSession 的管理,但是使用 Mapper 接口的方式更加类型安全,也更容易维护。 因此,推荐使用 Mapper 接口的方式。

3.5.7 总结

MyBatis 与 Spring 集成可以简化开发,提高效率。通过 Spring 的依赖注入和事务管理,可以更好地组织代码,保证数据的一致性。 选择使用 XML 配置或者 Java Config 取决于项目需求和个人偏好。 @MapperScan 注解和 Mapper 接口的方式是推荐的使用方式,可以提高代码的可读性和可维护性.

流程图:

解释:

  • Spring Context: Spring 容器,负责管理 Bean 的生命周期。

  • DataSource: 数据源,提供数据库连接。

  • SqlSessionFactoryBean: 用于创建 SqlSessionFactory 实例。

  • SqlSessionFactory: MyBatis 的核心接口,用于创建 SqlSession 实例。

  • SqlSessionTemplate: 线程安全的 SqlSession 实现。

  • MapperFactoryBean: 用于创建 Mapper 接口的代理对象。

  • Mapper Interface: Mapper 接口,定义了数据库操作方法。

  • Service Layer: 服务层,包含业务逻辑。

  • Controller Layer: 控制层,处理用户请求。

这个流程图展示了 MyBatis 与 Spring 集成的核心组件之间的关系。 Spring 容器负责管理数据源、SqlSessionFactory 和 Mapper 接口,并将 Mapper 接口注入到 Service 层,从而实现数据访问。


发布者: 作者: 转发
评论区 (0)
U