第6章 MyBatis框架入门详解(1)
数据持久化
在这章开始之前首先简单介绍一下什么是数据持久化。其实“持久化”是相对“临时”来说的,在计算机中存放数据的地方主要有两个,一个是内存,一个是硬盘,在内存中存放的数据虽然有访问速度快的优势,但是只要断电其数据就会丢失,而如果需要长期保存就需要存放在硬盘等可以长期保存数据的介质中,所以在这里内存的数据就是“临时”存储的,而把"临时"存储的数据转换为持久存储的数据这个过程就是持久化。当然上面这种说法并不真正严谨,但这主要是为了帮助我们理解。在持久化过程中会有很多数据的保存形式,比如文本、二进制流等等,而最常见的一种将“临时”数据进行持久化保存的形式就是将数据保存在数据库中,这就是数据库持久化。
什么是ORM
接下来再介绍一下什么是ORM,在前面的介绍中我们知道了什么是数据库持久化,但是在实际操作过程中我们会发现“临时”存储的数据的数据结构和数据库中持久性所需要用的数据结构可能不一样。在存储时需要进行一些转换。同时如果直接在应用程序中操作数据库则往往要编写大量的数据库访问层代码,并且这种代码大部分就是我们经常说的毫无技术含量的增删查改代码,这些重复的代码编写工作枯燥无味,操作繁琐。
为了解决上面提到的两个问题,发展出了ORM技术,全称是对象关系映射(Object Relationnal Mapping)它不仅解决了面向对象与关系数据库存在的不匹配问题,可以通过配置描述对象和数据库之间映射关系的元数据完成将对象自动持久化到关系型数据库中,简单来说就是让开发者操作实体类就实现操作数据库表,同时提供简化的语法解决大量编写增删查改等重复代码的工作。
常见的ORM框架
基于ORM技术出现了很多ORM框架,它们封装了数据库操作的很多细节,使开发者只需要关注SQL语句本身,它们都可以简化编程过程中操作数据库的编码,不过每个框架各自有各自的优缺点,目前开发领域流行度最广的ORM分别是Hibernate和Mybatis。 Hibernate宣称可以不用写一句SQL,而MyBatis以动态SQL见长。
Hibernate简介
Hibernate 对JDBC进行了非常轻量级的对象封装,它将POJO(普通JavaBeans)与数据库表建立映射关系,是一个全自动的ORM框架,Hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用。
Hibernate的主要优点有:
不需要编写的SQL语句(不需要编辑JDBC),只需要操作相应的对象就可以了,就可以能够存储、更新、删除、加载对象,可以提高生产效。
因为使用Hibernate只需要操作对象就可以了,所以整个开发过程可以专注在对象上。
使用Hibernate,具有很高的可移植性,使用Hibernate标准开发,在更换数据库时,只需要配置相应的配置文件就可以了。
Hibernate实现了透明持久化,当保存一个对象时,这个对象不需要继承Hibernate中的任何类、实现任何接口,只是个纯粹的简单对象。
Hibernate的主要缺点有:
Hibernate学习成本太高,配置复杂,开发人员掌握需要很长时间。
不适合有复杂的SQL查询,由于对持久层封装过于完整,导致开发人员无法对SQL进行优化,无法灵活使用JDBC的原生SQL。Hibernate封装的语句没有原生的JDBC程序访问数据库效率高。当项目中要使用数据库的特定优化机制的时候,不适合用Hibernate 。
配置文件复杂,框架中使用ORM原则,导致配置过于复杂,一旦遇到大型项目,配置文件的复杂性往往超过代码和业务逻辑本身的复杂性。
Mybatis简介
MyBatis本是一个半自动化的ORM框架,它本来是Apache基金会的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。其主要特点有
通过参数映射方式,可以将参数灵活的配置在SQL语句中的配置文件中,避免在Java类中配置参数。
通过输出映射机制,将结果集的检索自动映射成相应的Java对象,避免对结果集手工检索。
Mybatis可以通过Xml配置文件对数据库连接进行管理。
实现了SQL和Java代码的分离,通过配置文件实现SQL语句查询,将业务逻辑和数据访问逻辑分类,使得系统架构更加清晰明了。
支持通过各种条件来动态生成不同的SQL。
由于MyBatis入门难度更低,学习曲线更加平缓,并且项目组提供了脚本自动生成工具,因此MyBatis更适合初学者入门,后面我们也选择MyBatis进行介绍。
在Spring Boot中使用MyBatis
在Spring Boot中使用MyBatis之前我们要安装数据库,以便项目中使用。这里我们选择MySql数据库。数据安装教程网上有很多,这里我们就不再赘述了。安装完了Mysql之后,可以使用Mysql WorkBench、Navicat等客户端操作数据库,这里我们用Navicat创建一个数据库mybatis_demo,字符集选择了utf8,排序规则选择了utf8_general_ci
也可以使用跟前面一样使用IDEA操作数据库,这里秉承充分利用开发IDE的思路,我们选择使用IDEA操作数据库,在使用之前我们进行一些配置
配置IDEA数据库工具
点击IDEA左下角的方形图标,在弹出的页面选择Database
然后在右侧弹出的窗口选择Database,点击+号图标,选择DataSource,然后在选择MySQL
对数据库连接进行配置,Name处是用来标识这个数据库连接的信息,可以按需填写,随后填写Host,password和默认连接数据库等参数,这里我们希望默认连接到mybatis_demo。
配置完毕之后点击Test Connection,如果一切顺利会出现绿色的小勾和数据库信息,这说明配置成功了,然后点击Ok
随后我们可以在右侧窗口看到数据库连接信息,注意其中的0 of 7,说明当前Mysql里有7个数据库schemas,但是当前选中的是0,由于我们后面的操作都准备在mybatis_demo这个schema中操作,为了查看方便,我们点击红框,然后再弹出的界面中选择mybatis_demo
准备数据库表
好了现在我们选中了mybatis_demo作为默认schema,我们建立几张数据库表。我们后面以一个简易的旅游公司景点管理系统为例,逐步进行介绍。
首先我们设计第一张数据库表:用户表,这张表我们设计4个字段,一个是id用于存放用户编号,一个是name用于存放用户名字,一个是age用于存放用户年龄,一个是city_id用于存放城市编号,在这张表中每个用户对应一个城市,代表他可以管理旅游公司这个城市中的景点相关服务。具体的sql语句如下
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',`name` varchar(50) NOT NULL COMMENT '用户名',`age` int(11) NOT NULL COMMENT '年纪',`city_id` int(11) NOT NULL COMMENT '城市编号',primary key (`id`)
)ENGINE = InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET = utf8 COMMENT '用户表';INSERT INTO `user` VALUES (1, '李磊', 20, 1);
INSERT INTO `user` VALUES (2, '陈雨', 22, 2);
INSERT INTO `user` VALUES (3, '张华', 28, 3);
INSERT INTO `user` VALUES (4, '黄文树', 25, 4);
INSERT INTO `user` VALUES (5, '巴颂', 28, 5);
接下来我们再创建一张表:城市表,这张表我们设计3个字段,分别是city_id代表城市编号,这个编号和用户表里是一致的,后面我们可以通过用户表中的城市编号,到城市表中查找具体的城市信息,还有city_name城市名字段,最后一个是country字段代表城市所在的国家,具体SQL如下
DROP TABLE IF EXISTS `city`;
CREATE TABLE `city` (`city_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '城市编号',`city_name` varchar(50) NOT NULL COMMENT '城市名',`country` varchar(50) NOT NULL COMMENT '国家',primary key (`city_id`)
)ENGINE = InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET = utf8 COMMENT '城市表';INSERT INTO `city` VALUES (1, '北京', '中国');
INSERT INTO `city` VALUES (2, '上海', '中国');
INSERT INTO `city` VALUES (3, '杭州', '中国');
INSERT INTO `city` VALUES (4, '岘港', '越南');
INSERT INTO `city` VALUES (5, '曼谷', '泰国');
最后我们再创建一张表:景点表,存储每个城市的景点信息,这张表也有4个字段,首先是scenic_id代表景点编号,用于区分不同的景点,然后是city_id代表景点所在的城市,第3个字段是scenic_name代表景点名,第4个字段是price记录景点的价格,为了方便就直接记录所在国家的货币的价格。
DROP TABLE IF EXISTS `scenic`;
CREATE TABLE `scenic` (`scenic_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '景点编号',`city_id` int(11) NOT NULL COMMENT '城市编号',`scenic_name` varchar(50) NOT NULL COMMENT '景点名',`price` int(11) NOT NULL COMMENT '价格',primary key (`scenic_id`)
)ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '景点表';
INSERT INTO `scenic` VALUES (1, 1, '故宫', 40);
INSERT INTO `scenic` VALUES (2, 1, '颐和园',20 );
INSERT INTO `scenic` VALUES (3, 2, '外滩', 0);
INSERT INTO `scenic` VALUES (4, 2, '辰山植物园', 60);
INSERT INTO `scenic` VALUES (5, 3, '西湖', 0);
INSERT INTO `scenic` VALUES (6, 4, '巴拿山', 600000);
INSERT INTO `scenic` VALUES (7, 4, '岘港大教堂', 0);
INSERT INTO `scenic` VALUES (8, 5, '大皇宫', 500);
接下来再IDEA中新建工程chapter6,然后在com.cjl.chapter6目录下新增sql目录,然后添加mybatis_demo.sql文件将上面的SQL存放到文件中
然后点击右键,选择Run 'mybatis_demo.sql'运行脚本文件,接下来IDEA会询问你需要在哪个schema中执行,这个时候我们选择mybatis_demo
执行完毕之后,可以在右侧看到,新建出来的表
添加图片注释,不超过 140 字(可选)
双击数据库表可以看到里面的数据内容,例如双击user表,我们可以看到
数据库准备好了之后,正式使用MyBatis还需要进行一些配置,下面我们就开始配置MyBatis。
配置MyBatis
首先我们在com.cjl.chapter6下面再建两个目录model,mapper,在resources目录下新建目录mapper,用于接下来存放指定的文件,至于这些文件是什么? 是否一定需要这样安排目录,我们先用一用MyBatis有个感性认识后面再详细解释。
然后在application.properties文件中配置一下数据库连接信息和MyBatis目录信息。具体内容如下。
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_demo?useSSL=true&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=itJMF-4RObQ2
spring.datasource.driver-class-name=com.mysql.cj.jdbc.DriverMyBatis.mapper-locations=classpath:/mapper/*.xml
MyBatis.type-aliases-package=com.cjl.chapter6.model
上面4个配置参数是关于数据库连接的配置,参数一目了然就不具体解释了。不过另外2个参数我们需要解释一下首先是MyBatis.mapper-locations这个配置表面项目中mapper配置文件所在的目录,那什么是mapper配置文件呢? 在MyBatis中会使用一个配置文件把所需要生成的SQL语句按相应的语法配置好,然后MyBatis会根据这个配置文件(通常会保存为XML文件)生成需要的SQL语句,而MyBatis.mapper-locations配置参数就是告诉MyBatis上哪里去找这些Mapper配置文件。在这里配置的路径是classpath:/mapper/*.xml,其中classpath默认代表resource目录,所以这里的配置含义就是说MyBatis所需要的mapper配置文件存放在项目resource/mapper目录下。
另外一个配置参数MyBatis.type-aliases-package则指定POJO(普通Java类)的地址,还记得前面说的MyBatis是对象关系映射ORM的框架,它可以通过对象操作数据库映射,这里MyBatis.type-aliases-package参数就是指定MyBatis到哪里查找这个对象。
现在model目录已经介绍了,resources下的mapper目录也已经介绍了,那前面提到的com.cjl.chapter6下的mapper目录又是做什么的呢?其实这个目录存放的是MyBatis的mapper映射文件,什么是mapper映射文件呢,我们可以简单的理解为是定义POJO类可以提供哪些数据库操作的文件,每个mapper映射文件都是一个接口文件里面会定义一些方法,后面我们可以通过调用这些方法在执行相应的数据库操作。
完成上述配置后,接下来找到项目的入口函数所在文件,这里是Chapter6Application
在public class Chapter6Application语句上面添加@MapperScan("com.cjl.chapter6.mapper")
@SpringBootApplication
@MapperScan("com.cjl.chapter6.mapper")
public class Chapter6Application {public static void main(String[] args) {SpringApplication.run(Chapter6Application.class, args);}
}
这行注解告诉Spring Boot扫描com.cjl.chapter6.mapper目录查找mapper文件。也可以不再这里添加注解,不过那样的话就需要在每一个要使用的mapper文件里添加注解,这样会比较麻烦。
使用MyBatis
完成了前面所说的配置之后,MyBatis的使用前准备工作已经完成。接下来我们开始使用MyBatis开发。首先我们在model目录下面新建一个User类,并且添加代码
public class User {private Long id;private String name;private int age;private int city_id;public User(String name, int age, int city_id) {this.name = name;this.age = age;this.city_id = city_id;}public User(Long id, String name, int age, int city_id) {this.id = id;this.name = name;this.age = age;this.city_id = city_id;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}//其余get set省略
}
然后在Mapper目录下添加UserMapper接口文件,具体内容如下
@Component
public interface UserMapper {List<User> selectAllUser();User selectOne(Long id);
}
这个文件中我们添加了2个方法selectAllUser和selectOne这两个方法就是User这个POJO能够对外提供的数据库操作方法,注意我们在UserMapper接口上面添加了Component注解,告诉Spring Boot这是一个Component。
接下来我们在resources下面的mapper目录下添加UserMapper.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.cjl.chapter6.mapper.UserMapper"><select id="selectAllUser" resultMap="BaseResultMap">SELECT*FROM user</select><select id="selectOne" parameterType="Long" resultMap="BaseResultMap">SELECT*FROM userWHERE id = #{id}</select><resultMap id="BaseResultMap" type="com.cjl.chapter6.model.User"><id column="id" property="id" jdbcType="BIGINT"/><result column="name" property="name" jdbcType="VARCHAR"/><result column="age" property="age" jdbcType="INTEGER"/><result column="city_id" property="city_id" jdbcType="INTEGER"/></resultMap></mapper>
这个Mapper.xml就是按照MyBatis的语法编写的SQL模板文件,MyBatis会根据它的语法生成相应的SQL语句。这里先简单介绍一下
<?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配置文件使用MyBatis规则。
<mapper namespace="com.cjl.chapter6.mapper.UserMapper">
这句话的意思是本mapper配置文件的命名空间是com.cjl.chapter6.mapper.UserMapper,这样不同的mappper配置文件里有一样的SQL语句也不会出现冲突。
<select id="selectAllUser" resultMap="BaseResultMap"> SELECT * FROM user </select>
这个select标签说明这是一个select语句模板,最终会生成一条数据库select语句。id标志时这条select模板语句的身份标识,其后面的值需要和前面mapper接口文件中定义的方法名一致,MyBatis会根据id匹配方法的sql语句模板。resultMap="BaseResultMap"说明模板生成的sql语句执行之后的结果存放的地方,这里是BaseResultMap,那这个BaseResultMap又是什么呢?它其实是文件中的一个定义的标识,用于描述查询结果如何存放,具体语句如下
<resultMap id="BaseResultMap" type="com.cjl.chapter6.model.User"><id column="id" property="id" jdbcType="BIGINT"/><result column="name" property="name" jdbcType="VARCHAR"/><result column="age" property="age" jdbcType="INTEGER"/><result column="city_id" property="city_id" jdbcType="INTEGER"/></resultMap>
它的类型是com.cjl.chapter6.model.User,在resultMap标签中间的语句的作用是描述数据库中的字段和User类型中属性的对应关系,默认情况下MyBatis能够自动将数据库字段和POJO类的属性进行对应,不过要求字段名和属性名相同。
<result column="name" property="name" jdbcType="VARCHAR"/>
上面语句就是说查询结果中数据库的name字段中的值最后填充到User的name属性里,并且数据类型是VARCHAR型,其余几行也是类似这样含义。
前面的id=selectAllUser的标签内容最后会映射生成 SELECT * FROM user语句(注意这里user前没有添加schema名,MyBatis会使用连接配置中的默认schema),并且该语句最终执行的查询结果会存放在User类的对象中。
<select id="selectOne" parameterType="Long" resultMap="BaseResultMap"> SELECT * FROM user WHERE id = #{id} </select>
对于UserMapper.xml文件中的另外一个select模板,其对应方法selectOne,其作用是根据id号查询user,与另一个select模板不同的是这里使用了parameterType它会指明动态生成sql语句时的参数类型,这里是Long类型,其传入的参数用#{id}引用,在实际生成具体sql语句时这个引用会被具体值替代,例如如果传入的id为100则最终生成的sql语句为
SELECT * FROM user WHERE id = 100
验证MyBatis
完成前面的配置和代码编写之后,我们就完成了一个实体类到数据库的映射,接下来我们测试验证一下。在test目录里的Chapter6ApplicationTests单元测试类中,我们添加测试代码
@SpringBootTest
class Chapter6ApplicationTests {@Autowiredprivate UserMapper userMapper;@Testvoid contextLoads() {}@Testpublic void testSelectAllUser() {List<User> users = userMapper.selectAllUser();for (User user : users) {System.out.println("name:" + user.getName() + ", age:" +user.getAge() + ", city_id:" + user.getCity_id());}}@Testpublic void testSelectOneUser() {User user = userMapper.selectOne(1L);System.out.println("name:" + user.getName() + ", age:" +user.getAge() + ", city_id:" + user.getCity_id());}
}
这里具体代码就不详细介绍了,前面的文章都已经介绍过,我们执行单元测试
测试通过,说明可以通过UserMapper提供的方法操作对象达到操作数据库的目的。这说明MyBatis成功集成到了项目中,并可以通过操作类实现数据库操作。掌握了MyBatis的初步配置和使用之后,我们后面的文章将会介绍MyBatis的具体语法和自动生成工具。
项目源码
可以访问:https://github.com/qwdzq/springboot.git
文章有帮助,还请点个赞啊
第6章 MyBatis框架入门详解(1)相关推荐
- Mybatis的入门详解
mybatis简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为M ...
- Java Spring框架入门详解教程【多测师_何sir】
Spring框架入门详解教程 spring概述 spring结构 spring IOC spring DI spring概述 Spring是一个非常活跃的开源框架, 它是一个基于IOC和AOP来构架多 ...
- Mybatis框架全面详解
MyBatis的基本使用 第一章:MyBatis的概念 第二章: MyBtais的基本使用 2.1 环境的搭建 2.1.1 物理建模 2.1.2 逻辑建模 2.1.3 搭建框架开发环境 2.1.3.1 ...
- java框架魔乐_16 魔乐科技 SpringBoot框架开发详解
资源内容: 16 魔乐科技 SpringBoot框架开发详解|____springboot开发代码.rar|____第一章:SpringBoot入门 |____2. SpringBo ...
- c++框架有哪些_Java Mybatis框架入门教程_v20200726
MyBatis 的前身是 Apache 的开源项目 iBatis.MyBatis 几乎可以代替 JDBC,是一个支持普通 SQL 查询,存储过程和高级映射的基于 Java 的优秀持久层框架.MyBat ...
- gcn 图卷积神经网络_GCN图卷积网络入门详解
字幕组双语原文:[GCN]图卷积网络(GCN)入门详解 英语原文:Graph Convolutional Networks (GCN) 翻译:听风1996.大表哥 在这篇文章中,我们将仔细研究一个名为 ...
- 依赖注入框架Dagger2详解(一),依赖注入和控制反转的深入理解
IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序,而Dagger2框架是依赖注入思想践行者的优秀代表. 依赖注入框架Dagger2详解(一), ...
- Spring入门详解
typora-copy-images-to: upload Spring入门详解 Spring框架是Java开发中最常用的框架,功能非常强大 源码下载:Spring Framework jar包.文档 ...
- [论文阅读] (01) 拿什么来拯救我的拖延症?初学者如何提升编程兴趣及LATEX入门详解
又是在凌晨三点赶作业,又是在Deadline前去熬夜,一次次无眠,一次次抱怨.为什么三年前.两年前.一年前,甚至是昨天,我都下定决心"从现在开始读顶会论文",却又悄悄选择逃避:为什 ...
最新文章
- 160个Crackme038之P-Code初窥门径
- 如何在Windows 10中创建电源选项快捷图标,快速设置笔记本电脑的节能模式
- Exalogic Elastic Cloud
- ABP动态生成WebAPI
- JSP实现点击链接后下载文件(相当于右键另存)功能
- 【java笔记】IDEA debug调试
- java 异常捕捉 ( try catch finally ) 清晰解释
- sin傅里叶变换公式_傅里叶变换公式(傅里叶变换常用公式)
- Kali内Nmap端口扫描与高级扫描
- 2020身高体重标准表儿童_婴儿身高体重对照表2020
- STM32F简单应用
- [目标检测]论文翻译代码理解-SCRDet: Towards More Robust Detection for Small, Cluttered and Rotated Objects
- 李宏毅老师《机器学习》课程笔记-5 Transformer
- STM32之UART
- 2021云栖大会丨果断收藏!「混合云参会指南」来啦
- robocode调试技巧
- 魔兽服务器负载显示新,魔兽世界部分服务器的负载过高 官方将会开启免费转服服务...
- RMAN完全恢复与不完全恢复测试
- 俄罗斯游戏java源代码_Java俄罗斯方块游戏源代码JAVA游戏源码下载
- 如何设置word页脚中的总页码