当前位置:网站首页>JDBC回顾
JDBC回顾
2022-07-02 06:34:00 【程序源程序】
JDBC介绍
百度百科:Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
个人理解:
没有JDBC:因为各个数据库软件都是自成体系,对外提供服务时没有统一标准,不像http接口,因为http协议的存在及约束,对接一个新接口非常方便。且数据库连接本身也非常复杂,当我们需要连接不同数据库时,自己手写连接不现实,使用数据库厂商提供的工具连接自然可以,但开发限制较大,不同数据库的连接,执行,结果集处理均不能保证一致,应用切换数据库代价更是无比巨大,可能换一个数据库,数据库连接查询及结果处理的代码全部需要重写,bug也会更多。
JDBC意义:JAVA提供统一的数据库访问API,仅仅是一套标准,一系列规范化的操作。且不提供具体实现,而是不同数据库开发商根据jdbc标准提供具体实现,如何实现不需要开发者关心。这样可以做到,对数据库的连接,执行,结果集处理使用同一套规范与标准,提高开发效率与容错率,降低开发难度及与数据库的耦合度。
JDBC使用与测试
造数据
建表
CREATE TABLE `t_test`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`code` VARCHAR(32) DEFAULT NULL COMMENT '编码',
`name` VARCHAR(64) DEFAULT NULL COMMENT '名称',
PRIMARY KEY (`id`)
)
插入数据
INSERT INTO t_test(CODE, NAME) VALUES(‘ZS’,‘张三’), (‘LS’,‘李四’), (‘ZL’,‘张龙’), (‘ZH’,‘赵虎’);
查询
示例代码
public class MainTest {
public static void main(String[] args) throws Exception {
// 1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.创建连接
Connection mysqlConnection = DriverManager.getConnection(
"jdbc:mysql://host:port/dbName",
"username ",
"password"
);
// 3.创建statement,用于执行静态sql
Statement statement = mysqlConnection.createStatement();
// 4.执行查询sql,会返回结果集
String sql = "select * from t_test;";
ResultSet resultSet = statement.executeQuery(sql);
// 5.读取结果集
while (resultSet.next()) {
System.out.println(resultSet.getString("code")+" : "+resultSet.getString("name"));
}
}
}
解读
上述使用jdbc执行一个查询并处理返回值共分五步:
- 加载驱动
- 创建连接
- 创建statement,用于执行静态sql
- 执行查询sql,会返回结果集
- 读取结果集
为何要加载驱动
Class.forName(“com.mysql.cj.jdbc.Driver”);
这一步根据字面意思,使用Class类,去加载名为“com.mysql.cj.jdbc.Driver”的类,即加载mysql的驱动。乍一看简直是一脸懵逼,这句代码就能加载驱动了?而且为什么要加载驱动?没这么写过代码呀!
试着慢慢分析吧,首先Class.forName !
Java class在没有被需要用到时,是不会被加载到JVM内存中。当我们new一个从没用过的类时,JVM首先会去找这个类有么有在内存中,没有的话会先去加载这个类,然后
com.mysql.cj.jdbc.Driver源码:
package com.mysql.cj.jdbc;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
/** * Construct a new driver and register it with DriverManager * * @throws SQLException * if a database error occurs. */
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}
static代码块会在类被加载时执行,其他也没了,而static中就一句代码java.sql.DriverManager.registerDriver(new Driver());
注册了一个实现java.sql.Driver的mysql驱动,即把mysql厂商提供的驱动注册到了驱动管理器中,具体作用肯定是供后续使用,这里暂时无法明确用途。
创建连接
Connection mysqlConnection = DriverManager.getConnection(
"jdbc:mysql://host:port/dbName",
"username ",
"password"
);
创建连接阶段会根据提供的数据库信息进行数据库连接创建,这一步就需要连接具体的mysql数据库了,除了用户名、密码、数据库地址信息,似乎没有看到如何告诉jvm需要连mysql还是oracle或者其他数据库,url中倒是有mysql字样,难道用的这个连的?
先看下创建连接的代码:
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
/* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) * classloader, so that the JDBC driver class outside rt.jar * can be loaded from here. */
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
// Walk through the loaded registeredDrivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");
}
Connection con = aDriver.driver.connect(url, info);
这里可以看到,遍历已注册的驱动,挨个调用驱动创建连接,这里java只提供了接口,即Driver.connect.并没有提供具体实现,而是各个数据库厂商自己提供实现,提供如何去连接他们的数据库,返回一个可用的连接。
而这个驱动注册就是第一步加载驱动的意义:需要主动把厂商的驱动注册到jdbc的驱动管理器中,这样用户创建数据库连接时,jdbc的驱动管理器就使用已注册的驱动去创建对应数据库的连接。
如果项目中同时连接多种数据库,如果区分需要连哪个呢?
Jdbc不做决策,而是遍历所有驱动,挨个去创建连接,谁先创建成功了,就返回谁的连接。
注意
当前jdbc已经不需要手动加载驱动了,新的驱动管理器的静态代码块中已经自动进行了驱动加载。
public class DriverManager {
…
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
…
}
方式为遍历寻找所有java.sql.Driver接口的实现类,然后挨个执行Class.forName(XXX);
增删改查
private static void test_query() throws Exception {
String sql = "select * from t_test;";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getString("code")+" : "+resultSet.getString("name"));
}
}
private static void test_insert() throws Exception {
String sql = "INSERT INTO t_test(CODE, NAME) VALUES('ZS','张三'), ('LS','李四'), ('ZL','张龙'), ('ZH','赵虎');";
boolean result = statement.execute(sql);
System.out.println(result);
}
private static void test_update() throws Exception {
transaction(false);
String sql = "UPDATE t_test set name='张66' where code='ZS'";
boolean result = statement.execute(sql);
System.out.println(result);
commit();
}
private static void test_delete() throws Exception {
String sql = "DELETE FROM t_test WHERE code IN ('ZS', 'LS', 'ZL', 'ZH');";
boolean result = statement.execute(sql);
System.out.println(result);
}
事务控制
事务控制在connection层,默认是自动提交的,如果需要进行事务控制及业务回滚,需要将自动提交事务设置为false,然后可以在发生异常或者业务错误的情况下手动执行rollback回滚事务,或者在执行完成后手动执行commit提交事务。
// 将自动提交事务设置为false
mysqlConnection.setAutoCommit(false);
try{
// do something
} catch (SQLException e) {
e.printStackTrace();
//手动执行rollback回滚事务
mysqlConnection.rollback();
}
//手动执行commit提交事务
mysqlConnection.commit();
后续待补充
边栏推荐
- In depth analysis of how the JVM executes Hello World
- "Redis source code series" learning and thinking about source code reading
- Matplotlib剑客行——布局指南与多图实现(更新)
- 企业级SaaS CRM实现
- Chrome浏览器插件-Fatkun安装和介绍
- [staff] time mark and note duration (staff time mark | full note rest | half note rest | quarter note rest | eighth note rest | sixteenth note rest | thirty second note rest)
- 定时线程池实现请求合并
- Methods of classfile
- 洞见云原生|微服务及微服务架构浅析
- Watermelon book -- Chapter 6 Support vector machine (SVM)
猜你喜欢
Pool de connexion redis personnalisé
Programmers with ten years of development experience tell you, what core competitiveness do you lack?
[go practical basis] how to verify request parameters in gin
Knowledge points are very detailed (code is annotated) number structure (C language) -- Chapter 3, stack and queue
During MySQL installation, mysqld Exe reports that the application cannot start normally (0xc000007b)`
自定义Redis连接池
Chrome user script manager tempermonkey monkey
Matplotlib剑客行——初相识Matplotlib
Bold prediction: it will become the core player of 5g
Cloudreve自建云盘实践,我说了没人能限制得了我的容量和速度
随机推荐
Knife4j 2. Solution to the problem of file control without selection when uploading x version files
Microservice practice | declarative service invocation openfeign practice
机器学习之数据类型案例——基于朴素贝叶斯法,用数据辩男女
[go practical basis] how to install and use gin
《统计学习方法》——第五章、决策树模型与学习(上)
Mathematics in machine learning -- point estimation (I): basic knowledge
MySql报错:unblock with mysqladmin flush-hosts
聊聊消息队列高性能的秘密——零拷贝技术
Discussion on improving development quality and reducing test bug rate
Microservice practice | teach you to develop load balancing components hand in hand
Matplotlib swordsman line - layout guide and multi map implementation (Updated)
The channel cannot be viewed when the queue manager is running
Watermelon book -- Chapter 6 Support vector machine (SVM)
Chrome用户脚本管理器-Tampermonkey 油猴
Knowledge points are very detailed (code is annotated) number structure (C language) -- Chapter 3, stack and queue
Enterprise level SaaS CRM implementation
Ora-12514 problem solving method
告别996,IDEA中必装插件有哪些?
[staff] common symbols of staff (Hualian clef | treble clef | bass clef | rest | bar line)
idea查看字节码配置