在前面写的博客中,介绍了MyBatis通过配置方式和通过注解方式写的方法:
- 【Spring集成MyBatis】MyBatis诞生及代码快速入门(非注解开发)
- 【Spring集成MyBatis】MyBatis的Dao层实现(基于配置,非注解开发)
- 【Spring集成MyBatis】动态sql
- 【Spring集成MyBatis】核心配置文件
- 【Spring集成MyBatis】MyBatis的多表查询
- 【Spring集成MyBatis】MyBatis注解开发
在这篇博客中将具体介绍Spring整合MyBatis
Spring开放了一些接口,便于其他框架整合到Spring框架中去,所以导入坐标的时候,我们会导入来源于mybatis
整合好的mybatis-spring
坐标。
文章目录
- 1. 原本MyBatis代码
- 数据库表account
- 类account.java
- 配置文件SqlMapper.xml
- 外部数据源文件jdbc.properties
- 基于注解写的AccountDao.java
- 测试代码
- 运行结果
- 2. Spring整合MyBatis
- 导入相关坐标
- 写SpringConfig配置类
- JdbcConfig配置类
- MyBatis配置类
- 测试方法
1. 原本MyBatis代码
数据库表account
在这里新建了一个数据库表Account:
类account.java
package com.example.project2.domain;
public class Account {
private int id;
private String username;
private double money;
@Override
public String toString() {
return "Account{" +
"id=" + id +
", username='" + username + '\'' +
", money=" + money +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
配置文件SqlMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"></properties>
<typeAliases>
<package name="com.example.project2.domain"/>
</typeAliases>
<!-- 加载数据源-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="url" value="${jdbc.url}"/>
<property name="driver" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载Mapper类-->
<mappers>
<package name="com.example.project2.dao"/>
</mappers>
</configuration>
外部数据源文件jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
基于注解写的AccountDao.java
package com.example.project2.dao;
import com.example.project2.domain.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface AccountDao {
@Insert("insert into account(username, money) values(#{username}, #{money})")
void save(Account account);
@Delete("delete from account where id=#{id}")
void delete(int id);
@Update("update account set username=#{username} and money=#{money} where id=#{id}")
void update(Account account);
@Select("select * from account where id=#{id}")
Account findById(int id);
@Select("select * from account")
List<Account> findAll();
}
测试代码
package com.example.project2;
import com.example.project2.dao.AccountDao;
import com.example.project2.domain.Account;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Project2Application {
public static void main(String[] args) throws IOException {
// 加载输入流
InputStream inputStream = Resources.getResourceAsStream("SqlMapper.xml");
// 获得工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 工厂加载输入流
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 获得SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
List<Account> accountList = accountDao.findAll();
for (Account account : accountList) {
System.out.println(account);
}
// 关闭SqlSession
sqlSession.close();
}
}
运行结果
2. Spring整合MyBatis
导入相关坐标
在pom.xml中导入所有相关坐标:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>project2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>project2</name>
<description>project2</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
</dependencies>
</project>
其中,mybatis-spring
和mybatis
存在版本对应关系,这个需要去官网查询对应的版本(但是我去官网找了一下没找到),版本不匹配可能会导致运行出现问题等情况。注意:Spring整合MyBatis的依赖版本必须为3.0.0以上!——该句出自:整合Spring6+MyBatis3.5.10出现的bug
写SpringConfig配置类
SpringConfig配置类中,需要使用注解@Configuration
注明这是配置类
@ComponentScan
指定扫描的包,这个一般可以写大一点
@PropertySource
指定外部数据源
@Import
表示导入其他配置类,这里还需要配置JDBC的一些属性,同时配置MyBatis的属性
JDBC的属性和MyBatis属性的配置类实际作用就是将上面的SqlMapper.xml
的那些配置信息,写入到配置类中
package com.example.project2.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan("com.example.project2")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
public class SpringConfig {
}
JdbcConfig配置类
在JdbcConfig配置类中,主要写数据库驱动、链接、用户名密码等信息,即数据源来源的所有信息,对应于原本SqlMapper.xml
中的<environment>
下的部分
package com.example.project2.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
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;
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
其中,jdbc.properties中的内容:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
MyBatis配置类
原本在写MyBatis测试的时候,我们需要先加载输入流、获得工厂建造器、通过工厂建造器获得工厂、打开SqlSession会话链接
// 加载输入流
InputStream inputStream = Resources.getResourceAsStream("SqlMapper.xml");
// 获得工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 工厂加载输入流
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 获得SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
我们需要将这些方法转换到MyBatis配置类中来
上面的核心其实就是SqlSessionFactoryBuilder
,我们从中加载输入流获得的工厂
下面我们通过配置SqlSessionFactoryBean
一些必要的属性来获得具体的工厂
setTypeAliasesPackage
这个方法告诉 MyBatis 框架在指定的包路径下扫描实体类,然后为这些实体类设置别名。这样,在编写 MyBatis 的 Mapper 文件时可以直接使用实体类的别名来引用它们,而不必使用完整的类名。
举例来说,如果有一个位于 com.itheima.domain 包下的实体类 User,并且在 com.itheima.dao 包下编写了相应的 Mapper 接口,那么在 Mapper 文件中,可以使用 User 的别名来引用它,而不必写完整的类名 com.itheima.domain.User
setDataSource
就是设置相应的数据源,我们在JdbcConfig中已经配置了,这里写在属性中,Spring会自动把我们之前写好的那个dataSource bean注入进来
接着,通过配置mapperScannerConfigurer
来配置相应扫描包的范围,对应原本SqlMapper.xml
中加载Mapper类的内容
package com.example.project2.config;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MyBatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.example.project2.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.example.project2.dao");
return msc;
}
}
测试方法
package com.example.project2;
import com.example.project2.config.SpringConfig;
import com.example.project2.dao.AccountDao;
import com.example.project2.domain.Account;
import com.example.project2.service.AccountService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Project2Application {
public static void main(String[] args) throws IOException {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
AccountService accountService = ctx.getBean(AccountService.class);
Account account = accountService.findById(1);
System.out.println(account);
}
}
结果为:
PS:这里不需要再获得sqlSession
。我认为是因为,在new AnnotationConfigApplicationContext
方法的时候加载了Spring的配置类,在Spring配置类中又扫描了Service的相关内容、并import了MyBatisConfig
。
通过MyBatisConfig
获得了sqlSessionFactory,通过扫描包的方法扫描到了dao包下的类完成了sqlSession获得具体mapper的创建(等价于AccountDao accountdao = sqlSession.getMapper(AccountDao.class)
),而这个dao又进一步被注入到serviceImpl下的AccountDao中,进而可以在Service类中调用具体的方法。