在实际项目开发中,将 Spring 和 MyBatis 进行整合可以提高开发效率、简化配置、增强事务管理和可维护性,同时利用 Spring 的强大功能能提升系统的稳定性。这里从独立使用 MyBatis 开始,逐步实现与 Spring 框架的整合。
MyBatis 独立开发
现在,通过一个简单的案例来展示 MyBatis 的开发过程。
(1)创建 user 表
首先,创建一张用于测试的数据表。运行 sql 代码,在 db
数据库中创建一张 users
表:
CREATE DATABASE db;
USE db;DROP TABLE IF EXISTS users;
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(20) NOT NULL,password VARCHAR(20) NOT NULL
);INSERT INTO users VALUES (1, 'aa', '123');
(2)创建 Maven 项目
在 IDEA 中创建一个 Maven 项目,这里进入 New Project 选项中创建:
这里将 GroupId 命名为 com.it
。
(3)导入依赖
Maven 项目创建完成后,在项目的 pom.xml 文件中导入 MySQL 和 MyBatis 依赖:
<dependencies><!-- MyBatis 依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!-- MySQL 依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency>
</dependencies>
(4)创建 MyBatis 核心配置文件
在 src/main/resources 文件夹下创建一个 mybatis-config.xml
文件。首先,从 MyBatis 官网 拷贝一份模板至 mybatis-config.xml
文件中,并且在模板的基础上引入外部配置文件和删除 mapper 配置(后续使用注解配置 SQL 映射):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 引入外部配置文件 --><properties resource="jdbc.properties"/><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>
</configuration>
接着,在 src/main/resources 文件夹下创建一个 jdbc.properties
文件,名称与 mybatis-config.xml
文件中引入的配置文件名保持一致,其内容为:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///db?useSSL=false
jdbc.username=root
jdbc.password=123456
(5)创建 POJO 类
在 com.it.domain 文件夹下定义 User
类,属性名称与数据库字段保持一致:
public class User{private Integer id;private String username;private String password;public Integer getId() {return id;}public String getUsername() {return username;}public String getPassword() {return password;}public void setId(Integer id) {this.id = id;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
(6)使用注解配置 SQL 映射
在 com.it.dao 文件夹下定义 UserDao
接口,并通过注解实现 SQL 语句的映射:
public interface UserDao {@Insert("INSERT into users(username,password) VALUES (#{username},#{password}))")void save(User user);@Delete("DELETE FROM users WHERE id = #{id}")void delete(Integer id);@Update("UPDATE users set name = #{name}}")void update(User user);@Select("SELECT * FROM users")List<User> findAll();@Select("SELECT * FROM users WHERE id = #{id}")User findById(Integer id);
}
在之前创建的 mybatis-config.xml
文件中绑定接口:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 引入外部配置文件 --><properties resource="db.properties"/><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!-- 绑定接口 --><mappers><mapper class="com.it.dao.UserDao"/></mappers>
</configuration>
(7)测试
在 com.it 包下创建一个 App 类,测试 MyBatis 项目是否能正常运行:
public class App {public static void main(String[] args) throws IOException {// 1. 创建 SqlSessionFactoryBuilder 对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();// 2. 加载 mybatis-config.xml 配置文件InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");// 3. 创建 SqlSessionFactory 对象SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);// 4. 获取 SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();// 5. 使用 SqlSession 对象执行查询,获取 UserUserDao userDao = sqlSession.getMapper(UserDao.class);User user = userDao.findById(1);System.out.println(user);// 6. 释放资源sqlSession.close();}
}
运行上述代码后可正常查询出创建 users 数据库表时插入的用户信息。至此,MyBatis 独立项目运行成功。
Spring 整合
现在,从 App 类中的 Main 运行程序出发,分析一下 MyBatis 中可以交给 Spring 框架管理的 Bean 对象,以此实现整合。查看 Main 方法可知,前三个步骤是初始化 SqlSessionFactory 对象。第四步骤和五步骤用于获取连接和获取数据层接口,这部分主要与业务相关。最后,第六步关闭连接。在这个过程中,核心对象是 SqlSessionFactory 对象。因此,可以将 SqlSessionFactory 对象交给 Spring 框架管理,进而实现框架整合。
综上,整个整合思路是这样的:将 SqlSessionFactory 对象交给 Spring 框架管理。而由于 SqlSessionFactory 对象涉及 mybatis-config.xml 文件,因此,需要将该文件中涉及的对象一起交给 Spring 框架管理,比如 dataSource。
(1)引入 Spring 依赖
首先,我们需要引入 Spring 框架。在 MyBatis 独立开发项目的基础上,向 pom.xml 文件中导入 Spring 依赖:
<!-- Spring 依赖 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version>
</dependency>
(2)引入 Spring 操作数据库的依赖
在 pom.xml 文件中导入与 Spring 操作数据库相关的依赖:
<!-- Spring JDBC 依赖 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.10.RELEASE</version>
</dependency>
(3)引入 Spring 整合 MyBatis 的依赖
在 pom.xml 文件中导入与 Spring 整合 MyBatis 相关的依赖:
<!-- Spring 整合 MyBatis 依赖 -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version>
</dependency>
这个依赖包实际上属于 MyBatis 提供的,即 Spring 提供统一规范,MyBatis 负责实现。
(4)整合 dataSource 管理
这里使用德鲁伊连接池(数据源)对数据库连接进行管理。在使用 Spring 框架时,可以将德鲁伊数据源交给 Spring 管理。首先,在 pom.xml 文件中导入相关依赖:
<!-- Druid 连接池依赖 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version>
</dependency>
接着,选择纯注解开发模式,在 com.it.config 包下面创建一个 JdbcConfig 类:
public class JdbcConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String userName;@Value("${jdbc.password}")private String password;// 1. 定义一个方法获取要管理的对象// 2. 添加 @Bean,表示当前方法的返回值是一个 Bean@Bean("dataSource")public DataSource dataSource () {DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(userName);ds.setPassword(password);return ds;}
}
其中,dataSource 方法用于返回数据源 Bean 对象,代替了 mybatis-config.xml
文件中对数据源的配置项。
(5)整合 MyBatis
选择纯注解开发模式,在 com.it.config 包下面创建一个 MybatisConfig 配置类,用于实现对 SqlSessionFactory 对象的管理:
public class MybatisConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();// 用于替代 mybatis-config.xml 配置文件中的数据源配置项ssfb.setDataSource(dataSource);return ssfb;}@Beanpublic MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer msc = new MapperScannerConfigurer();// 用于替代 mybatis-config.xml 配置文件中的绑定接口项msc.setBasePackage("com.it.dao");return msc;}
}
其中,sqlSessionFactory 方法用于返回需要 Spring 管理的 SqlSessionFactory Bean 对象。在纯注解模式下,引用类型注入只需要为 Bean 定义方法设置形参即可,容器会根据类型自动装配对象。因此,这个方法将通过 dataSource 形参自动注入上一步中生成的数据源 Bean 对象。另外,由于 mybatis-config.xml 文件中指定了绑定接口项,因此,也需要创建对应的 mapperScannerConfigurer 来替代配置文件。
(6)创建核心配置类
完成 JdbcConfig 和 MybatisConfig 配置类之后,在 com.it.config 包下面创建一个 SpringConfig 核心配置类,将上述两个配置类通过 SpringConfig 引入:
@Configuration
@ComponentScan("com.it")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class})
public class SpringConfig {
}
注意,需要使用 @Configuration
注解表示这个类为配置类。使用 @ComponentScan
注解对包进行扫描,以此注入相关 Bean 对象。使用 @PropertySource
注解指定数据源的配置文件,最后使用 @Import
注解将 JdbcConfig 数据源配置类、 MybatisConfig 配置类引入。
(7)整合测试
在完成上述步骤后,可以将原本保留的 mybatis-config.xml 配置文件删除。至此,便完成了 Spring 对 MyBatis 的整合。现在通过 App1 类对整合结果进行测试:
public class App1 {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);UserDao userDao = ctx.getBean(UserDao.class);User user = userDao.findById(1);System.out.println(user);}
}
除。至此,便完成了 Spring 对 MyBatis 的整合。现在通过 App1 类对整合结果进行测试:
public class App1 {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);UserDao userDao = ctx.getBean(UserDao.class);User user = userDao.findById(1);System.out.println(user);}
}
最终,成功返回了 users 表中 id 等于 1 的用户信息。