本文介绍如何在 Spring 框架中整合 MyBatis 和 Junit。
这里使用一个”纯 MyBatis“的示例项目,在这个项目基础上将其修改为使用 Spring 框架的版本。
关于如何创建 MyBatis 项目以及基本的使用方式,可以看这篇文章。
先下载项目代码并导入数据库sql。
添加 spring 框架依赖:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>6.0.10version>
dependency>
要让 Spring 使用 JDBC,还需要添加一个 spring-jdbc 依赖:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>6.0.10version>
dependency>
这个依赖的版本与 Spring 框架的版本要一致。
后面创建 MyBatis 的 SqlSesstionFactory 对象时需要指定一个数据源,所以这里添加一个 Druid 依赖用于构建数据源对象:
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.16version>
dependency>
要在 Spring 框架中整合 MyBatis,还需要一个 mybatis-spring 依赖:
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>3.0.1version>
dependency>
该依赖起到类似”驱动程序“的用途,所以 mybatis-spring 的版本与 Spring 以及 MyBatis 的版本都是有关的,具体可以查看官方文档。
添加 Spring IoC 容器加载的核心配置类:
@Configuration
@ComponentScan(basePackages = "cn.icexmoon.mybatisdemo")
public class SpringConfig {
}
添加入口类:
public class SpringApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
ctx.registerShutdownHook();
}
}
之前 MyBatis 是通过 SqlSesstionFactory 加载核心配置文件,并创建一个 SqlSession 的方式来操作数据库。
在 MyBatis 的核心配置中定义了数据库连接信息以及 Mapper 的包扫描路径:
<configuration>
<typeAliases>
<package name="cn.icexmoon.mybatisdemo.entity"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="mysql"/>
dataSource>
environment>
environments>
<mappers>
<package name="cn.icexmoon.mybatisdemo.mapper"/>
mappers>
configuration>
现在我们要用 Spring Bean 的方式创建和管理 SqlSession,并且添加类似的配置信息。
添加一个配置文件 jdbc.properties:
jdbc.username=root
jdbc.password=mysql
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis?useSSL=false
在核心配置类中加载 properties:
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
}
创建另一个配置类,并用 Bean 方法创建一个 Spring 管理的数据源对象:
@Configuration
public class JDBCConfig {
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
@Bean
DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driver);
druidDataSource.setUsername(userName);
druidDataSource.setPassword(password);
return druidDataSource;
}
}
添加一个 MyBatis 的配置类,并创建 SqlSessionFactory 的 Bean:
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
//设置类型别名
sqlSessionFactoryBean.setTypeAliasesPackage("cn.icexmoon.mybatisdemo.entity");
return sqlSessionFactoryBean;
}
}
这里可以直接构建SqlSessionFactory
,但也可以像上面那样使用一个更方便的SqlSessionFactoryBean
。就像命名那样,该类实现了 Spring 的FactoryBean
接口,所以它是一个实例工厂。添加了它就等于同时添加了SqlSessionFactoryBean
Bean 以及 SqlSessionFactory
Bean。
还需要添加一个 Mapper 的设置,对应的是MapperScannerConfigurer
这个类:
@Configuration
public class MyBatisConfig {
// ...
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("cn.icexmoon.mybatisdemo.mapper");
return mapperScannerConfigurer;
}
}
当然,你也可以将上边的所有 Bean 方法都写在同一个配置类中,但是这样做对代码可读性不好。
现在我们可以在需要的时候获取SqlSessionFactory
Bean,并执行数据库操作:
public class SpringApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
ctx.registerShutdownHook();
SqlSessionFactory sqlSessionFactory = ctx.getBean(SqlSessionFactory.class);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectById(1);
System.out.println(user);
}
}
但实际上我们通常会通过 Service 进行操作:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User selectById(int id) {
return userMapper.selectById(id);
}
}
可以看到,在 Service 中并没有直接使用 SqlSessionFactory 或 SqlSession,而是直接注入 UserMapper,并使用 UserMapper 完成数据库操作。
当前项目已经添加了 JUnit 的依赖:
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13version>
<scope>testscope>
dependency>
Spring 框架要使用 JUnit,还需要添加一个 spring-test 依赖:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>6.0.10version>
<scope>testscope>
dependency>
当然,spring-test 依赖的版本要与 spring-context 一致。
添加一个 JUnit 测试套件(Test Suit):
//设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//指定上下文配置
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
}
与普通的 JUnit 测试套件不同的是,这里为测试套件添加了2个注解@RunWith
和@ContextConfiguration
,这是为了能够在测试套件中使用 Spring 的 IoC 容器以及加载配置类。
这里的写法是 Spring 整合 JUnit4 的写法,JUnit5 有所不同。
现在就可以在 JUnit 测试套件中直接编写测试用例:
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testSelectById(){
System.out.println(userService.selectById(1));
}
}
需要的 Spring Bean 直接可以使用自动装配进行注入。
本文的所有示例可以从这里获取。