五、Spring和Mybatis的整合
以Account账户表为案例,查询表中的数据,并且CRUD操作
1. 整合的思路
1)Mybatis操作数据库,提供sql语句的操作,秩序操作映射文件
Mybatis的主配置文件为空即可
2)Spring操作数据库连接池技术
3)Spring操作Mybatis工厂对象
-- 配置数据库的数据源
-- 加载mybatis主配置件
-- 配置别名包扫描器
4)Spring操作mybatis的动态的代理
2. 整合的步骤
1)使用maven创建一个java工程 02-spring-mybatis
2)在pom.xml文件中添加开发需要的依赖包
-- spring的核心jar包
-- mysql的驱动程序包
-- 数据库连接池的依赖jar包:druid
-- 数据库JDBC的模板包
-- mybatis的依赖包
-- mybatis与spring的整合包
-- @Resource注解依赖的jar包
-- spring的test包
-- Junit的单元测试包
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjpowernode</groupId>
<artifactId>02-spring-mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<name>02-spring-mybatis</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--添加Junit的单元测试包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!--添加Mysql驱动程序包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--添加数据库连接池的druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!--spring的jdbc模板包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--添加mybatis的依赖包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--添加Spring的核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<!--添加Spring的test依赖包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<!--添加mybatis和spring的整合包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- @Resource注解依赖的jar包-->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<!--添加log4j日志的jar包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--找映射文件:spring与mybatis整合肯定要使用到mybatis的映射文件-->
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--映射文件所有在目录-->
<!--包含目录下的.properties文件,.xml文件都会进行扫描-->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
3)开发代码
-- dao层
-- service层
-- 测试类
4)数据库表
5) 配置日志文件log4j.properties
log4j.rootLogger = debug,stdout,D,E
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3.代码的实现
3.1 dao层
1)创建账户类Account
/**
* dao层:账户的实体类
*/
public class Account {
private Integer id;
private String name;
private Integer money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
2)创建mybatis动态代理的接口AccountMapper
/**
* dao层:账户的动态接口
*/
public interface AccountMapper {
//1、查询账户列表信息
public List<Account> selectAllAccounts();
/*2、通过姓名模糊查询*/
public List<Account> selectAccountsByName(String name);
/*3、添加账户信息*/
public void insertAccount(Account account);
/*4、删除用户信息*/
public void deleteAccount(Integer id);
/*5、汇款的更能:汇款,收款*/
/*转账*/
public void outMoney(String fromName, Integer money);
/*收款*/
public void inMoney(String toName, Integer money);
}
3)创建mybatis动态代理的映射文件AccountMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace的值就是动态接口的全限定名称-->
<mapper namespace="com.suke.mapper.AccountMapper">
<!--执行查询所有账户信息的sql语句-->
<select id="selectAllAccounts" resultType="com.suke.pojo.Account">
select id, name, money
from account;
</select>
<!--根据账户名称查询账户信息列表的sql语句-->
<select id="selectAccountsByName" parameterType="string" resultType="account">
select id, name, money
from account
where name like "%" #{name} "%";
</select>
<!--添加一个账户信息-->
<insert id="insertAccount" parameterType="account">
insert into account(id, name, money)
values (#{id}, #{name}, #{money});
</insert>
<!--根据id删除账户信息-->
<delete id="deleteAccount" parameterType="int">
delete
from account
where id = #{id};
</delete>
<!--转款和收款的sql语句-->
<!--转账-->
<update id="outMoney">
update account
set money = money - #{arg1}
where name = #{arg0};
</update>
<!--收款-->
<update id="inMoney">
update account
set money = money + #{arg1}
where name = #{arg0};
</update>
</mapper>
4)创建mybatis的主配置文件SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--保持空数据即可:交给Spring容器管理-->
</configuration>
5)dao层的jdbc属性文件db.properties
#数据库的参数设置
jdbc_driver=com.mysql.cj.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/myjdbc?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
jdbc_user=root
jdbc_password=root
#连接池的参数设置
#初始化连接数
initialSize=10
#最小空闲数
mindle=10
#最大连接池
maxActive=30
#最大的等待时间
maxWatit=6000
6)dao层的Spring容器文件applicationContext-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--加载jdbc的属性文件-->
<context:property-placeholder location="classpath:jdbc/db.properties"/>
<!--配置mysql数据库参数:使用的是Druid技术-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close" lazy-init="false">
<!--获取mysql的参数-->
<property name="driverClassName" value="${jdbc_driver}"/>
<property name="url" value="${jdbc_url}"/>
<property name="username" value="${jdbc_user}"/>
<property name="password" value="${jdbc_password}"/>
<!--获取连接池中参数-->
<property name="initialSize" value="${initialSize}"/>
<property name="minIdle" value="${mindle}"/>
<property name="maxActive" value="${maxActive}"/>
<property name="maxWait" value="${maxWatit}"/>
</bean>
<!--管理mybatis的工厂类对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--加载数据源-->
<property name="dataSource" ref="dataSource"/>
<!--加载mybatis的主配置文件-->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>
<!--配置别名包扫描器-->
<property name="typeAliasesPackage" value="com.suke.pojo"/>
</bean>
<!--Spring配置mybatis的动态代理的过程-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--配置映射文件的包扫描器-->
<property name="basePackage" value="com.suke.mapper"/>
</bean>
<!--构建一个Account的对象-->
<!-- <bean id="account" class="com.suke.pojo.Account">
<property name="name" value="吕布"/>
<property name="money" value="10000"/>
</bean>-->
</beans>
3.2 service层
1)业务的接口AccountService
/**
* Service层:业务的方法的接口
*/
public interface AccountService {
//1、查询所有账户信息的方法
public List<Account> findAllAccounts();
//2、根据名声牧户查询账户信息列表
public List<Account> findAccountsByName(String name);
//3、添加一个账户信息的业务方法
public void addAccount(Account account);
//4、根据账户的id删除账户信息的业务方法
public void deleteAccount(Integer id);
//5、转账功能的业务方法
public void transfer(String fromName, String toName, Integer money);
}
2)业务的实现类AccountServiceImpl
/**
* Service层:业务的方法的接口实现类
*/
@Service
public class AccountServiceImpl implements AccountService {
/*注入dao层对象*/
@Autowired
private AccountMapper accountMapper;
/**
* 实现查询所有账户信息的方法
* @return
*/
@Override
public List<Account> findAllAccounts() {
return accountMapper.selectAllAccounts();
}
/**
* 实现通过名称查询账户信息列表的业务方法
* @param name
* @return
*/
@Override
public List<Account> findAccountsByName(String name) {
return accountMapper.selectAccountsByName(name);
}
/**
* 实现添加一个账户信息的业务方法
* @param account
*/
@Override
public void addAccount(Account account) {
accountMapper.insertAccount(account);
}
/**
* 实现根据账户的id删除账户信息的业务方法
* @param id
*/
@Override
public void deleteAccount(Integer id) {
accountMapper.deleteAccount(id);
}
/**
* 实现转账功能的业务方法
* @param fromName:汇款人
* @param toName:收款人
* @param money:交易的金额
*/
@Override
public void transfer(String fromName, String toName, Integer money) {
accountMapper.outMoney(fromName, money);
/*故意设置异常*/
int num = 100/0;
accountMapper.inMoney(toName, money);
}
}
3)业务层的Spring容器文件applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--添加Service层的注解的包扫描器-->
<context:component-scan base-package="com.suke.service"/>
</beans>
4)dao层的Spring容器文件 与 业务层的Spring容器文件整合文件total.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<import resource="classpath:spring/applicationContext-dao.xml"/>
<import resource="classpath:spring/applicationContext-service.xml"/>-->
<import resource="classpath:spring/applicationContext-*.xml"/>
</beans>
3.3 测试类
/**
* 测试类
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/total.xml")
public class AccountTest {
//注入Service层对象
@Autowired
private AccountService accountService;
/* @Test
public void testFindAllAccounts(){
//1、创建Spring的容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/total.xml");
AccountService accountService = applicationContext.getBean(AccountService.class);
List<Account> accountList = accountService.findAllAccounts();
for (Account account : accountList) {
System.out.println(account);
}
}*/
/**
* 测试查询所有账户列表信息
*/
@Test
public void testFindAllAccounts() {
List<Account> accountList = accountService.findAllAccounts();
for (Account account : accountList) {
System.out.println(account);
}
}
/**
* 测试通过名称模糊查询账户列表信息
*/
@Test
public void testFindAccountsByName() {
List<Account> accountList = accountService.findAccountsByName("李");
for (Account account : accountList) {
System.out.println(account);
}
}
/**
* 测试添加一条账户信息
*/
@Test
public void testAddAccount() {
//获取一个Account对象
Account account = new Account();
account.setId(4);
account.setName("貂蝉");
account.setMoney(1000);
accountService.addAccount(account);
}
/**
* 测试通过id删除一条账户信息
*/
@Test
public void testDeleteAccount() {
accountService.deleteAccount(3);
}
/**
* 测试通过业务转账的功能
*/
@Test
public void testTransferAccount() {
accountService.transfer("吕布", "貂蝉", 200);
}
}