Spring学习笔记(六):MyBatis集成

1 概述

MyBaits是一个著名的持久层框架,本文首先介绍了MyBatis的简单使用,接着与Spring进行整合,最后简单地使用了Generator去自动生成代码。

2 MyBatis简介

MyBatis本来是Apache的一个开源项目——iBatis,2010年由Apaceh Software Foundation迁移到了Google Code,并改名为MyBatis

MyBatis是一个基于Java的持久层框架,提供的持久层框架包括SQL MapsData Access Objects,使用简单的XML或者注解用于配置映射,将接口和POJO映射成数据库中的记录,是一个小巧、方便、高效、简单、直接、半自动化的持久层框架。

3 工作原理

上图:

在这里插入图片描述

  • 读取配置文件:mybatis-config.xml是全局MyBatis配置文件,配置了MyBatis运行环境信息
  • 加载映射文件:也就是SQL映射文件,配置了操作数据库的SQL语句
  • 构造会话工厂:通过配置文件构造会话工厂SqlSessionFactory
  • 创建会话对象:由上一步的会话工厂创建会话对象SqlSession
  • 获取MapperStatement:通过用户调用的apiStatement ID获取MapperStatement对象
  • 输入参数映射:通过ExecutorMapperStatement进行解析,将各种Java基本类型转化为SQL操作语句中的类型
  • 输出结果映射:JDBC执行SQL后,借助MapperStatement的映射关系将返回结果转化为Java基本类型并返回

4 MyBatis示例

首先先来看一下纯MyBaits的示例,没有整合Spring,一个简单的Maven工程,项目结构如下:

在这里插入图片描述

4.1 依赖

1<dependency> 2 <groupId>org.mybatis</groupId> 3 <artifactId>mybatis</artifactId> 4 <version>3.5.5</version> 5</dependency> 6 7<dependency> 8 <groupId>org.projectlombok</groupId> 9 <artifactId>lombok</artifactId> 10 <version>1.18.12</version> 11</dependency> 12 13<!--驱动用的是MySQL,版本请自行修改--> 14<dependency> 15 <groupId>mysql</groupId> 16 <artifactId>mysql-connector-java</artifactId> 17 <version>8.0.21</version> 18</dependency>

Gradle

1compile group: 'org.mybatis', name: 'mybatis', version: '3.5.5' 2compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21'

4.2 实体类

1@Setter 2@Getter 3@Builder 4public class User { 5 private Integer id; 6 private String name; 7 8 @Override 9 public String toString() { 10 return "id:"+id+"\tname:"+name; 11 } 12}

4.3 映射文件

新建一个叫UserMapper.xml的映射文件:

1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3<mapper namespace="UserMapper"> 4 <select id="selectById" parameterType="Integer" resultType="pers.entity.User"> 5 select * from user where id=#{id} 6 </select> 7 <select id="selectAll" resultType="pers.entity.User"> 8 select * from user 9 </select> 10 11 <insert id="insert" parameterType="pers.entity.User"> 12 INSERT INTO `user` (`id`,`name`) 13 VALUES (#{id},#{name}) 14 </insert> 15 16 <update id="update" parameterType="pers.entity.User"> 17 UPDATE `user` set `name`=#{name} where id=#{id} 18 </update> 19 20 <delete id="delete" parameterType="Integer"> 21 DELETE FROM `user` WHERE `id` = #{id} 22 </delete> 23</mapper>

映射文件是一个XML文件,根元素为<mapper>,需要注意其中的namespace属性,调用的时候通过该namespace调用。其中的子元素表示SQL语句:

  • <select>:查询,id指定了这条语句的id号,调用时通过namespace.id的方式调用,比如该条select需要通过UserMapper.selectById调用,parameterType指定参数类型,这里是一个Integer的参数,resultType指定返回类型,实体类
  • <insert>/<update>/<delete>:对应的插入/修改/删除语句
  • 关于占位符:#{}表示是占位符,相当于传统JDBC中的?#{id}表示该占位符等待接收的参数名称为id

4.4 配置文件

MyBatis的配置文件,叫mybatis-config.xml

1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3<configuration> 4 <environments default="development"> 5 <environment id="development"> 6 <transactionManager type="JDBC" /> 7 <dataSource type="POOLED"> 8 <property name="driver" value="com.mysql.cj.jdbc.Driver"/> 9 <property name="url" value="jdbc:mysql://localhost:3306/test"/> 10 <property name="username" value="test"/> 11 <property name="password" value="test"/> 12 </dataSource> 13 </environment> 14 </environments> 15 16 <mappers> 17 <mapper resource="mapper/UserMapper.xml" /> 18 </mappers> 19</configuration>

指定了数据库的一些连接属性还有mapper的位置。

4.5 测试

1public class Main { 2 public static void main(String[] args) { 3 try 4 { 5 InputStream inputStream = Resources.getResourceAsStream("config/mybatis-config.xml"); 6 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); 7 SqlSession session = factory.openSession(); 8 User user = session.selectOne("UserMapper.selectById",1); 9 System.out.println(user); 10 User user1 = User.builder().name("test").build(); 11 session.insert("UserMapper.insert",user1); 12 user1.setName("222"); 13 session.update("UserMapper.update",user1); 14 List<User> list = session.selectList("UserMapper.selectAll"); 15 list.forEach(System.out::println); 16 session.delete("UserMapper.delete",1); 17 session.commit(); 18 session.close(); 19 } 20 catch (Exception e) 21 { 22 e.printStackTrace(); 23 } 24 } 25}

主要流程如下:

  • 读取配置文件:根据org.apache.ibatis.io.Resources读取配置文件mybatis-config.xml,请注意配置文件的位置正确,这里的配置文件都放在resources下,mybatis-config.xml放在其中的config
  • 构建Session:根据配置文件构建SqlSessionFactory后,通过openSession创建Session
  • 业务操作:通过sessionselectOne/insert/update等进行业务操作,这类操作带两个参数,第一个参数是String,表示配置文件中的SQL语句,采用namespace.id的形式,比如这里的UserMapper.xml中声明namespaceUserMapper,其中带有一条idselectByIdselect语句,因此调用时使用UserMapper.selectById的形式,第二个参数是一个Object,表示要传递的参数,也就是绑定到配置文件中对应占位符的值
  • 提交与关闭:业务操作完成后提交事务并关闭session

示例测试结果:

在这里插入图片描述

5 Spring整合示例

上面的例子只是为了演示MyBatis的基本使用,没有整合Spring,这里的例子是把Spring整合进来,流程也大概差不多,项目结构如下:

在这里插入图片描述

5.1 依赖

分为5类JAR

  • MyBatis需要的JAR
  • Spring需要的JAR
  • MyBatisSpring整合的中间JAR
  • 数据库驱动JAR
  • 数据源JAR

完整依赖如下:

1<dependency> 2 <groupId>org.springframework</groupId> 3 <artifactId>spring-context</artifactId> 4 <version>5.2.9.RELEASE</version> 5</dependency> 6 7<dependency> 8 <groupId>org.springframework</groupId> 9 <artifactId>spring-core</artifactId> 10 <version>5.2.9.RELEASE</version> 11</dependency> 12 13<dependency> 14 <groupId>org.springframework</groupId> 15 <artifactId>spring-beans</artifactId> 16 <version>5.2.9.RELEASE</version> 17</dependency> 18 19<dependency> 20 <groupId>org.springframework</groupId> 21 <artifactId>spring-web</artifactId> 22 <version>5.2.9.RELEASE</version> 23</dependency> 24 25<dependency> 26 <groupId>org.projectlombok</groupId> 27 <artifactId>lombok</artifactId> 28 <version>1.18.12</version> 29</dependency> 30 31<dependency> 32 <groupId>org.springframework</groupId> 33 <artifactId>spring-jdbc</artifactId> 34 <version>5.2.9.RELEASE</version> 35</dependency> 36 37<dependency> 38 <groupId>mysql</groupId> 39 <artifactId>mysql-connector-java</artifactId> 40 <version>8.0.21</version> 41</dependency> 42 43<dependency> 44 <groupId>org.springframework</groupId> 45 <artifactId>spring-tx</artifactId> 46 <version>5.2.9.RELEASE</version> 47</dependency> 48 49<dependency> 50 <groupId>org.mybatis</groupId> 51 <artifactId>mybatis</artifactId> 52 <version>3.5.5</version> 53</dependency> 54 55<dependency> 56 <groupId>org.mybatis</groupId> 57 <artifactId>mybatis-spring</artifactId> 58 <version>2.0.5</version> 59</dependency> 60 61<dependency> 62 <groupId>org.apache.commons</groupId> 63 <artifactId>commons-dbcp2</artifactId> 64 <version>2.8.0</version> 65</dependency>

Gradle

1compile group: 'org.springframework', name: 'spring-beans', version: '5.2.9.RELEASE' 2compile group: 'org.springframework', name: 'spring-context', version: '5.2.9.RELEASE' 3compile group: 'org.springframework', name: 'spring-core', version: '5.2.9.RELEASE' 4compile group: 'org.springframework', name: 'spring-tx', version: '5.2.9.RELEASE' 5compile group: 'org.springframework', name: 'spring-jdbc', version: '5.2.9.RELEASE' 6compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21' 7compile group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.8.0' 8compile group: 'org.mybatis', name: 'mybatis', version: '3.5.5' 9compile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.5'

5.2 配置文件

配置文件分为三类:

  • MyBatis映射文件:编写mapper的地方,也就是业务需要的SQL语句
  • MyBatis全局配置文件:由于整合了Spring,数据源的配置放在了Spring的配置文件中,而只需要保留mapper的查找位置
  • Spring配置文件:配置数据源+事务管理+MyBaitssqlSssionFactory+组件扫描

5.2.1 MyBatis映射文件

与上面的例子差不多,只是修改了namespace包名.类名的形式:

1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3<mapper namespace="pers.dao.UserDao"> 4 <select id="selectById" parameterType="Integer" resultType="pers.entity.User"> 5 select * from user where id=#{id} 6 </select> 7 <select id="selectAll" resultType="pers.entity.User"> 8 select * from user 9 </select> 10 11 <insert id="insert" parameterType="pers.entity.User"> 12 INSERT INTO `user` (`id`,`name`) 13 VALUES (#{id},#{name}) 14 </insert> 15 16 <update id="update" parameterType="pers.entity.User"> 17 UPDATE `user` set `name`=#{name} where id=#{id} 18 </update> 19 20 <delete id="delete" parameterType="Integer"> 21 DELETE FROM `user` WHERE `id` = #{id} 22 </delete> 23</mapper>

namespace需要与对应包名的带有@Mapper的类配置一致。

5.2.2 MyBatis配置文件

1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3<configuration> 4 <mappers> 5 <mapper resource="mapper/UserMapper.xml" /> 6 </mappers> 7</configuration>

5.2.3 Spring配置文件

1<?xml version="1.0" encoding="utf-8" ?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/tx 9 http://www.springframework.org/schema/tx/spring-tx.xsd 10 http://www.springframework.org/schema/context 11 https://www.springframework.org/schema/context/spring-context.xsd" 12 > 13 14 <context:component-scan base-package="pers.dao"/> 15 <context:component-scan base-package="pers.service"/> 16 <!--数据源--> 17 <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> 18 <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> 19 <property name="url" value="jdbc:mysql://localhost:3306/test"/> 20 <property name="username" value="test"/> 21 <property name="password" value="test"/> 22 <!--最大连接数+最大空闲数+初始连接数--> 23 <property name="maxTotal" value="30"/> 24 <property name="maxIdle" value="10"/> 25 <property name="initialSize" value="5"/> 26 </bean> 27 28 <!--事务管理--> 29 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 30 <property name="dataSource" ref="dataSource"/> 31 </bean> 32 33 <!--开启事务注解--> 34 <tx:annotation-driven transaction-manager="txManager" /> 35 36 <!--创建SqlSessionFactory Bean--> 37 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 38 <property name="dataSource" ref="dataSource"/> 39 <property name="configLocation" value="classpath:config/mybatis-config.xml"/> 40 </bean> 41 42 <!--注解扫描,主要用于@Mapper,会扫描basePackge下的@Mapper注解的接口并自动装配为MyBatis的映射接口--> 43 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 44 <property name="basePackage" value="pers.dao"/> 45 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 46 </bean> 47</beans>

5.3 持久层

需要加上@Mapper注解,表示自动装配为MyBatis的映射接口,注意:

  • 映射文件中的namespace需要与包名.类名对应,比如这里的包为pers.dao,类名为UserDao,那么映射文件中的namespacepers.dao.UserDao

  • id需要与方法名对应,比如映射文件中的有一条select语句的idselectById,那么方法就需要命名为selectById,且参数类型需要对应一致

    @Repository @Mapper public interface UserDao { User selectById(Integer id); List<User> selectAll(); int insert(User user); int update(User user); int delete(Integer id); }

5.4 业务层

1@Service 2@Transactional 3@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 4public class MyBatisService { 5 private final UserDao dao; 6 7 public void test(){ 8 User user = dao.selectById(13); 9 System.out.println(user); 10 dao.insert(User.builder().name("333").build()); 11 dao.update(User.builder().name("88888").id(13).build()); 12 dao.selectAll().forEach(System.out::println); 13 dao.delete(12); 14 dao.selectAll().forEach(System.out::println); 15 } 16}

注入UserDao后进行简单的测试,结果如下:

在这里插入图片描述

6 自动生成代码

相信很多程序员也讨厌写又长又麻烦的XML配置文件,因此,MyBatis也提供了一个生成器插件,可以直接从表中生成实体类、dao接口以及映射文件,可以省去很多操作。

步骤如下:

  • 导入依赖
  • 编写Generator配置文件
  • 生成代码

6.1 依赖

其实就是加入一个插件:

1<build> 2 <plugins> 3 <plugin> 4 <groupId>org.mybatis.generator</groupId> 5 <artifactId>mybatis-generator-maven-plugin</artifactId> 6 <version>1.4.0</version> 7 <configuration> 8 <!-- 在控制台打印执行日志 --> 9 <verbose>true</verbose> 10 <!-- 重复生成时会覆盖之前的文件--> 11 <overwrite>true</overwrite> 12 <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> 13 </configuration> 14 <dependencies> 15 <dependency> 16 <groupId>mysql</groupId> 17 <artifactId>mysql-connector-java</artifactId> 18 <version>8.0.21</version> 19 </dependency> 20 </dependencies> 21 </plugin> 22 </plugins> 23</build>

数据库驱动请对应修改。

至于Gradle版请看Kotlin版源码。

6.2 配置文件

这里是参考别人的配置文件,修改数据库连接、表名、包名即可:

1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE generatorConfiguration 3 PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" 4 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> 5<generatorConfiguration> 6 <!-- context 是逆向工程的主要配置信息 --> 7 <!-- id:起个名字 --> 8 <!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 --> 9 <context id="default" targetRuntime="MyBatis3"> 10 <!--optional,指在创建class时,对注释进行控制--> 11 <commentGenerator> 12 <property name="suppressDate" value="true"/> 13 <!-- 是否去除自动生成的注释 true:是 : false:--> 14 <property name="suppressAllComments" value="true"/> 15 </commentGenerator> 16 <!--jdbc的数据库连接 wg_insert 为数据库名字--> 17 <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="test" password="test" /> 18 <!--非必须,类型处理器,在数据库类型和java类型之间的转换控制--> 19 <javaTypeResolver> 20 <!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal--> 21 <!-- 不是 double 和 long 类型 --> 22 <!-- 使用常用的基本类型代替 sql 包下的引用类型 --> 23 <property name="forceBigDecimals" value="false"/> 24 </javaTypeResolver> 25 <!-- targetPackage:生成的实体类所在的包 --> 26 <!-- targetProject:生成的实体类所在的硬盘位置 --> 27 <javaModelGenerator targetPackage="pers.entity" 28 targetProject="src/main/java"> 29 <!-- 是否允许子包 --> 30 <property name="enableSubPackages" value="false"/> 31 <!-- 是否对modal添加构造函数 --> 32 <property name="constructorBased" value="true"/> 33 <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 --> 34 <property name="trimStrings" value="true"/> 35 <!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 --> 36 <property name="immutable" value="false"/> 37 </javaModelGenerator> 38 <!-- targetPackage 和 targetProject:生成的 mapper 文件的包和位置 --> 39 <sqlMapGenerator targetPackage="mapper" 40 targetProject="src/main/resources"> 41 <!-- 针对数据库的一个配置,是否把 schema 作为字包名 --> 42 <property name="enableSubPackages" value="false"/> 43 </sqlMapGenerator> 44 <!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 --> 45 <javaClientGenerator type="XMLMAPPER" 46 targetPackage="pers.dao" targetProject="src/main/java"> 47 </javaClientGenerator> 48 <!-- tableName是数据库中的表名,domainObjectName是生成的JAVA模型名,后面的参数不用改,要生成更多的表就在下面继续加table标签 --> 49 <table tableName="user" domainObjectName="User" 50 enableCountByExample="false" enableUpdateByExample="false" 51 enableDeleteByExample="false" enableSelectByExample="false" 52 selectByExampleQueryId="false" /> 53 </context> 54</generatorConfiguration>

6.3 生成代码

在这里插入图片描述

双击生成即可:

在这里插入图片描述

生成了实体类、dao接口以及mapper文件。

7 参考源码

Java版:

Kotlin版:

8 参考链接

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )