Spring整合Mybatis之注解方式
我有一篇博客详细写了我自己使用xml的方法Spring整合MyBatis,现在我就把核心配置文件中的每个bean的配置使用注解的方式实现
注解整合MyBatis分析
注解整合MyBatis分析
⚫ 业务类使用注解形式声明bean,属性采用注解注入
⚫ 建立独立的配置管理类,分类管理外部资源,根据功能进行分类,并提供对应的方法获取bean
⚫ 使用注解形式启动bean扫描,加载所有注解配置的资源(bean)
⚫ 使用AnnotationConfigApplicationContext对象加载所有的启动配置类,内部使用导入方式进行关联
注解整合MyBatis步骤
- 修改mybatis外部配置文件格式为注解格式
- 业务类使用@Component声明bean,使用@Autowired注入对象
- 建立配置文件JDBCConfig与MyBatisConfig类,并将其导入到核心配置类SpringConfig
- 开启注解扫描
- 使用AnnotationConfigApplicationContext对象加载配置项
项目目录结构
项目准备
数据库mysql
/*
SQLyog Ultimate v12.14 (64 bit)
MySQL - 5.6.45 : Database - test
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test`;
/*Table structure for table `account` */
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`money` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
/*Data for the table `account` */
insert into `account`(`id`,`name`,`money`) values
(1,'小付',800),
(2,'小花',1200),
(3,'小张',324),
(4,'小红花',1434),
(5,'笑小',1314),
(6,'你铪',6575),
(8,'花花',333);
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fs</groupId>
<artifactId>day02_spring_annotation_MyBatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
<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.47</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
代码演示(代码中有详细解释)
SpringConfig
package com.fs.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
//表示这个类是一个spring的配置类,并将其存入到ioc容器中
@Configuration
/*开启扫描注解的那些包
<!-- 启动spring扫描注解的包,只扫描spring的注解-->
<context:component-scan base-package="com.fs"/>
*/
@ComponentScan("com.fs")
//引入其他的配置类
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}
JdbcConfig
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.93.132:3306/test
jdbc.username=root
jdbc.password=root
我们将下面的配置转变成spring的配置类,通过注解实现
<!-- 引入properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 整合druid,把DruidDataSource交给spring管理-->
<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>
创建一个JdbcConfig
package com.fs.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
/*
<!-- 引入properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
*/
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
//@Value("${Key}")
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/*
<!-- 整合druid,把DruidDataSource交给spring管理-->
<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>
*/
//将返回的DruidDataSource交给ioc管理
@Bean
public DruidDataSource getDruidDataSource(){
//创建DruidDataSource
DruidDataSource druidDataSource = new DruidDataSource();
//给属性赋值,这个是上面从配置文件中依耐注入给属性的
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
//返回DruidDataSource,然后交给ioc管理
return druidDataSource;
}
}
MybatisConfig
将下面的配置文件中的配置转变成java配置类,通过注解实现
<!-- 整合MyBatis-->
<!-- 配置MyBatis的会话工厂类 mybatis.spring 下的SqlSessionFactoryBean
配置的sqlSessionFactory得到SqlSession,然后MyBatis从spring中拿到SqlSession.getMapper()去动态代理dao-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 给MyBatis配置链接池,依耐注入-->
<property name="dataSource" ref="dataSource"/>
<!-- 配置别名扫描的包,被扫描的包下的类起的别名就是类名首字母小写,用于mapper.xml文件中使用-->
<property name="typeAliasesPackage" value="com.fs.pojo"/>
</bean>
<!--配置MyBatis扫描dao的包,让MyBatis动态代理生成这个dao的实现类,并交给ioc管理
mybatis-spring这个包下MapperScannerConfigurer提供了spring于MyBatis的整合-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 告诉MyBatis我dao在哪里.然后MyBatis将这个dao实现,然后给spring管理-->
<property name="basePackage" value="com.fs.dao"/>
</bean>
创建一个MybatisConfig
package com.fs.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MybatisConfig {
/*
<!-- 配置MyBatis的会话工厂类 mybatis.spring 下的SqlSessionFactoryBean
配置的sqlSessionFactory得到SqlSession,然后MyBatis从spring中拿到SqlSession.getMapper()去动态代理dao-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 给MyBatis配置链接池,依耐注入-->
<property name="dataSource" ref="dataSource"/>
<!-- 配置别名扫描的包,被扫描的包下的类起的别名就是类名首字母小写,用于mapper.xml文件中使用-->
<property name="typeAliasesPackage" value="com.fs.pojo"/>
</bean>
*/
@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){
//创建sql会话工厂类 //这里@Autowired也是从ioc拿DataSource
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//从ioc容器中取出jdbcConfig中配置的druidDatasource
sqlSessionFactoryBean.setDataSource(dataSource);
//配置起别名
sqlSessionFactoryBean.setTypeAliasesPackage("com.fs.pojo");
return sqlSessionFactoryBean;
}
/*
<!--配置MyBatis扫描dao的包,让MyBatis动态代理生成这个dao的实现类,并交给ioc管理
mybatis-spring这个包下MapperScannerConfigurer提供了spring于MyBatis的整合-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 告诉MyBatis我dao在哪里.然后MyBatis将这个dao实现,然后给spring管理-->
<property name="basePackage" value="com.fs.dao"/>
</bean>
*/
//创建MyBatis动态代理扫描类
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer(){
//创建映扫描配置类
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置动态代理扫描的dao的包
mapperScannerConfigurer.setBasePackage("com.fs.dao");
//交给spring管理
return mapperScannerConfigurer;
}
}
Dao Service接口
AccountDao
package com.fs.dao;
import com.fs.pojo.Account;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface AccountDao {
@Select("select * from account")
List<Account> findAll();//查询所有
}
AccountService
package com.fs.service;
import com.fs.pojo.Account;
import java.util.List;
public interface AccountService {
List<Account> findAll();
}
AccountServiceImpl
将下面的配置文件中的配置信息,通过注解的方法交给spring管理
<!-- 把业务类 AccountServiceImpl 交给ioc管理 -->
<bean id="accountServiceImpl" class="com.fs.service.impl.AccountServiceImpl">
<!-- 依耐注入dao,这个dao被MyBatis动态代理实现后被spring存放在ioc容器中-->
<property name="accountDao" ref="accountDao"/>
</bean>
AccountServiceImpl
package com.fs.service.impl;
import com.fs.dao.AccountDao;
import com.fs.pojo.Account;
import com.fs.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/*
<!-- 把业务类 AccountServiceImpl 交给ioc管理 -->
<bean id="accountServiceImpl" class="com.fs.service.impl.AccountServiceImpl">
<!-- 依耐注入dao,这个dao被MyBatis动态代理实现后被spring存放在ioc容器中-->
<property name="accountDao" ref="accountDao"/>
</bean>
*/
@Service
public class AccountServiceImpl implements AccountService {
//从ioc获取MyBatis动态代理的accountDao实现类
@Autowired
private AccountDao accountDao;
//提供DI依耐注入的set方法
// public void setAccountDao(AccountDao accountDao) {
// this.accountDao = accountDao;
// }
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
}
测试整合代码(注解整合Junit)
注意:
◆ 从Spring5.0以后,要求Junit的版本必须是4.12及以上
◆ Junit仅用于单元测试,不能将Junit的测试类配置成spring的bean,否则该配置将会被打包进入工
程中
测试代码
package com.fs.service;
import com.fs.config.SpringConfig;
import com.fs.pojo.Account;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//设定加载的spring的配置类或者文件
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
//从spring容器中获取AccountService的实现类
@Autowired
private AccountService accountService;
@Test
public void findAll() {
//根据配置文件获取到ioc容器
//ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
//从ioc容器中拿到业务层类
//AccountService bean = applicationContext.getBean(AccountService.class);
//调用查询方法
List<Account> all = accountService.findAll();
//输出一下
System.out.println(all);
}
}
测试结果
说明整合成功: