导读

官网地址

https://mybatis.org/mybatis-3/zh/index.html

架构原理图

说明

mybatis配置文件

  1. SqlMapConfig.xml,此文件为mybatis的全局配置文件,配置了mybatis的运行环境等信息
  2. XXXMapper.xml,此文件作为mybatis的sql映射文件,文件中配置了操作数据库的CRUD语句。需要在SqlMapConfig.xml中加载

SqlSessionFactory

  1. 通过mybatis环境等配置信息构造SqlSessionFactory,既会话工厂

***跟底层源码查看创建SqlSessionFactory流程***

注:底层如何获取标签值,请自行研究(剧透:for循环遍历XML获取标签中的值,然后放入Map)!~

SqlSession

  1. 通过会员工厂创建SqlSession即会话,程序通过SqlSession会话接口对数据库进行CRUD操作。

Executor执行器

  mybatis底层自定义了Executor执行器接口来具体操作数据库,Executor接口有两个实现,一个是基本执行器(默认),一个缓存执行器,SqlSession底层是通过executor接口操作数据库

Mapped Statement

  他是mybatis一个底层封装对象,包装了mybatis配置信息及XXXMapper.xml映射文件等。XXXMapper.xml文件中一个个select/insert/update/delete标签对应一个Mapped Statement对象

原始JDBC代码

  原始JDBC和mybatis操作数据库数据,与上面架构图流程相对应。

public class JDBCTest {

    public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver"); // 通过驱动管理类获取数据库链接connection = DriverManager
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
"root",
"root"
); // 定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
// 获取预处理 statement
preparedStatement = connection.prepareStatement(sql); // 设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的
preparedStatement.setString(1, "王五");
// 向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
// 遍历查询结果集
while (resultSet.next()) {
System.out.println(
resultSet.getString("id")
+ " " +
resultSet.getString("username")
);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block e.printStackTrace();
}
}
}
}
}

Mybatis 入门基础

表结构

表数据

Mybatis环境搭建 

添加依赖

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cyb</groupId>
<artifactId>mybatis</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency> <!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<finalName>mybatis</finalName>
</build>
</project>

SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入外部配置文件 -->
<properties resource="db.properties"></properties>
<!-- 数据库链接相关 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 添加映射文件 -->
<mapper resource="UserMapper.xml" />
</mappers>
</configuration>

db.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/cyb
db.username=root
db.password=root

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">
<!-- namespace:为了分类管理映射文件中的MappedStatement -->
<mapper namespace="test">
<select id="queryUserById" parameterType="int" resultType="com.cyb.mybatis.demo.User">
select * from user where id = #{id}
</select>
</mapper>

User.java

package com.cyb.mybatis.demo;

import java.util.Date;

public class User {
private int id;
private String username;
private Date birthday;
private int sex;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address="
+ address + "]";
}
}

MybatisDemo.java

package com.cyb.mybatis.demo;

import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; public class MybatisDemo { private SqlSessionFactory sqlSessionFactory; @Before
public void init() throws Exception {
//指定全局配置文件路径
String resource = "SqlMapConfig.xml";
//加载资源文件(包括全局文件和映射文件)
InputStream inputStream = Resources.getResourceAsStream(resource);
//使用构建者模式创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} @Test
public void testSelect() {
//由SqlSessionFactory工厂去创建SqlSession(会话)
SqlSession sqlSession = sqlSessionFactory.openSession();
//调用SqlSession接口,去实现数据库的CRUD
User user = sqlSession.selectOne("test.queryUserById", 1);
System.out.println(user);
//释放资源
sqlSession.close();
}
}

项目结构

测试

功能实现

根据用户id查询一个用户信息

根据用户名称模糊查询用户信息列表

添加用户

主键返回

    <!-- 主键返回 -->
<insert id="insertUser" parameterType="com.cyb.mybatis.demo.User">
<!-- selectKey将主键返回,需要再返回 -->
<selectKey keyProperty="id" order="AFTER"
resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address});
</insert>

添加selectKey标签实现主键返回。

* keyProperty:指定返回的主键,存储在pojo中的哪个属性

* order:selectKey标签中的sql的执行顺序,是相对与insert语句来说。由于mysql的自增原理,执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after。

* resultType:返回的主键对应的JAVA类型

* LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

更新用户

删除用户

Mybatis开发Dao层

mapper代理开发方式

XML方式

使用:只需要开发Mapper接口(Dao接口)和xxxMapper约束文件,不需要编写实现类。

开发规范:

  1. Mapper接口的类路径xxxMapper.xml文件中的namespace相同
  2. Mapper接口方法名称xxxMapper.xml中定义的每个statementid相同
  3. Mapper接口方法的输入参数类型xxxMapper.xml中定义的每个sql的parameterType的类型相同
  4. Mapper接口方法的返回值类型xxxMapper.xml中定义的每个sql的resultType类型相同

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cyb</groupId>
<artifactId>mybatis</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency> <!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<finalName>mybatis</finalName>
</build>
</project>

SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入外部配置文件 -->
<properties resource="db.properties"></properties>
<!-- 数据库链接相关 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 添加映射文件 -->
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>

db.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/cyb
db.username=root
db.password=root

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">
<!-- namespace:为了分类管理映射文件中的MappedStatement -->
<mapper namespace="com.cyb.mybatis.mapper.UserMapper">
<!-- 通过ID查询 -->
<select id="queryUserById" parameterType="int"
resultType="com.cyb.mybatis.demo.User">
select * from user where id = #{id}
</select>
</mapper>

Use.java

package com.cyb.mybatis.demo;

import java.util.Date;

public class User {
private int id;
private String username;
private Date birthday;
private int sex;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address="
+ address + "]";
}
}

UserMapper.java

package com.cyb.mybatis.mapper;

import com.cyb.mybatis.demo.User;

public interface UserMapper {
/**
* 根据用户id查询用户信息
* @param id 内码
* @return
* @throws Exception
*/
public User queryUserById(int id) throws Exception;
}

MybatisDemo.java

package com.cyb.mybatis.demo;

import java.io.InputStream;
import java.util.Date;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import com.cyb.mybatis.mapper.UserMapper; public class MybatisDemo { private SqlSessionFactory sqlSessionFactory; @Before
public void init() throws Exception {
// 指定全局配置文件路径
String resource = "SqlMapConfig.xml";
// 加载资源文件(包括全局文件和映射文件)
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用构建者模式创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} @Test
public void testSelect() throws Exception {
// 由SqlSessionFactory工厂去创建SqlSession(会话)
SqlSession sqlSession = sqlSessionFactory.openSession();
// 调用SqlSession接口,去实现数据库的CRUD
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user = userMapper.queryUserById(1);
System.out.println(user);
// 释放资源
sqlSession.close();
}
}

项目结构

测试

全局配置文件

properties标签

  可以引入java属性文件中的配置信息

typeAlias标签

  别名的作用:为了简化映射文件中parameterType和resultType中POJO类型的包名

默认支持别名

批量指定别名(推荐)

注:可以写多个package,但是package和typeAlias不能一起用!!!

单个指定别名(typeAlias)

注:可以写多个typeAlias,但是package和typeAlias不能一起用!!!

mappers标签

<mapper resource="" /> (不推荐)

注:一次加载一个映射文件,相当于资源路径

<package name="" />(推荐)

  注册指定包下的所有mapper接口,来加载mapper映射文件。

注:mapper接口和mapper映射文件名称相同,且放到同一目录下

关联查询

一对多

Collection标签:定义了一对多关联的结果映射。
property="orders":关联查询的结果集存储在User对象的上哪个属性。
ofType="orders":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。

源码部分

构建SqlSessionFactory过程

  下面我们具体的查看下是如何构建SqlSessionFactory对象

  通过源码可以看出,最终生成一个DefaultSqlSessionFactory实例,这个不是我们关注的重点,我们核心是关注如何初始化对象的。

构建XMLConfigBuilder对象

  build函数首先会构造一个XMLConfigBuilder对象,他是解析XML配置文件的。

  • XMLxxxBuilder:解析XML配置文件的,不同类型的XMLxxxBuilder解析不同的部位

    • XMLConfigBuilder:解析mybatis全局配置文件
    • XMLMapperBuilder:解析mybatis映射文件
    • XMLStatementBuilder:解析映射文件中statement语句(CRUD Sql语句)
    • MapperBuilderAssistant:辅助解析映射文件并生成MappedStatement对象

这些XMLxxxBuilder都有一个共同的父类->BaseBuilder这个父类维护了全局的Configuration对象,mybatis的配置文件解析后就以Configuration对象的形式存储。   

加载映射文件

  底层代码量较多,录制的gif图片较大不能上传,分3段上传的,内容都是连续的;这里抛块砖,实际还是要自己打个断点,跟踪下底层源码,根据自身爱好,研究相应内容,准备工作:了解知识点:XPath(如,解析XML配置文件,点我直达)、设计模式(如:构建者模式,点我直达)、面向对象等等,要不然跟踪源码是件很痛苦的事儿~~~

构建者模式使用地方

XPath使用地方

补充

注意:此处用到了遍历list节点,因为映射文件有很多的select、update、delete标签哦~

打开session会话

  我们可以看到,SqlSessionFactory是一个接口,里面有很多重载方法

SqlSessionFactory接口重载说明

跟踪到SqlSessionFactory的实现类DefaultSqlSessionFactory

  通过跟踪到DefaultSqlSessionFactory,我们可以看到,底层使用了重载,默认自动提交事务未false,从而解答了,我们使用默认无参构造函数时,对数据库进行:插入、修改、删除,需要手动提交事务

  细心的小伙伴此时会问,问什么跟踪源码的时候,他不是有两个实现类吗,为什么要跟踪上面一个,不跟踪下面那个,是因为创建SqlSessionFactory的时候,默认返回的是DefaultSqlSessionFactory

跟踪selectOne

selectList分析

我们跟踪下,是如何从Configuration全局配置文件中(从Map中获取),获取MapperStatement的;注:这个全局配置文件(configuration)是在初始化SqlSessionFactory时加载的

接下来我们跟踪下,是如何解析传递的参数的,分3种处理情况,分别为:集合、list、其他;注:参数类型与xxxMapper.xml的parameterType类型想对应,传什么类型,走什么情况

跟踪executor.query

  先走下面那个实现类,在走上面那个实现类

为什么先走下面那个实现类呢?看gif,先委托下面那个实现类

设置参数绑定

  打个断点,调试下就知道了!!








Mybatis 快速入门(XML方式)第一天的更多相关文章

  1. Java基础-SSM之mybatis快速入门篇

    Java基础-SSM之mybatis快速入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实你可能会问什么是SSM,简单的说就是spring mvc + Spring + m ...

  2. MyBatis学习总结(一)——MyBatis快速入门

    一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...

  3. MyBatis快速入门

    一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...

  4. MyBatis学习总结(一)——MyBatis快速入门(转载)

    本文转载自http://www.cnblogs.com/jpf-java/p/6013537.html MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了 ...

  5. MyBatis入门学习教程-MyBatis快速入门

    一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...

  6. MyBatis学习总结(一)——MyBatis快速入门

    一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...

  7. 【转】MyBatis学习总结(一)——MyBatis快速入门

    [转]MyBatis学习总结(一)——MyBatis快速入门 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC ...

  8. MyBatis学习总结-MyBatis快速入门的系列教程

    MyBatis学习总结-MyBatis快速入门的系列教程 [MyBatis]MyBatis 使用教程 [MyBatis]MyBatis XML配置 [MyBatis]MyBatis XML映射文件 [ ...

  9. MyBatis学习笔记(一)——MyBatis快速入门

    转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4261895.html 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优 ...

随机推荐

  1. mongoDB(一)——mongoDB安装部署和常用shell命令

    1.mongoDB简介 mongoDB 是由C++语言编写的,是一种分布式的面向文档存储的开源nosql数据库.nosql是Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统 ...

  2. Spiking-YOLO : 前沿性研究,脉冲神经网络在目标检测的首次尝试 | AAAI 2020

    论文提出Spiking-YOLO,是脉冲神经网络在目标检测领域的首次成功尝试,实现了与卷积神经网络相当的性能,而能源消耗极低.论文内容新颖,比较前沿,推荐给大家阅读   来源:晓飞的算法工程笔记 公众 ...

  3. 2019-2020-1 20199308《Linux内核原理与分析》第一周作业

    Linux 基础入门(新版)学习笔记 实验二 基本概念及操作 重要快捷键 Tab 补全命令 Ctrl+c 强行终止当前命令 历史命令 方向上键↑,恢复之前输入过的命令 通配符 在命令行中获取帮助 某个 ...

  4. 2019-2020-1 20199310《Linux内核原理与分析》第三周作业

    1.问题描述 计算机的3大法宝是存储程序计算机,函数调用堆栈和中断机制,存储程序计算机已经在上一个博客中进行具体描述,本文将在剩下两方面出发对操作系统是如何工作的进行学习和探讨. 2.解决过程 2.1 ...

  5. C++多线程队列实现

    C++多线程队列实现 C++多线程队列学习 介绍 在项目中,进行多线程队列实现是一个比较麻烦的事, 找到了一个实现比较好的多线程队列实现, 自己做了一点修改更加适应自己的项目, 记录下来, 有需要的自 ...

  6. 都2020年了,这5个java IDE神器你还不知道?

    TIOBE的4月份编程语言排行榜出来了,java还是稳坐第一位,java最新的版本也到了13,一直以来java凭借其企业级应用的优势和大量的框架级应用俘获了大量的粉丝和企业客户. 谈到开发者,java ...

  7. varnish4.0缓存代理配置

    防伪码:你必须非常努力,才能看起来毫不费力. 一.varnish原理: 1)Varnish简介: varnish缓存是web应用加速器,同时也作为http反向缓存代理.你可以安装varnish在任何h ...

  8. 蘑菇街CEO陈琪上市致辞:科技是生产力 美丽也是生产力

    雷帝网 乐天 12月7日报道 蘑菇街CEO陈琪今日在纽交所上市致辞时表示,蘑菇街的使命是让时尚触手可及,立志成为最领先的时尚目的地,并把"科技是生产力,美丽也是生产力"作为蘑菇街价 ...

  9. Get史上最优雅的加密方式!没有之一!

    你的配置文件是不是还在使用下面这种落后的配置暴露一些密码: jdbc.url=jdbc:mysql://127.0.0.1:3305/afei jdbc.username=afei 如果是,那么继续往 ...

  10. tr标签使用hover的box-shadow效果不生效

    先说问题: 这是大致的HTML结构 <table cellpadding="0" cellspacing="0"> <thead> &l ...