作者 | 田维常  责编 | 张文

头图 | CSDN 下载自东方 IC

来源 | Java后端技术全栈(ID:jjs-2018)

本文思维导图:

传统 JDBC

1.1 传统 JDBC 编码格式

public class DataBaseUtil {    public static final String URL = "jdbc:mysql://localhost:3306/mblog";    public static final String USER = "root";    public static final String PASSWORD = "123456";public static void main(String[] args) throws Exception {                Class.forName("com.mysql.jdbc.Driver");        //2.         Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);        //3.        Statement stmt = conn.createStatement();        //4.        ResultSet rs = stmt.executeQuery("SELECT id, name, age FROM m_user where id =1");        //如果有数据,rs.next()返回true        while(rs.next()){            System.out.println("name: "+rs.getString("name")+" 年龄:"+rs.getInt("age"));        }    }}

上面代码中知识为了展示 JDBC 整个过程(异常和资源是简单粗暴的处理了,我们关注的点不在这两个)。

大致可以分为六个步骤:

  1. 加载驱动程序;

  2. 获得数据库连接;

  3. 创建一个Statement对象;

  4. 操作数据库,实现增删改查;

  5. 获取结果集;

  6. 关闭资源。

使用层面来说,采用原生态的 JDBC 在项目中使用起来成本还是很高的。如果我们的项目中的业务相对比较复杂,数据库表也相对较多,各种操作数据库的增删改查的方法也会随之多起来,那么这样的代码重复次数会非常之多。

1.2 传统 JDBC 的问题

  1. 创建数据库的连接存在大量的硬编码;

  2. 执行 statement 时存在硬编码;

  3. 频繁的开启和关闭数据库连接,会严重影响数据库的性能,浪费数据库的资源;

  4. 存在大量的重复性编码。

为了解决以上问题,就诞生了各种各样替换 JDBC 的产品。即 ORM 框架。

什么是 ORM?

全称为 Object Relational Mapping。对象-映射-关系型数据库。对象关系映射(简称ORM、O/RM 或 O/R mapping),用于实现面向对象编程语言里不同类型系统的数据之间的转换。简单的说,ORM 是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射。

ORM 提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得 ORM 中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。

我们的项目中是这样的:

比如:Apache DbUtils、Spring JDBC、 Hibernate、Ibatis(Mybatis 的前生)、Spring Data Jpa 等等。

目前最为流行的是 Mybatis 和 Spring Data Jpa。本系列我们先讲解Mybatis,Jpa 后面再讲。

ORM 的优缺点

优点:

  1. 提高了开发效率。由于 ORM 可以自动对 Entity 对象与数据库中的 Table 进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。

  2. ORM 提供了对数据库的映射,不用 sql 直接编码,能够像操作对象一样从数据库获取数据。

缺点:牺牲程序的执行效率和会固定思维模式,降低了开发的灵活性。

从系统结构上来看,采用 ORM 的系统一般都是多层系统,系统的层次多了,效率就会降低。ORM 是一种完全的面向对象的做法,而面向对象的做法也会对性能产生一定的影响

在我们开发系统时,一般都有性能问题。性能问题主要产生在算法不正确和与数据库不正确的使用上。ORM 所生成的代码一般不太可能写出很高效的算法,在数据库应用上更有可能会被误用,主要体现在对持久对象的提取和和数据的加工处理上,如果用上了 ORM,程序员很有可能将全部的数据提取到内存对象中,然后再进行过滤和加工处理,这样就容易产生性能问题。

在对对象做持久化时 ORM 一般会持久化所有的属性。有时,这是不希望的。但 ORM 是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。我们不能指望工具能一劳永逸的解决所有问题,有些问题还是需要特殊处理的,但需要特殊处理的部分对绝大多数的系统,应该是很少的。

MyBatis

4.1 MyBatis 是什么?

如果在面试的时候被问到,只要你说出下面三种即可。(来自官网)

  1. MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

  2. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

  3. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

4.2 MyBatis 的优点和缺点

优点:

  1. 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响。SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用;

  2. 与 JDBC 相比,减少了 50% 以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;

  3. 很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持);

  4. 能够与 Spring 很好的集成;

  5. 提供映射标签,支持对象与数据库的 ORM 字段关系映射,提供对象关系映射标签,支持对象关系组件维护。

缺点

  1. SQL 语句的编写工作量较大。尤其当字段多、关联表多时,对开发人员编写 SQL 语句的功底有一定要求。

  2. SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

Mybatis环境搭建及简单实例

5.1 创建一张数据库表

创建一张 m_user 表使用 MySQL 数据库。

CREATE TABLE `m_user` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(255) DEFAULT NULL,  `age` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

添加依赖

<dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis</artifactId>            <version>3.5.2</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>8.0.16</version>            <scope>runtime</scope>        </dependency></dependencies>

项目结构如下:

创建一个 mybatis-config.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>    <environments default="development">        <environment id="development">            <transactionManager type="JDBC"/>            <dataSource type="POOLED">                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>                <property name="url" value="jdbc:mysql://localhost:3306/mblog?useUnicode=true"/>                <property name="username" value="root"/>                <property name="password" value="123456"/>            </dataSource>        </environment>    </environments>    <mappers>        <mapper resource="mapper/UserMapper.xml"/>    </mappers></configuration>

实体类User

ublic class User {    private Integer id;    private String name;    private Integer age;    //set get    @Override    public String toString() {        return "User{" +                "id=" + id +                ", name='" + name + '\'' +                ", age=" + age +                '}';    }}

创建 UserMapper.java

import com.tian.mybatis.entity.User;
public interface UserMapper {    User selectUserById(Integer id);}

创建 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.tian.mybatis.mapper.UserMapper">    <select id="selectUserById" resultType="com.tian.mybatis.entity.User">        select * from m_user where id = #{id}    </select></mapper>

创建一个测试类

import com.tian.mybatis.entity.User;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 java.io.IOException;import java.io.InputStream;
public class MybatisApplication {public static void main(String[] args) {        String resource = "mybatis-config.xml";        InputStream inputStream = null;        SqlSession sqlSession =null;        try {            inputStream = Resources.getResourceAsStream(resource);            //工厂模式            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);            //sql操作会话            sqlSession = sqlSessionFactory.openSession();            //获取数据并解析成User对象            User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1);            System.out.println(user);        } catch (Exception e) {            e.printStackTrace();        }finally {            try {                inputStream.close();            } catch (IOException e) {                e.printStackTrace();            }            sqlSession.close();        }    }
}

输出结果:

User{id=1, name='tian', age=22}

整体步骤:

另外一种启动方式:

import com.tian.mybatis.entity.User;import org.apache.ibatis.builder.xml.XMLConfigBuilder;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import java.io.IOException;import java.io.InputStream;import java.util.Properties;
public class MybatisApplication {public static void main(String[] args) {        String resource = "mybatis-config.xml";        InputStream inputStream = null;        try {            inputStream = Resources.getResourceAsStream(resource);        } catch (IOException e) {            e.printStackTrace();        }        //解析xml文件        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, null, null);        //构建一个SqlSessionFactory工厂类        SqlSessionFactory sqlSessionFactory = build(parser.parse());        //创建一个SqlSession        SqlSession sqlSession = sqlSessionFactory.openSession();        //获取数据并解析成User对象        User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1);        System.out.println(user);    }public static SqlSessionFactory build(Configuration config) {        return new DefaultSqlSessionFactory(config);    }}

输出和上面一样。还可以直接使用 Java 代码而不用 mybatis-config.xml。

//创建数据源
DataSource dataSource = getDataSource();TransactionFactory transactionFactory = new JdbcTransactionFactory();Environment environment = new Environment("development", transactionFactory, dataSource);Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
小总结:

从上面这个案例中我们大致能猜到,Mybatis 中最主要几个组件:SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper。

SqlSessionFactoryBuilder 这个类可以被初始、使用和丢弃,如果你已经创建好了一个 SqlSessionFactory 后就不用再保留它。

因此 ,SqlSessionFactoryBuilder 的最好作用域是方法体内,比如说定义一个方法变量。

你可以重复使用 SqlSessionFactoryBuilder 生成多个 SqlSessionFactory 实例,但是最好不要强行保留,因为 XML 的解析资源要用来做其它更重要的事。

SqlSessionFactory 一旦创建,SqlSessionFactory 就会在整个应用过程中始终存在。所以没有理由去销毁和再创建它,一个应用运行中也不建议多次创建 SqlSessionFactory。如果真的那样做,会显得很拙劣。

因此 SqlSessionFactory 最好的作用域是 Application。可以有多种方法实现。

最简单的方法是单例模式或者是静态单例模式。然而这既不是广泛赞成和好用的。反而,使用 Google Guice 或 Spring 来进行依赖反射会更好。这些框架允 许你生成管理器来管理 SqlSessionFactory 的单例生命周期

SqlSession 每个线程都有自己的 SqlSession 实例,SqlSession 实例是不能被共享,也是不是线程安全的。因此最好使用 Request 作用域或者方法体作用域。

不要使用类的静态变量来引用一个 SqlSession 实例,甚至不要使用类的一个实例变更来引用。永远不要在一个被管理域中引用 SqlSession。比如说在 Servlet 中的HttpSession 中。如果你正在使用 WEB 框架,应该让 SqlSession 跟随 HTTP 请求的相似作用域。

也就是说,在收到一个 HTTP 请求过后,打开 SqlSession,等返回一个回应以后,立马关掉这个 SqlSession。关闭 SqlSession 是非常重要的。你必须要确保 SqlSession 在 finally 方法体中正常关闭。

SqlSession session = sqlSessionFactory.openSession();try {// do work} finally {session.close();}

使用这种模式来贯穿你的所有代码,以确保所有数据库资源都被完全关闭。

Mapper:

Mapper 是一种你创建的用于绑定映射语句的接口。Mapper 接口的实例是用 SqlSession 来获得的。同样,从技术上来说,最广泛的 Mapper 实例作用域像 SqlSession 一样,使用请求作用域。确切地说,在方法被调用的时候调用 Mapper 实例,然后使用后,就自动销毁掉。不需要使用明确的注销。当一个请求执行正确无误的时候,像 SqlSession 一样,你可以轻而易举地操控这一切。保持简单性,保持 Mapper 在 方法体作用域内。

 //获取数据并解析成User对象 User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1); System.out.println(user);

这里映射涉及到四个主体:

  1. 实体类 User;

  2. 接口 UaerMapper;

  3. xml 配置文件 UserMapper;

  4. 数据库表 m_user。

Mybatis 的五部曲:

总结

本文主要回顾 JDBC 的 demo、JDBC 中的问题、创建一个 Mybatis 示例、总结出重要的四个组件以及每个组件的作用,希望对大家有所帮助。

更多精彩推荐
☞对标鸿蒙 OS,Google 下一代操作系统 Fuchsia 源码公开!☞红帽"干掉" CentOS 8,CentOS Stream 上位
☞科技垄断正在朝着纵向发展☞挑战TensorFlow、PyTorch,谁才是中国AI开源框架之星
☞CPU:网卡老哥,你到底怎么工作的?☞GitHub标星7000+,快速恢复像素化图像,效果惊人
点分享点点赞点在看

从 JDBC 到 Mybatis,看这篇就够了相关推荐

  1. 一下子搞懂JDBC,看这篇就够了--以MySQL为例。

    一下子搞懂JDBC,看这篇就够了–以MySQL为例. 文章目录 一下子搞懂JDBC,看这篇就够了--以MySQL为例. 一.什么是JDBC? 二.JDBC的使用步骤 三.jdbc进阶--上述各个类或接 ...

  2. Docker入门实战看这篇就够了(最新详细以及踩过的坑)

    Docker入门实战看这篇就够了 前言 初识 是什么 容器与虚拟机 能干什么 去哪玩 安装 先决条件 查看自己的内核 安装所需的软件包(支持devicemapper存储类型) 设置镜像的仓库 设置yu ...

  3. 一文详解JavaBean 看这篇就够了

    一文详解JavaBean 看这篇就够了 JavaBean的历史渊源 JavaBean的定义(通俗版) JavaBean应用 < jsp:useBean > < jsp:getProp ...

  4. React入门看这篇就够了

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 很多值得了解的细节. 原文:React入门看这篇就够了 作者:Random Fundebug经授权转载,版权归原作者所 ...

  5. uiautomation遍历windows所有窗口_万字长文!滑动窗口看这篇就够了!

    大家好,我是小浩.今天是小浩算法 "365刷题计划" 滑动窗口系列 - 整合篇.之前给大家讲解过一些滑动窗口的题目,但未作系统整理. 所以我就出了这个整合合集,整合工作中除了保留原 ...

  6. .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

    写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...

  7. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既 ...

  8. [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了

    园子里关于ASP.NET Core Web API的教程很多,但大多都是使用EF+Mysql或者EF+MSSQL的文章.甚至关于ASP.NET Core Web API中使用Dapper+Mysql组 ...

  9. ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...

  10. 史上最全!用Pandas读取CSV,看这篇就够了

    导读:pandas.read_csv接口用于读取CSV格式的数据文件,由于CSV文件使用非常频繁,功能强大,参数众多,因此在这里专门做详细介绍. 作者:李庆辉 来源:大数据DT(ID:hzdashuj ...

最新文章

  1. 李飞飞公布谷歌云TPU、AutoML、行业方案等多项进展,AI云计算成谷歌全新增长点...
  2. VMware虚拟机相关文件问题
  3. docker删除es数据_Docker的常用命令
  4. Java多线程-BlockingQueue-ArrayBlockingQueue-LinkedBlockingQueue
  5. 图片无法删除要计算机管理员,存在桌面的图片删不掉,怎么处理?提示是需要管理员权限。...
  6. bin文件怎么转换成文本文档_怎么把pdf文件转换成word文档?这样转很简单
  7. 变体类型Variant
  8. ABC互联 shopex网店主机 试用
  9. ASP.NET AJAX学习笔记之:CollapsiblePanel---可折叠的面板
  10. oracle数据库 date函数,Oracle 函数(处置Date)
  11. 励志:滴滴打车App初期是怎么推广的?
  12. 5月6号基金分析的那篇文章,时隔两个月收益如何?
  13. 【OpenGL开发】关于GLEW扩展库
  14. 学习计算机网络的几个好网站
  15. 以太坊源码分析:fetcher模块和区块传播
  16. Python是不是被严重高估了?
  17. linux查找多少天前的文件,linuxfind查找大于多少天的文件,并删除之
  18. 立冬、小雪、凛冬将至:如何理解美国科技企业裁员潮?
  19. 领航优配|累计分红超300亿元,外资持续加仓,云计算龙头再拉涨停
  20. 在Mac os上使用LaTex

热门文章

  1. 自己写的Weblogic的poc
  2. Spring Boot 9-FreeMarker模板引擎
  3. 首先不谈C语言,我们先来谈谈编程工具
  4. luogu P1273 有线电视网
  5. thinkjs 学习笔记
  6. ECMAScript 运算符--逗号运算符
  7. 转Windows 2003服务器安全配置终极技巧
  8. 显卡显存故障检测工具_为RTX30系显卡做准备,骨伽GEX750金牌全模组电源装机体验...
  9. 二叉树——基本知识+python实现
  10. 记录——《C Primer Plus (第五版)》第九章编程练习第八题