为什么MapperScannerConfigurer不配置sql获取sessionfactoryy属性也能插入数据

Spring Boot 实践折腾记(三):三板斧,Spring Boot下使用Mybatis
Spring Boot 实践折腾记(三):三板斧,Spring Boot下使用Mybatis
springboot
Spring MVC
你要搞清楚自己人生的剧本:不是你父母的续集,不是你子女的前传,更不是你朋友的外篇。对待生命你不妨大胆冒险一点,因为好歹你要失去它。——源自尼采
上面的金句是被转载很多的一句话,Spring Boot也有自己的舞台,只是这个舞台还没有大量展开。今天接着上一篇的内容开始正式的切入到Spring Boot,按照从Spring mvc里的xml配置导入使用到class类配置,最后使用starter的方法来实战,到最后,大家就能看到是怎么过渡到的了,还能体会到最后那快速的畅快感。
1、建立启动类
建包: com.hjf.boot.demo.boot_mybatis
首先建立StartApp启动程序类
import org.springframework.boot.SpringA
import org.springframework.boot.autoconfigure.SpringBootA
@SpringBootApplication
public class StartApp {
public static void main(String[] args) {
SpringApplication.run(StartApp.class,args);
1:用这个注解,就能实现自动扫描包和自动配置默认配置的功能,它包含了@ComponentScan和@EnableAutoConfiguration这两个注解,同时这个类自身也是一个配置类@Configuration,可以直接在这个类里添加@Bean来注入java bean,第一章用的注解组合实现的和这个注解功能是一致的,这也是Spring Boot官方推荐的配置方式,是不是觉得很简单,以前需要在xml里写自动扫描的bean,现在只需要一个注解就搞定,快速、快速、快速,重要的原则说三遍,这也是Spring Boot的目标。
2、建立演示用服务类
我们使用现在基本通用的设计模式来设计类,包含controller(我更喜欢叫api),dao,domain,service,每一个都只有一个类。
模型类:domain—&TestPOJO.class
public class TestPOJO {
private int
服务类:service—&TestServices.class
import com.hjf.boot.demo.boot_mybatis.dao.TestD
import com.hjf.boot.demo.boot_mybatis.domain.TestPOJO;
import org.springframework.beans.factory.annotation.A
import org.springframework.stereotype.S
import java.util.L
public class TestServices {
@Autowired
private TestDao testD
public String show(){
return "hello world!";
public List&TestPOJO& showDao(int age){
return testDao.get(age);
1:这里提供两个方法,一个只是简单返回字符串,另个从mysql数据库里去取出数据显示。
接口控制器类:api—&TestController.class
import com.hjf.boot.demo.boot_mybatis.services.TestS
import org.springframework.beans.factory.annotation.A
import org.springframework.web.bind.annotation.RequestM
import org.springframework.web.bind.annotation.RestC
@RestController
public class TestController {
@Autowired
private TestServices testS
@RequestMapping(value = "/show")
public String show(){
return testServices.show();
@RequestMapping(value = "/showDao")
public Object showDao(int age){
return testServices.showDao(age);
1:使用这个方法代表rest风格的控制器,这个是Spring MVC的特性。主要是方便不写@ResponseBody;
2:注入服务方法;
3:调用普通服务接口方法;
4:调用查询数据库接口方法。
文件结构配置完后,接下来我们开始配置链接数据库的dao接口和配置,这里就会有三种方法:
方法1:引用xml配置
在Spring Boot里其实是不推荐使用导入xml配置的,但不是说就不能导入xml,只能用starter,之前也看过有关的集成的文章,都是一笔带过,我还是那个感触,不能一篇文章就成功过的,反正我自己折腾了很久才成功。
第1步:添加pom依赖。这需要添加mybatis相关的驱动依赖和jdbc连接池的依赖。
第2步:建立文件applicationContext.xml。我们要在resources下新建applicationContext.xml并将上一章同名xml文件里的datasource和mybatis的配置放入这里(我们不用profile配置,直接使用datasource简单一点):
applicationContext.xml
id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close"&
name="driverClassName" value="${jdbc.driver}" /&
name="url" value="${jdbc.url}" /&
name="username" value="${jdbc.username}" /&
name="password" value="${jdbc.password}" /&
name="maxActive" value="10" /&
name="maxIdle" value="50" /&
name="minIdle" value="0" /&
name="defaultAutoCommit" value="false" /&
id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&
name="dataSource" ref="dataSource" /&
name="typeAliasesPackage" value="com.hjf.boot.api.domain" /&
name="mapperLocations" value="classpath:/mybatis/*Mapper.xml" /&
class="org.mybatis.spring.mapper.MapperScannerConfigurer"&
name="basePackage" value="com.hjf.boot.demo.boot_mybatis.domain" /&
name="annotationClass" value="com.hjf.boot.demo.boot_mybatis.dao.Mapper"/&
使用同样注入自定义@Mapper的方式来发现接口,并且使用xml的真实Mapper来执行sql,这里没有写propertites的读取,是因为Spring Boot会默认自动读取application.properties里的内容。
第3步:建立application.properties,并写入如下属性内容。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&amp
jdbc.username=test
jdbc.password=123456
jdbc.pool.minIdle=0
jdbc.pool.maxIdle=10
jdbc.pool.maxActive=50
第4步:在dao文件夹下新建dao接口和@Mapper注解类。
TestDao.class
import com.hjf.boot.demo.boot_mybatis.domain.TestPOJO;
import java.util.L
public interface TestDao {
List&TestPOJO& get(int age);
Mapper.class
import org.
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Component
public @interface Mapper {
String value() default "";
TestDaoMapper.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="com.hjf.boot.demo.boot_mybatis.dao.TestDao"&
id="Column_list"&
id="ListTest" type="TestPOJO" &
column="id" property="id" /&
column="name" property="name" /&
column="age" property="age" /&
id="get" parameterType="int" resultMap="ListTest"&
refid="Column_list" /&
WHERE age = #{age}
到此类已经建立完毕了,启动,然后报错!为什么呢?通过idea的上下文关联图可以看得比较明白:
这个图是生成的,其实用boot,可以不用在项目工程里加载spring的上下文的,这里是为了方便说明,我手动建立了spring的上下文,那什么启动会报错呢,这个跟Spring Boot的启动机制有关,boot在启动启动类以后,才会根据类文件间的依赖去加载spring的bean类,boot本身并不会自动去读取xml文件,所以boot是不知道我们在xml里注入的bean的,所以肯定找不到datasource和mybatis配置,所以,我们要在StartApp类里增加一个注解@@ImportResource,让boot主动加载我们的bean。
@ImportResource(locations = "classpath*:/applicationContext.xml")
这时启动还是会报错,因为boot本着自动配置的原则,会帮你去加载mybatias的自动配置类,但自动配置类又是用的包内自有的mapper,导致找不到包,这时我们排除一下自动配置:
@SpringBootApplication(exclude = MybatisAutoConfiguration.class)
启动,成功,测试数据成功。
方法2:使用class类配置
虽然我们能够使用导入xml的配置,但是还是显得有点麻烦,并且配置xml文件有一个很大的缺点:容易出现拼写错误。上一个例子中我自己写的类的位置很多时候检查不够充分,也因为写错两个字母,一直报类找不到,spring 从4.x开始推荐使用class配置的方式来配置bean,我刚开始其实还是挺不喜欢class的方式的,觉得,这就是写代码了配置了,有时想修改下配置变量也需要提交上线,岂不是太麻烦了。class有class的好处,保密性比配置文件好,但不如xml方便,具体使用看使用场景和个人习惯。我是觉得,小项目配置改动比较小的可以使用class方式,对于协作比较多的项目还是使用xml和配置的方式。接下来使用class的方法来配置dao。
第1步:建立配置类文件config。这里需要三个类文件:
DataSourceConfig —&datasource源配置
MyBatisConfig —&
配置sqlSessionFactory
MyBatisMapperScannerConfig —&
配置mapperScannerConfigurer
这里需要说明一下:最后一个配置因为依赖前两个,需要最后一个加载,否则会报错。
DataSourceConfig .class
import org.apache.tomcat.jdbc.pool.DataS
import org.springframework.context.annotation.B
import org.springframework.context.annotation.C
@Configuration
public class DataSourceConfig {
public DataSource dataSource(){
DataSource dataSource = new DataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8");
dataSource.setUsername("test");
dataSource.setPassword("123456");
return dataS
1:代表此类为配置类;
2:代表需要注入的bean;
3:使用代码的方式传入值到对象。
MyBatisConfig .class
import org.apache.ibatis.session.SqlSessionF
import org.apache.tomcat.jdbc.pool.DataS
import org.mybatis.spring.SqlSessionFactoryB
import org.mybatis.spring.SqlSessionT
import org.springframework.beans.factory.annotation.A
import org.springframework.context.annotation.B
import org.springframework.context.annotation.C
import org.springframework.core.io.support.PathMatchingResourcePatternR
import org.springframework.core.io.support.ResourcePatternR
import org.springframework.jdbc.datasource.DataSourceTransactionM
import org.springframework.transaction.PlatformTransactionM
import org.springframework.transaction.annotation.TransactionManagementC
@Configuration
public class MyBatisConfig implements TransactionManagementConfigurer {
@Autowired
DataSource dataS
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean() {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setTypeAliasesPackage("com.hjf.boot.demo.boot_mybatis.domain");
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:/mybatis/*Mapper.xml"));
return bean.getObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource);
1:实现TransactionManagementConfigurer接口,配置spring事务的管理;
2:注入datasource;
3:注入的名称指定,如果不指定,默认方法名为bean的名字,命名规则需要遵守spring命名规范;
4:跳过分页插件,需要使用的,自行去了解mybatis分页插件的内容。
MyBatisMapperScannerConfig
import com.hjf.boot.demo.boot_mybatis.dao.M
import org.mybatis.spring.mapper.MapperScannerC
import org.springframework.boot.autoconfigure.AutoConfigureA
import org.springframework.context.annotation.B
import org.springframework.context.annotation.C
@Configuration
@AutoConfigureAfter(MyBatisConfig.class)
public class MyBatisMapperScannerConfig {
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.hjf.boot.demo.boot_mybatis");
mapperScannerConfigurer.setAnnotationClass(Mapper.class);
return mapperScannerC
1 : 让此类在上一个类加载完毕后再加载,代码都是xml内容的转化,比较简单。
现在,我们来看一下上下文的依赖变化成什么样了,如下图:
这个图很好的说明了boot在建立配置的方式,和xml是有一定区别的,所以才需要注意配置类的加载顺序。
到此,方法2建立dao完毕,我们注释掉方法1里的@ImportResource和application.properties里的所有内容,启动,成功!测试数据成功!
方法3:使用starter配置
终于来到最简单的方法了,能够自己实践,然后读到这里的同学,是不是感觉到,xml反而比class的方式还麻烦呢,讲了这么多,也没有觉得Spring Boot有多方便呢,但是在前两个方法的过渡中,很多配置其实是逐渐减少了,比如web.xml,spring-mvc的serverlet配置文件,读取properties,是不是没有配置了,虽然mvc里的配置更自由,但boot也是加载了默认配置,适用于大多数场景,并且它同样提供了强大的mvc的配置和自定义的配置,后续章节会涉及到。现在,我们继续建立dao。
第1步:引入mybatis的starter的包。 Spring Boot将封装的一系列支持boot的应用的工程都叫做starter,我们这里引入mybatis对boot的支持的starter。如果是同一个的pom,要注释掉mybatis的依赖,starter会自动引入依赖包。
&org.mybatis.spring.boot&
&mybatis-spring-boot-starter&
第2步:配置properties。
spring.datasource.driver-class-name=com.mysql.jdbc.Driver //1
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=test
spring.datasource.password=123456
spring.datasource.max-active=10
spring.datasource.max-idle=5
spring.datasource.min-idle=0
mybatis.mapper-locations=classpath:/mybatis
1: spring.开头的是spring boot自动配置的属性开头,后面我们会讨论怎么自定义自己类型安全的配置项。
2: 这是mybatis配置的自动配置的属性。
第3步,新建dao。
import com.hjf.boot.demo.boot_mybatis.domain.TestPOJO;
import org.apache.ibatis.annotations.M
import java.util.L
public interface TestDao {
List&TestPOJO& get(int age);
1:这里的Mapper是Mybatis自己定义的注解。
到此,结束,启动,成功!测试成功!
到此,本章内容结束了,到方法3的时候,会不会觉得,这么简单?就这么简单,快速配置,快速启动,你只需要关注你的核心业务。三种方法各有优缺点,适用的场景也不相同。
上面提到的要排除自动配置,其实是因为我的demo里的pom引入了mybatis的starter,细心的同学可能已经发现,可以不用加exclude。
示例地址:
of 366 in chapter 2016
我的热门文章
即使是一小步也想与你分享JAVA Web开发 &&&&最新内容
JAVA Web开发 &&&&随机内容Spring和Mybatis整合时无法读取properties的处理方案
Properties代码 &
##数据库(mysql|mssql|oracle...)
environment=mysql &&
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/portal?useUnicode=true&characterEncoding=utf8
jdbc.user=root &&
jdbc.password=root &&
#初始化连接(根据实际访问量设置大小) &&
jdbc.initialSize=10&&
#最大空闲连接(根据实际访问量设置大小) &&
jdbc.maxIdle=50&&
#最小空闲连接(根据实际访问量设置大小) &&
jdbc.minIdle=10&&
#最大连接数量(根据实际访问量设置大小) &&
jdbc.maxActive=200&&
##数据库(mysql|mssql|oracle...)
environment=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/portal?useUnicode=true&characterEncoding=utf8
jdbc.user=root
jdbc.password=root
#初始化连接(根据实际访问量设置大小)
jdbc.initialSize=10
#最大空闲连接(根据实际访问量设置大小)
jdbc.maxIdle=50
#最小空闲连接(根据实际访问量设置大小)
jdbc.minIdle=10
#最大连接数量(根据实际访问量设置大小)
jdbc.maxActive=200
&Spring配置信息(截取部分)
&&/span&context:property-placeholder&location="classpath:config.properties"&/&&&
&&/span&bean&id="dataSource"&class="mons.dbcp.BasicDataSource"&destroy-method="close"&&&
&&&&&&/span&property&name="driverClassName"&value="${jdbc.driver}"/&&&
&&&&&&/span&property&name="url"&value="${jdbc.url}"/&&&
&&&&&&/span&property&name="username"&value="${jdbc.user}"/&&&
&&&&&&/span&property&name="password"&value="${jdbc.password}"/&&&
&&&&&&/span&property&name="initialSize"&value="${jdbc.initialSize}"/&&&
&&&&&&/span&property&name="maxIdle"&value="${jdbc.maxIdle}"/&&&
&&&&&&/span&property&name="minIdle"&value="${jdbc.minIdle}"/&&&
&&&&&&/span&property&name="maxActive"&value="${jdbc.maxActive}"/&&&
&&&&&&/span&property&name="removeAbandoned"&value="true"/&&&
&&&&&&/span&property&name="removeAbandonedTimeout"&value="120"/&&&
&&&&&&/span&property&name="maxWait"&value="3000"/&&&
&/&/span&bean&&&
&&/span&bean&id="sqlSessionFactory"&class="org.mybatis.spring.SqlSessionFactoryBean"&&&
&&&&&&/span&property&name="dataSource"&ref="dataSource"/&&&
&&&&&&/span&property&name="configLocation"&value="classpath:mybatis-config.xml"/&&&
&&&&&&&&&/span&property&name="mapperLocations"&value="classpath*:com.anly.portal.*.mapper/*Mapper.xml"&/&&
&/&/span&bean&&&
&&/span&bean&class="org.mybatis.spring.mapper.MapperScannerConfigurer"&&&
&&&&&&/span&property&name="basePackage"&value="com.anly.portal.*.mapper"/&&&
&&&&&&/span&property&name="sqlSessionFactory"&ref="sqlSessionFactory"/&&&
&/&/span&bean&&&
&此时,启动会报异常,${jdbc.driver}这样的表达式获取不到properties里面的值,因为MapperScannerConigurer实际是在解析加载bean定义阶段的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类,这个时候,PropertyPlaceholderConfigurer还没来得及替换定义中的变量,导致把表达式当作字符串复制了,解决的办法如下:
原理:使用sqlSessionFactoryBeanName注入,不会立即初始化sqlSessionFactory,
所以不会引发提前初始化问题,同时还应注意在配置org.mybatis.spring.SqlSessionFactoryBean
这个Bean时,id不能为sqlSessionFactory,如果为这样的话会导致MapperScannerConigurer在bean定义加载时,加载PropertyPlaceholderConfigurer还没来得及替换定义中的变量
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 sqlsessionfactory 的文章

 

随机推荐