前言

还记得之前我们写接口也是基于SpringMVC+MyBatis环境下,项目入手就需要N个配置文件,N个步骤才能实现,不但繁琐,而且时间长了xml配置文件太多,难以维护。现在基于spring boot环境。3分钟就能编写一个基于MyBatis增删改查的demo。那么为什么这么神奇呢?

准备工作

1、环境依赖

  <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>

  

2、配置文件(applition.yml)

主要配置数据源(DataSource)和MyBatis。

spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.80.129:3306/test
username: root
password: 123456 mybatis:
type-aliases-package: com.zhangfei.entity
mapper-Locations: classpath:mybatis/*.xml

 

Example

1、程序入口

这里最关键的地方就是MapperScan注解,扫码Mapper接口所在地址。

@SpringBootApplication
@MapperScan(value = "com.zhangfei.dao")
public class DemoApplication { public static void main(String[] args){
SpringApplication.run(DemoApplication.class,args);
} }

2、Dao接口实现

也就是Mapper实现,放在resources/mybatis/*.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">
<mapper namespace="com.zhangfei.dao.StudentDao">
<select id="getStudentList" resultType="Student">
select * from student;
</select> <select id="getById" resultType="Student">
select * from student where id=#{id};
</select> <insert id="insert" parameterType="Student">
insert into student (name,age) values (#{name},#{age})
</insert> <update id="update" parameterType="Student">
update student set name=#{name},age=#{age} where id=#{id}
</update> <delete id="delete" parameterType="long">
delete from student where id=#{id}
</delete>
</mapper>

  OK,有了接口、有了接口实现,第一个增删改查就搞定了,就是这么简单,来看单元测试。 单元测试注意2.x环境下已经推荐使用SpringBootTest注解。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class DemoApplicationTest { @Autowired
StudentDao studentDao; @Test
public void test(){ List<Student> students=studentDao.getStudentList(); System.out.println("size:"+students.size()); Student student=studentDao.getById(1);
System.out.println(student.getId()+","+student.getName()); } @Test
public void test1(){
//测试insert
Student student=new Student();
student.setName("lisi");
student.setAge(30); int result=studentDao.insert(student);
} @Test
public void test2(){
//测试update
Student student=new Student();
student.setName("lisi222");
student.setAge(35);
student.setId(2); int result=studentDao.update(student);
} @Test
public void test3(){
//测试update
long id=3;
int result=studentDao.delete(id);
} }

  

 

总结:

还记得之前用SpringMVC+MyBatis开发接口应用时,基于spring托管mybatis时需要在xml中配置datasource、sqlsessionfactory、sqlsession。那么现在不需要自己亲力亲为了呢,那么这就是springboot、mybatis自动配置的工作所在。 在org.mybatis.spring.boot.configure包下有两个关键类:

MyBatisProperties

      这个类主要是读取你在applition.yml中配置的mybatis的基本属性用来配置数据源使用

@ConfigurationProperties(
prefix = "mybatis"
)
public class MybatisProperties {
public static final String MYBATIS_PREFIX = "mybatis";
private String configLocation;
private String[] mapperLocations;
private String typeAliasesPackage;
private String typeHandlersPackage;
private boolean checkConfigLocation = false;
private ExecutorType executorType;
private Properties configurationProperties;
@NestedConfigurationProperty
private Configuration configuration; public MybatisProperties() {
} public String getConfigLocation() {
return this.configLocation;
} public void setConfigLocation(String configLocation) {
this.configLocation = configLocation;
} /** @deprecated */
@Deprecated
public String getConfig() {
return this.configLocation;
} /** @deprecated */
@Deprecated
public void setConfig(String config) {
this.configLocation = config;
} public String[] getMapperLocations() {
return this.mapperLocations;
} public void setMapperLocations(String[] mapperLocations) {
this.mapperLocations = mapperLocations;
} public String getTypeHandlersPackage() {
return this.typeHandlersPackage;
} public void setTypeHandlersPackage(String typeHandlersPackage) {
this.typeHandlersPackage = typeHandlersPackage;
} public String getTypeAliasesPackage() {
return this.typeAliasesPackage;
} public void setTypeAliasesPackage(String typeAliasesPackage) {
this.typeAliasesPackage = typeAliasesPackage;
} public boolean isCheckConfigLocation() {
return this.checkConfigLocation;
} public void setCheckConfigLocation(boolean checkConfigLocation) {
this.checkConfigLocation = checkConfigLocation;
} public ExecutorType getExecutorType() {
return this.executorType;
} public void setExecutorType(ExecutorType executorType) {
this.executorType = executorType;
} public Properties getConfigurationProperties() {
return this.configurationProperties;
} public void setConfigurationProperties(Properties configurationProperties) {
this.configurationProperties = configurationProperties;
} public Configuration getConfiguration() {
return this.configuration;
} public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
} public Resource[] resolveMapperLocations() {
PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
ArrayList resources = new ArrayList();
if(this.mapperLocations != null) {
String[] var3 = this.mapperLocations;
int var4 = var3.length; for(int var5 = 0; var5 < var4; ++var5) {
String mapperLocation = var3[var5]; try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException var8) {
;
}
}
} return (Resource[])resources.toArray(new Resource[resources.size()]);
}
}

  

MyBatisAutoConfiguration

@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnBean({DataSource.class})
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class MybatisAutoConfiguration {
private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);
private final MybatisProperties properties;
private final Interceptor[] interceptors;
private final ResourceLoader resourceLoader;
private final DatabaseIdProvider databaseIdProvider;
private final List<ConfigurationCustomizer> configurationCustomizers; public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
this.properties = properties;
this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
this.resourceLoader = resourceLoader;
this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();
} @PostConstruct
public void checkConfigFileExists() {
if(this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");
} } @Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
if(StringUtils.hasText(this.properties.getConfigLocation())) {
factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
} org.apache.ibatis.session.Configuration configuration = this.properties.getConfiguration();
if(configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
configuration = new org.apache.ibatis.session.Configuration();
} if(configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
Iterator var4 = this.configurationCustomizers.iterator(); while(var4.hasNext()) {
ConfigurationCustomizer customizer = (ConfigurationCustomizer)var4.next();
customizer.customize(configuration);
}
} factory.setConfiguration(configuration);
if(this.properties.getConfigurationProperties() != null) {
factory.setConfigurationProperties(this.properties.getConfigurationProperties());
} if(!ObjectUtils.isEmpty(this.interceptors)) {
factory.setPlugins(this.interceptors);
} if(this.databaseIdProvider != null) {
factory.setDatabaseIdProvider(this.databaseIdProvider);
} if(StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
} if(StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
} if(!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
factory.setMapperLocations(this.properties.resolveMapperLocations());
} return factory.getObject();
} @Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
ExecutorType executorType = this.properties.getExecutorType();
return executorType != null?new SqlSessionTemplate(sqlSessionFactory, executorType):new SqlSessionTemplate(sqlSessionFactory);
} @Configuration
@Import({MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class})
@ConditionalOnMissingBean({MapperFactoryBean.class})
public static class MapperScannerRegistrarNotFoundConfiguration {
public MapperScannerRegistrarNotFoundConfiguration() {
} @PostConstruct
public void afterPropertiesSet() {
MybatisAutoConfiguration.logger.debug("No {} found.", MapperFactoryBean.class.getName());
}
} public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
private BeanFactory beanFactory;
private ResourceLoader resourceLoader; public AutoConfiguredMapperScannerRegistrar() {
} public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
MybatisAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); try {
if(this.resourceLoader != null) {
scanner.setResourceLoader(this.resourceLoader);
} List ex = AutoConfigurationPackages.get(this.beanFactory);
if(MybatisAutoConfiguration.logger.isDebugEnabled()) {
Iterator var5 = ex.iterator(); while(var5.hasNext()) {
String pkg = (String)var5.next();
MybatisAutoConfiguration.logger.debug("Using auto-configuration base package \'{}\'", pkg);
}
} scanner.setAnnotationClass(Mapper.class);
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(ex));
} catch (IllegalStateException var7) {
MybatisAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", var7);
} } public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
} public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
}
}

  这个类里的内容是不是看起来会面熟很多,看到了熟悉的SqlSessionFactory、SqlSessionTemplate。SpringBoot在运行的时候会进行自动配置,在mybatis-spring-boot-autoconfigure里找到spring.factories。然后找到MyBatisAutoConfiguration。其中checkConfigFileExists 使用了PostContruct注解,在初始化时加载mybatis配置文件创建SqlSessionFactory。sqlSessionFactory、sqlSessionTemplate两个方法都添加了ConditionalOnMissingBean注解,在bean不存在时分别创建SqlSessionFactory和SqlSessionTemplate。

在回过头来看程序入口还有一个MapperScan注解,主程序运行时去扫描mapper接口实现类,为其注入sqlsessionfactory和sqlsession。OK。这就是spring boot和mybatis为我们所提供的基础功能。

spring boot(三) 集成mybatis的更多相关文章

  1. 小代学Spring Boot之集成MyBatis

    想要获取更多文章可以访问我的博客 - 代码无止境. 上一篇小代同学在Spring Boot项目中配置了数据源,但是通常来讲我们访问数据库都会通过一个ORM框架,很少会直接使用JDBC来执行数据库操作的 ...

  2. Spring Boot入门——集成Mybatis

    步骤: 1.新建maven项目 2.在pom.xml文件中引入相关依赖 <!-- mysql依赖 --> <dependency> <groupId>mysql&l ...

  3. Spring Boot:集成Druid数据源

    综合概述 数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个:释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据 ...

  4. spring boot 2使用Mybatis多表关联查询

    模拟业务关系:一个用户user有对应的一个公司company,每个用户有多个账户account. spring boot 2的环境搭建见上文:spring boot 2整合mybatis 一.mysq ...

  5. Spring Boot:实现MyBatis动态数据源

    综合概述 在很多具体应用场景中,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动态数据 ...

  6. Spring Boot:实现MyBatis动态创建表

    综合概述 在有些应用场景中,我们会有需要动态创建和操作表的需求.比如因为单表数据存储量太大而采取分表存储的情况,又或者是按日期生成日志表存储系统日志等等.这个时候就需要我们动态的生成和操作数据库表了. ...

  7. Spring Boot Redis 集成配置(转)

    Spring Boot Redis 集成配置 .embody{ padding:10px 10px 10px; margin:0 -20px; border-bottom:solid 1px #ede ...

  8. spring boot 2 集成JWT实现api接口认证

    JSON Web Token(JWT)是目前流行的跨域身份验证解决方案.官网:https://jwt.io/本文使用spring boot 2 集成JWT实现api接口验证. 一.JWT的数据结构 J ...

  9. Spring Boot中使用MyBatis注解配置详解(1)

    之前在Spring Boot中整合MyBatis时,采用了注解的配置方式,相信很多人还是比较喜欢这种优雅的方式的,也收到不少读者朋友的反馈和问题,主要集中于针对各种场景下注解如何使用,下面就对几种常见 ...

随机推荐

  1. kubernetes CRD学习笔记

    前言 最近在极客时间订阅了kubernetes的专栏,这篇文章是想记录一下自己学习CRD(custom resource definition)的过程,加深一下记忆. 准备工作 首先安装一下我们用的g ...

  2. mysql的ACID的理解

    这是在网上copy下来的ACID的概念,可以直接跳过看后面: 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开 ...

  3. IntelliJ IDEA 和谐地址及快捷键

    转载:http://my.oschina.NET/dyyweb/blog/494504 http://blog.csdn.net/tanlon_0308/article/details/5085473 ...

  4. 复习java基础

    十进制转换成二进制:     方法:整除法,计数方式从右往左,二进制中非0即1.例子如下: 计数方式是从右往左进行,然后填写数字的顺序是余数优先 二进制转换成十进制: 方法:乘二法,例如二进制数字为: ...

  5. 【.NET Core项目实战-统一认证平台】第二章网关篇-定制Ocelot来满足需求

    [.NET Core项目实战-统一认证平台]开篇及目录索引 这篇文章,我们将从Ocelot的中间件源码分析,目前Ocelot已经实现那些功能,还有那些功能在我们实际项目中暂时还未实现,如果我们要使用这 ...

  6. Node.js的安装以及npm的基础使用

    索引: Node.js的安装以及Node.js的模块管理Node.js开发环境搭建以及对ES6的支持Node.js构建Vue.js项目Vue.js单文件组件的开发基于Vue.js的UI组件(Eleme ...

  7. Windows 10 IoT Core 17133 for Insider 版本更新

    今天,微软发布了Windows 10 IoT Core 17133 for Insider 版本更新,本次更新只修正了一些Bug,没有发布新的特性.用户可以登录Windows Device Porta ...

  8. Javascript高级编程学习笔记(35)—— DOM(1)节点

    DOM JS由三部分组成 1.BOM 2.DOM 3.ECMAScript ES和BOM在前面的文章已经介绍过了 今天开始JS组成的最后一部分DOM(文档对象模型) 我们知道,JS中的这三个部分实际上 ...

  9. ScrollView嵌套子View的getDrawingCache为空的解决方法

    ScrollView嵌套子View的getDrawingCache为空的解决方法 问题 将组件的显示布局改为可以滚动的,然后用ScrollView作为了View的父类,发现View的getDrawin ...

  10. 封装一个简易版的ajax操作对象

    /** * 发送ajax请求 * @type {Object} * 使用方法如下: * $ajax.request( * method: "post", //请求方式 * url: ...