前言

还记得之前我们写接口也是基于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. Notes : <Hands-on ML with Sklearn & TF> Chapter 7

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  2. 使用pdf.js预览实现读取服务器外部文件

    不知道大家使用百度网盘的文件预览功能,f12看过控制台没有. 发现百度网盘使用的预览文件功能全是基于开源pdf .js的 接下来正题,我们在使用pdf.js默认是读取发布容器内部的文件,读取外部的文件 ...

  3. python之路(十)-正则表达式

    re模块用于对python的正则表达式的操作. 字符: . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 \s 匹配任意的空白符 \d 匹配数字 \b 匹配单词的开始或结束 ^ 匹配 ...

  4. Think twice before starting the adventure

    杂文一篇. 1. 取名字真心是一件特别困难的事情.这位独立开发者花了将近两天的时间,给他的私人项目取了个名字:这篇博客<为何我不鸟你的开源项目>里显然还忽视了一个原因,就是名字取得太烂以至 ...

  5. 解决Eclipse中无法直接使用Base64Encoder的问题(转载)

    资源出处:https://blog.csdn.net/u011514810/article/details/72725398 Base64的加密解密都是使用sun.misc包下的BASE64Encod ...

  6. java holdsLock()方法检测一个线程是否拥有锁

    http://blog.csdn.net/w410589502/article/details/54949506 java.lang.Thread中有一个方法叫holdsLock(),它返回true如 ...

  7. 两台Linux机器传送文件

    https://www.cnblogs.com/lianrenjujishou/p/5458206.html

  8. Python学习笔记-基础1

    一 初识Python python是一种面向对象.解释型的计算机程序语言.Python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特 ...

  9. Centos6.5安装中文支持和中文输入法---VIM编辑器中文支持

    Centos6.5安装中文支持和中文输入法 第一步:中文支持:    在shell命令下输入: # vi  /etc/sysconfig/i18n 然后修改LANG="en_US.UTF-8 ...

  10. 【阿里聚安全·安全周刊】Intel芯片级安全漏洞事件|macOS存在漏洞

    关键词:Intel漏洞丨mac OS漏洞丨三星漏洞丨安卓安全丨CPU漏洞丨phpMyAdmin漏洞丨iOS设备|安卓恶意软件检测|Burpsuite   本周资讯top3 [Intel漏洞]芯片级安全 ...