【Mybatis源码解析】- JDBC连接数据库的原理和操作
JDBC连接数据库的原理和操作
JDBC即Java DataBase Connectivity,java数据库连接;JDBC 提供的API可以让JAVA通过API方式访问关系型数据库,执行SQL语句,获取数据;常见关系型数据库如Oracle、MySQL、SQLServer等;对于非关系型数据库如Redis、mongonDB等就显得无力;关系型数据库最典型的数据结构是表,易于维护,灵活使用(使用表结构,支持SQL语言的简单及复杂表及多表之间的查询),非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合(文档型、键值对型、列式数据库、图形数据库),相对于关系型数据库(读写性能比较差,效率低,灵活度低、高并发处理显得鸡肋);非关系型数据库优点多多,速度快、高拓展、低成本(就数据结构复杂,其他都比较简单,学习难度就有点大)。
JDBC是一种规范,它提供的接口,是一套完整的、可移植的访问底层数据库的程序。
JDBC连接数据库步骤
- 在开发环境中加载指定的数据库驱动。例如在mysql使用环境中,则需要下载mysql对应的驱动程序
mysql-connector-java-xxx.java; - 在应用中加载驱动。例如使用
Class.forName()的方式将驱动类加载到内存中; - 创建数据库连接对象。在接口
Driver中定义了相应的连接方式; - 创建
Statement对象。Statement类的主要是用于执行静态SQL语句并返回它所生成结果的对象。通过Connection对象的createStatement()方法可以创建一个Statement对象。例如:Statement statament = connection.createStatement(); - 调用
Statement对象的相关方法执行相对应的 SQL 语句; - 关闭数据库连接:使用完数据库或者不需要访问数据库时,通过
Connection.close()方法及时关闭数据连接。
示例
1、数据准备
现在mysql数据库中创建person表,并插入需要的数据
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for blog
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`mobile` varchar(11) COLLATE utf8mb4_general_ci DEFAULT NULL,
`age` int(2) DEFAULT NULL,
`email` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of blog
-- ----------------------------
BEGIN;
INSERT INTO `person` VALUES (1, 'wujiwen', '13011111111', 20, 'jiwenwu@outlook.com');
INSERT INTO `person` VALUES (2, 'mybatis', '13100000000', 10, 'service@mybatis.com');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
2、引入mysql驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
3、使用JDBC连接数据库
按照上面的步骤,我们先将特定厂商Mysql的驱动加载到内存中,然后通过Driver实例获取数据库连接
private final String url = "jdbc:mysql://127.0.0.1:3306/mybatis";
private final String user = "root";
private final String password = "passw0rd";
private final String mysqlDriver = "com.mysql.cj.jdbc.Driver";
public Connection getConnectionByProperties() throws Exception {
Properties properties = new Properties();
properties.put("user",user);
properties.put("password",password);
// 加载驱动实例
Driver driver = ((Driver) Class.forName(mysqlDriver).newInstance());
// 获取链接
return driver.connect(url,properties);
}
public Connection getConnectionByUserPassword() throws Exception {
// 加载驱动实例
Class.forName(mysqlDriver);
// 通过DriverManager获取
return DriverManager.getConnection(url, user, password);
}
当使用Class.forName(mysqlDriver)加载驱动类到内存中的时候,同时会执行这个驱动类中的静态代码块,创建一个Driver实例;然后调用DriverManager 进行注册Driver;DriverManager 作为 Driver 的管理器,它在第一次被调用的时候,它会被加载到内存中,然后执行其定义的静态代码段,在静态代码段中,有一个 loadInitialDrivers() 静态方法,用于加载配置在jdbc.drivers 系统属性内的驱动Driver,DriverManager来统一管理操作Driver和获取Connection对象;
4、增删改查
列举最简单的sql操作示例
public int insert(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
return statement.executeUpdate("insert into `person` (nickname,mobile,age,email) values ('insert', '13100000000', 14, 'insert@mybatis.com');");
}catch (Exception e){
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
connection.close();
}
return 0;
}
public int update(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
return statement.executeUpdate("update `person` set mobile = '12000000000' where id = 4;");
}catch (Exception e){
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
connection.close();
}
return 0;
}
public int delete(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
return statement.executeUpdate("delete `person` where id = 4;");
}catch (Exception e){
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
connection.close();
}
return 0;
}
public List<Person> listPerson(Connection connection) throws SQLException {
List<Person> personList = new ArrayList<>();
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from `person`;");
while (resultSet.next()){
Person person = new Person();
// 指定列名方式获取
Integer id = resultSet.getInt("id");
// 指定列索引方式获取,startIndex = 1
String nickname = resultSet.getString(2);
String mobile = resultSet.getString("mobile");
Integer age = resultSet.getInt(4);
String email = resultSet.getString("email");
person.setId(id);
person.setNickname(nickname);
person.setMobile(mobile);
person.setAge(age);
person.setEmail(email);
personList.add(person);
}
}catch (Exception e){
e.printStackTrace();
}finally {
connection.close();
}
return personList;
}
JDBC简化方案
原生方式不仅硬编码多而且非常的不灵活,对于结果的封装处理也比较麻烦。这时候也出现了一些比较好用的简化操作方案,例如常见的Hibernate,DBUtils,Mybatis。本文将简单的介绍一下DBUtils是如何简化数据的查询和操作的。
DBUtils
该组件严格上说不是一款持久化框架,更多的可以理解成一款简化操作工具集合,将原生JDBC的很多动态化操作进行了封装,方便了使用
核心功能介绍
- QueryRunner类,提供了对sql语句的各种api
- ResultSetHandler接口,用于定义查询操作后,如何对结果进行封装
- DbUtils工具类,里面封装了很多关闭资源及处理事务的方法
示例
private final String url = "jdbc:mysql://127.0.0.1:3306/mybatis";
private final String user = "root";
private final String password = "passw0rd";
private final String mysqlDriver = "com.mysql.cj.jdbc.Driver";
public Connection getConnection() throws Exception {
Class.forName(mysqlDriver);
return DriverManager.getConnection(url, user, password);
}
public int insert(Connection connection) throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "insert into `person` (nickname,mobile,age,email) values (?,?,?,?);";
Object[] params = {"dbutils", "12000000000", 10, "dbutils@dbutils.com"};
return runner.update(connection, sql, params);
}
public int update(Connection connection) throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "update `person` set mobile = '00000000000' where id = ?";
Object params = 5;
return runner.update(connection,sql,params);
}
public int delete(Connection connection) throws SQLException{
QueryRunner runner = new QueryRunner();
String sql = "delete `person` where id = ?";
Object params = 5;
return runner.update(connection,sql,params);
}
// 查询单个对象
public Person getPerson(Connection connection) throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "select * from `person` where id = ? ";
Object params = 1;
return runner.query(connection,sql,new BeanHandler<>(Person.class),params);
}
// 查询集合对象
public List<Person> listPerson(Connection connection) throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "select * from `person`";
return runner.query(connection,sql,new BeanListHandler<>(Person.class));
}
这时候我们会发现动态sql的编写也比较简单了,参数的设置比较灵活,特别是对于查询结果的封装变得容易多了。
但是还有很多不足的地方,例如如果将nickname修改成username,这种情况就无法准确的对应的bean结果集。我们也可以对其进行改造,添加相应的别名方式处理。
相对于Hibernate的庞大和繁琐,我们更推荐Mybatis去处理。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
后续将简单演示mybatis是如何处理这些问题的,并了解这背后的相关原理及实现方式。
【Mybatis源码解析】- JDBC连接数据库的原理和操作的更多相关文章
- Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了
这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...
- mybatis源码-解析配置文件(三)之配置文件Configuration解析
目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...
- Mybatis源码解析,一步一步从浅入深(一):创建准备工程
Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...
- Mybatis源码解析,一步一步从浅入深(三):实例化xml配置解析器(XMLConfigBuilder)
在上一篇文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码 ,中我们看到 代码:XMLConfigBuilder parser = new XMLConfigBuilder(read ...
- Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例
在Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们看到了XMLConfigBuilder(xml配置解析器)的实例化.而且这个实例化过程在文章:Mybatis源码解析,一步一步从浅 ...
- Mybatis源码解析,一步一步从浅入深(七):执行查询
一,前言 我们在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码的最后一步说到执行查询的关键代码: result = sqlSession.selectOne(command.ge ...
- Mybatis源码解析(一) —— mybatis与Spring是如何整合的?
Mybatis源码解析(一) -- mybatis与Spring是如何整合的? 从大学开始接触mybatis到现在差不多快3年了吧,最近寻思着使用3年了,我却还不清楚其内部实现细节,比如: 它是如 ...
- Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?
Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的? 如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
随机推荐
- SpringBoot注解集合
使用注解的优势: 1.采用纯java代码,不在需要配置繁杂的xml文件 2.在配置中也可享受面向对象带来的好处 3.减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 @SpringBo ...
- SpringBoot(二): SpringBoot属性配置文件 SpringBoot多环境配置文件 SpringBoot自定义配置文件
1.属性配置文件 一共分为两种,一种是键值对的properties属性配置文件,一种是yaml格式的配置文件 properties配置: 2.多环境配置文件 当我们的项目中有多套配置文件 比如开发的配 ...
- 二叉树、平衡二叉树、红黑树、B树、B+树与B*树
转: 二叉树.平衡二叉树.红黑树.B树.B+树与B*树 一.二叉树 1️⃣二叉查找树的特点就是左子树的节点值比父亲节点小,而右子树的节点值比父亲节点大,如图: 基于二叉查找树的这种特点,在查找某个节点 ...
- 全局解决Vue跳转相同路由导致报错的问题
大家使用Vue做开发的时候应该都遇到过这个问题,就是某个页面下调用this.$router.push(path),而path指向的页面和当前页面是同一页面时,就会发生报错,vue-router会提示你 ...
- 抽一根烟的时间学会.NET Core 操作RabbitMQ
什么是RabbitMQ? RabbitMQ是由erlang语言开发的一个基于AMQP(Advanced Message Queuing Protocol)协议的企业级消息队列中间件.可实现队列,订阅/ ...
- C语言之结构体内存的对齐
C语言之结构体内存的对齐 大纲: 零.引例 一.结构体内存对齐规则 二.怎样计算结构体的大小 三.设计结构体时要注意的方面 四.为什么存在内存对齐 五.修改默认对齐数 在前面的章节中,我们谈到了C ...
- windows下MySQL如何完全卸载并安装行的版本
卸载本地mysql之前,请务必要先将需要的数据库备份 停止mysql 服务 windows键-->搜索服务 找到mysql 服务,并停止他 卸载mysql server 在控制面板--程序 找到 ...
- P3388 【模板】割点(割顶) 题解 (Tarjan)
题目链接 P3388 [模板]割点(割顶) 解题思路 最近学的东西太杂了,多写点博客免得自己糊里糊涂的过去了. 这个题求割点,感觉这篇文章写得挺好. 割点是啥?如果去掉这个点之后连通图变成多个不连通图 ...
- U盘重装系统:手把手教你怎么使用U盘重装系统、清除登录密码
前言 之前讲过<不懂电脑也能自己重装系统,可视化傻瓜式一键重装系统不求人!!!>,这是针对可以正常开机的情况下直接使用浏览器功能重装系统, 那不能正常开机或者忘记密码的怎么办呢? 不慌,今 ...
- android分析之Thread类
线程与线程类要区分开来. 抽象来说,线程是CPU调度的最小单位,但是线程总要执行代码,这个代码就在线程类里说明(即Thread类).无论如何,Thread只是一个类,但其功能就是"启动一个线 ...