- Spring集成Mybatis3.5
- 具体实现
- Spring 主配置文件引入子配置文件
十八、Spring集成Mybatis3.5
18.1 实现步骤
第一步:准备数据库表。
- 使用
t_act
表(账户表)。
- 使用
第二步:IDEA 中创建一个模块
spring6-011-springmybatis
,并引入相关依赖:spring-context
- 会关联引入
aop
依赖,spring-aop
- 会关联引入
spring-jdbc
- 会关联引入事务依赖,
spring-tx
- 会关联引入事务依赖,
mysql
驱动mybatis
mybatis-spring
:mybatis提供的与spring框架集成的依赖- 德鲁伊连接池
druid
junit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.f</groupId>
<artifactId>spring6-011-springmybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!--仓库-->
<repositories>
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<!--依赖-->
<dependencies>
<!--spring context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.8</version>
</dependency>
<!--spring jdbc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.8</version>
</dependency>
<!--mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!--myabtis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<!--mybatis-spring依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.3</version>
</dependency>
<!--druid依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>第三步:基于三层架构实现,提前创建好所有的包。
com.f.bank.mapper
- 在 Mybatis 中习惯将
dao
写成mapper
,并且不需要写实现类,因为 Mybatis 会通过动态代理机制自动给我们生成实现类。
- 在 Mybatis 中习惯将
com.f.bank.service
com.f.bank.service.impl
com.f.bank.pojo
第四步:编写
pojo
类。Account
类,属性私有化,提供公开的setter
、getter
和toString
方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package com.f.spring6.pojo;
/**
* @author fzy
* @date 2024/1/27 14:58
*/
public class Account {
private String actno;
private Double balance;
public Account() {
}
public Account(String actno, Double balance) {
this.actno = actno;
this.balance = balance;
}
public String toString() {
return "Account{" +
"actno='" + actno + '\'' +
", balance=" + balance +
'}';
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
}
第五步:编写
mapper
接口。AccountMapper
接口,定义方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package com.f.spring6.mapper;
import com.f.spring6.pojo.Account;
import java.util.List;
/**
* @author fzy
* @date 2024/1/27 15:00
*/
public interface AccountMapper { // 该接口的实现类是Mybatis通过动态代理机制动态生成的
// 新增账户
int insert(Account account);
// 根据账号删除账户
int deleteByActno(String actno);
// 修改账户
int update(Account account);
// 根据账号查询账户
Account selectByActno(String actno);
// 查询所有账户
List<Account> selectAll();
}
第六步:编写
mapper
配置文件。在配置文件中配置命名空间为
AccountMapper
接口的全类名,以及每一个方法对应的sql
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<mapper namespace="com.f.spring6.mapper.AccountMapper">
<insert id="insert">
INSERT INTO t_act VALUES (#{actno}, #{balance})
</insert>
<delete id="deleteByActno">
DELETE FROM t_act
<where>
actno = #{actno}
</where>
</delete>
<update id="update">
UPDATE t_act
<set>
balance = #{balance}
</set>
<where>
actno = #{actno}
</where>
</update>
<select id="selectByActno" resultType="Account">
SELECT actno, balance
FROM t_act
<where>
actno = #{actno}
</where>
</select>
<select id="selectAll" resultType="Account">
SELECT actno, balance
FROM t_act
</select>
</mapper>
第七步:编写
service
接口和service
接口实现类。AccountService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29package com.f.spring6.service;
import com.f.spring6.pojo.Account;
import java.util.List;
/**
* @author fzy
* @date 2024/1/27 15:14
*/
public interface AccountService {
// 开户
int save(Account account);
// 销户
int deleteByActno(String actno);
// 修改账户
int modify(Account account);
// 查询账户
Account getByActno(String actno);
// 查询所有账户
List<Account> getAll();
// 转账
void transfer(String fromActno, String toActno, double money);
}AccountServiceImpl
- 添加事务
@Transactional
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65package com.f.spring6.service.impl;
import com.f.spring6.mapper.AccountMapper;
import com.f.spring6.pojo.Account;
import com.f.spring6.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author fzy
* @date 2024/1/27 15:17
*/
public class AccountServiceImpl implements AccountService {
private AccountMapper accountMapper;
public int save(Account account) {
return accountMapper.insert(account);
}
public int deleteByActno(String actno) {
return accountMapper.deleteByActno(actno);
}
public int modify(Account account) {
return accountMapper.update(account);
}
public Account getByActno(String actno) {
return accountMapper.selectByActno(actno);
}
public List<Account> getAll() {
return accountMapper.selectAll();
}
public void transfer(String fromActno, String toActno, double money) {
Account fromAct = accountMapper.selectByActno(fromActno);
Account toAct = accountMapper.selectByActno(toActno);
if (fromAct.getBalance() < money) {
throw new RuntimeException("账户余额不足");
}
fromAct.setBalance(fromAct.getBalance() - money);
toAct.setBalance(toAct.getBalance() + money);
int count = accountMapper.update(fromAct);
// 人为设置异常
//String s = null;
//s.toString();
count += accountMapper.update(toAct);
if (count != 2) {
throw new RuntimeException("未知异常,转账失败");
}
}
}- 添加事务
第八步:编写
jdbc.properties
配置文件。数据库连接池相关信息。
1
2
3
4jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring6
jdbc.username=root
jdbc.password=root
第九步:编写
mybatis-config.xml
配置文件。该文件可以没有,大部分的配置可以转移到 Spring 配置文件中。
如果遇到 Mybatis 相关的系统级配置,还是需要这个文件。如:缓存。
- Spring 集成 Mybatis 之后,可以将 Mybatis 的核心配置文件中的大部分的配置转移到 Spring 配置文件中,所以可以没有 Mybatis 的核心配置文件,如果遇到 Mybatis 相关的系统级配置,还是需要这个文件。所以只要不进行系统级参数的配置, Mybatis 配置文件可以省略。
1
2
3
4
5
6
7
8
9
10
<configuration>
<settings>
<!--帮助我们打印mybatis的日志信息、sql语句等-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
</configuration>
第十步:编写
spring.xml
配置文件。- 组件扫描
- 引入外部的属性文件
- 数据源(德鲁伊连接池)
SqlSessionFactoryBean
配置- 注入 mybatis 核心配置文件路径
- 指定别名包
- 注入数据源
- Mapper 扫描配置器
- 主要扫描
Mapper
接口,生成代理类
- 主要扫描
- 事务管理器
DataSourceTransactionManager
- 注入数据源
- 启用事务注解
- 注入事务管理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<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"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--组件扫描-->
<context:component-scan base-package="com.f.spring6"/>
<!--引入外部属性配置文件-->
<context:property-placeholder location="jdbc.properties"/>
<!--数据源(德鲁伊连接池)-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置SqlSessionFactoryBean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
<!--指定mybatis核心配置文件-->
<property name="configLocation" value="mybatis-config.xml"/>
<!--指定别名包-->
<property name="typeAliasesPackage" value="com.f.spring6.pojo"/>
</bean>
<!--配置Mapper扫描配置器,主要扫描Mapper接口,生成代理类-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.f.spring6.mapper"/>
</bean>
<!--配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--启用事务注解-->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>第十一步:编写测试程序,进行测试。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.f.spring6.test;
import com.f.spring6.service.AccountService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author fzy
* @date 2024/1/27 15:44
*/
public class SpringMybatisTest {
public void testSpringMybatis() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
try {
accountService.transfer("act001", "act002", 10000.0);
System.out.println("转账成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
18.2 Spring 主配置文件引入子配置文件
Spring 配置文件可以有多个,并且可以在 Spring 的核心配置文件中使用
import
引入子配置文件。例如我们可以将组件扫描单独定义到一个配置文件中。
1
2
3
4
5
6
7
8
9
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--组件扫描-->
<context:component-scan base-package="com.f.spring6"/>
</beans>然后在核心配置文件中使用
import
标签引入子配置文件:1
2
3
4
5
6
7
8
9
10
11
12
<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"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--在spring的核心配置文件中引入组件扫描子配置文件-->
<import resource="spring-common.xml"/>
......
</beans>
在实际开发中,配置可能会很多,
service
单独配置到一个文件中,dao
单独配置到一个文件中,然后在核心配置文件中引入,养成好习惯。