Mybatis 手撸专栏
第20章:整合Spring
引言
在前几篇文章中,我们详细介绍了 Mybatis 的基本使用和高级特性,以及二级缓存的原理和优化策略。然而,对于实际的项目开发而言,仅仅使用 Mybatis 本身可能还不够。通常,我们需要将 Mybatis 与其他框架进行整合,以便更好地应对复杂的业务场景和需求。而其中最常见的整合方式莫过于 Mybatis 和 Spring 的组合。
本章我们将深入探讨如何整合 Mybatis 和 Spring,以及如何利用 Spring 的优势来简化我们的开发流程。我们将从配置 Spring 和 Mybatis,到实现事务管理和依赖注入,一步步地带领大家完成整合的过程。
配置 Spring 和 Mybatis
添加 Maven 依赖
首先,我们需要在项目的 pom.xml
文件中添加 Mybatis 和 Spring 的 Maven 依赖。请确保您已经正确配置了 Maven 环境。
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
<!-- Spring Context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<!-- 数据库驱动,根据实际使用的数据库选择 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
配置 Spring 和 Mybatis
接下来,我们需要配置 Spring 和 Mybatis 的相关配置文件。
1. applicationContext.xml
首先,创建一个 applicationContext.xml
的配置文件,并将其放置在项目的 resources
目录下。在这个文件中,我们可以配置 Spring 的核心功能,以及与 Mybatis 相关的配置。
<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/mydatabase?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- Mybatis SqlSessionFactory 配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:com/example/mapper/*.xml"/>
<property name="typeAliasesPackage" value="com.example.model"/>
</bean>
<!-- Mybatis Mapper 接口扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解式事务 -->
<tx:annotation-driven/>
</beans>
在上述配置中,我们使用了 Spring 的 DriverManagerDataSource
类作为数据源,根据实际情况修改相关配置。同时,我们配置了 Mybatis 的 SqlSessionFactory
,指定了 Mapper 接口和映射文件的位置,以及实体类的包名。
2. web.xml
如果您使用的是基于 Servlet 的 Web 应用程序,还需要在 web.xml
文件中添加如下配置:
<!-- Spring 配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
这样,当应用程序启动时,Spring 将会加载 applicationContext.xml
文件并初始化 Spring 容器。
使用 Spring 进行事务管理
在项目开发过程中,事务管理是非常重要的一个方面。Spring 提供了强大的事务管理功能,可以简化我们的代码,并确保事务的一致性和完整性。
配置事务管理器
我们已经在 applicationContext.xml
文件中配置了事务管理器 DataSourceTransactionManager
。现在,我们需要使用 @EnableTransactionManagement
注解来启用 Spring 的事务管理功能。
首先,在 Spring 的配置类上添加 @EnableTransactionManagement
注解:
@Configuration
@EnableTransactionManagement
public class AppConfig {
// ...
}
接下来,我们可以在需要进行事务管理的方法上添加 @Transactional
注解:
@Transactional
public void addUser(User user) {
// 添加用户的业务逻辑
userDao.addUser(user);
}
在上述代码中,我们使用 @Transactional
注解标识了一个添加用户的方法。当该方法被调用时,Spring 将自动创建并管理事务。如果方法执行成功,则事务将被提交;如果方法执行出现异常,则事务将被回滚。
事务传播行为
在实际的业务场景中,我们经常会遇到多个方法相互调用的情况。而在事务管理中,就在事务管理中,我们需要考虑方法之间的事务传播行为,以确保事务的一致性和正确性。
Spring 提供了几种事务传播行为的选项,我们可以根据实际需求来选择合适的选项。
- PROPAGATION_REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新事务。这是最常用的传播行为,适用于大多数的业务场景。
- PROPAGATION_REQUIRES_NEW:创建一个新事务,并挂起当前的事务(如果存在)。这意味着无论外部事务是否存在,该方法都将在自己的独立事务中执行。
- PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。该传播行为适用于不需要强制事务的读取操作。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起该事务。适用于不需要事务支持的操作,例如只读查询等。
通过使用不同的事务传播行为,我们可以根据具体情况灵活地控制事务的行为。
代码语言:java复制@Transactional(propagation = Propagation.REQUIRED)
public void processOrder(Order order) {
// 处理订单的业务逻辑
// 调用其他事务方法
userService.updateUserPoints(order.getUserId(), order.getPoints());
inventoryService.reduceStock(order.getProductId(), order.getQuantity());
}
在上述代码中,我们使用了 @Transactional
注解,并在方法上设置了事务的传播行为为 Propagation.REQUIRED
。这表示在处理订单的过程中,将会自动创建一个新的事务,并且如果 userService.updateUserPoints
和 inventoryService.reduceStock
方法中存在事务,则会加入当前的事务。
利用 Spring 的依赖注入
一直以来,依赖注入(Dependency Injection)都是 Spring 框架的明星特性之一。通过依赖注入,我们可以将对象之间的依赖关系交给 Spring 容器来管理,以实现松耦合的设计。
在整合 Mybatis 和 Spring 的过程中,我们可以充分利用 Spring 的依赖注入功能,提高代码的可维护性和可测试性。
配置文件中的 Bean 声明
在 applicationContext.xml
配置文件中,我们可以使用 <bean>
元素来声明需要被 Spring 管理的 Bean。
<bean id="userService" class="com.example.service.UserService">
<property name="userDao" ref="userDao" />
</bean>
<bean id="userDao" class="com.example.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
在上述代码中,我们通过 <bean>
元素配置了一个名为 userService
的 Bean,它的类型是 com.example.service.UserService
。同时,我们使用 <property>
元素来注入 userService
的依赖,即 userDao
。
通过注解进行依赖注入
除了在配置文件中声明 Bean 和依赖关系外,我们还可以使用注解方式来进行依赖注入。
@Autowired 注解
@Autowired
是 Spring 框架提供的基础注解之一,用于自动注入依赖。
我们可以在需要注入依赖的地方使用 @Autowired
注解,Spring 将会根据类型自动查找并注入相应的 Bean。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
// ...
}
在上述代码中,我们使用 @Autowired
注解将 userDao
成员变量注入到 UserServiceImpl
类中。
@Resource 注解
@Resource
注解是 JavaEE 规范中定义的注解,也可以用于依赖注入。
与 @Autowired
注解不同,@Resource
注解可以根据名称或类型来进行依赖查找和注入。
@Controller
public class UserController {
@Resource
private UserService userService;
// ...
}
在上述代码中,我们使用 @Resource
注解将 userService
成员变量注入到 UserController
类中。
构造函数注入
除了使用属性注入外,我们还可以使用构造函数注入来满足对象之间的依赖关系。
在 Spring 的配置文件中,我们可以使用 <constructor-arg>
元素来配置构造函数注入的参数。
<bean id="userService" class="com.example.service.UserServiceImpl">
<constructor-arg ref="userDao" />
</bean>
在上述配置中,我们使用 <constructor-arg>
元素注入了一个类型为 com.example.dao.UserDao
的 Bean。
在相应的类中,我们可以定义一个带有参数的构造函数,Spring 将会根据配置自动进行构造函数注入。
代码语言:java复制@Service
public class UserServiceImpl implements UserService {
private final UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
// ...
}
在上述代码中,我们定义了一个带有 UserDao
参数的构造函数,并将其赋值给了 userDao
成员变量。
通过构造函数注入,我们可以在对象创建时就完成依赖关系的注入,确保对象的一致性和稳定性。
总结
本文我们深入探讨了如何将 Mybatis 和 Spring 进行整合。通过配置 Spring 和 Mybatis,我们可以充分发挥两者的优势,简化开发流程,并确保事务的一致性和完整性。
同时,我们还介绍了如何利用 Spring 的依赖注入功能,实现对象之间的解耦和灵活管理。
希望本文对您理解整合 Mybatis 和 Spring 的过程有所帮助。如果您有任何问题或需要进一步的指导,请随时向我提问。谢谢阅读!
文章参考来源:Spring Framework Documentation MyBatis Documentation
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!