写在前面:
我是「沸羊羊_」,昵称来自于姓名的缩写 fyy ,之前呕心沥血经营的博客因手残意外注销,现经营此账号。
本人是个小菜,正向着全栈工程师的方向努力着,文章可能并不高产,也很基础,但每写一篇都在用心总结,请大佬勿喷。
如果您对编程有兴趣,请关注我的动态,一起学习研究。
感谢每位读者!
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
//连接数据库
public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
//1、导入驱动jar包
//mysql-connector-java.jar
//2、注册驱动(将异常抛出)
Class.forName("com.mysql.jdbc.Driver");
//3、获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://xxx.xxx.xxx.xxx:3306/dbName?characterEncoding=utf-8","root","123456");
//4、定义sql语句
String sql = "update worker_info set WorkerName = '测试' where WorkerId = 3456";
//5、获取执行 sql 的对象 Statement
Statement stmt = conn.createStatement();
//6、执行 sql
int count = stmt.executeUpdate(sql);
//7、处理结果
System.out.println(count);
//8、释放资源
stmt.close();
conn.close();
}
}
当我们导入完jar包,连接数据库的第一个步骤就是 Class.forName,它有什么作用?
Class.forName() 方法要求JVM查找并加载指定的类到内存中,此时将"com.mysql.jdbc.Driver" 当做参数传入,就是告诉JVM,去"com.mysql.jdbc"这个路径下找Driver类,将其加载到内存中。
由于加载类文件时会执行其中的静态代码块,其中Driver类的源码如下。
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());//首先new一个Driver对象,并将它注册到DriverManage中
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
接下来我们再看看这个DriverManager.registerDriver 方法。
public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException {
registerDriver(driver, null);
}
继续看registerDriver方法做了什么。
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();// registeredDrivers 是一个支持并发的arraylist
public static void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException {
if (driver != null) {
//如果该驱动尚未注册,那么将他添加到 registeredDrivers 中去。这是一个支持并发情况的特殊ArrayList
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
此时,Class.forName(“com.mysql.jdbc.Driver”) 的工作就完成了,工作就是:将mysql驱动注册到DriverManager中去。
功能
将mysql驱动注册到DriverManager中之后,我们就可以通过DriverManager的getConnection方法获得mysql的连接了:
Connection conn = DriverManager.getConnection("jdbc:mysql://xxx.xxx.xxx.xxx:3306/dbName?characterEncoding=utf-8","root","123456");
接下来看看 getConnection()方法。
@CallerSensitive
public static Connection getConnection(String url, String user, String password) throws SQLException {
....
return (getConnection(url, info, Reflection.getCallerClass()));
}
DriverManager调用了自身的 getConnection()方法。
private static Connection getConnection(String url, java.util.Properties info, Class<?> caller) throws SQLException {
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
// 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 {
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
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;
}
throw new SQLException("No suitable driver found for "+ url, "08001");
}
可以看到它对上文提到的静态变量 registeredDrivers 进行了遍历,调用了connect(url, info)方法,这是一个接口,由各个不同的驱动自己实现。
/**
* Attempts to make a database connection to the given URL.
* The driver should return "null" if it realizes it is the wrong kind
* of driver to connect to the given URL. This will be common, as when
* the JDBC driver manager is asked to connect to a given URL it passes
* the URL to each loaded driver in turn.
*/
Connection connect(String url, java.util.Properties info)
throws SQLException;
到此为止,我们就获得了connection对象,现在就可以对数据库进行操作了。
连接数据库时,需要获取一个可以执行sql语句的对象,Connection类的createStatement 方法就是创建一个 statement 对象来将SQL语句发送到数据库。
createStatement()方法有很多重载方法,最常用的就是执行不带参数的SQL语句。
简单介绍除无参的createStatement()方法外的两个重载方法。
语法一:
创建一个 Statement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。此方法与上述 createStatement 方法相同,但它允许重写默认结果集类型和并发性。已创建结果集的可保存性可调用 getHoldability() 函数来确定。
Statement createStatement(int resultSetType,int resultSetConcurrency)throws SQLException
参数说明:
示例:
本示例获得了一个 Statement 对象,并发类型为只读,结果集类型光标只能向前移动。
Connection conn = …… //省略部分代码
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); //创建Statement对象
语法二:
Statement createStatement(int resultSetType,int resultSetConcurrency,int resultSetHoldability)throws SQLException
参数说明:
示例:
本示例获得了一个 Statement 对象,并发类型为只读,结果集类型光标只能向前移动,具有此可保存性的打开的 ResultSet 对象将保持开放。
Connection conn = …… //省略部分代码 //创建Statement对象
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
正确打开方式:
ResultSet rs = null;
//循环判断游标是否指向最后一行末尾
while (rs.next()){
//获取数据
}
目的:
实现:
//JDBCUtil.java
package cn.itcast.util;
import com.sun.javafx.css.CssError;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/*
• JDBC工具类
• */
public class JDBCUtil {
private static String url;
private static String user;
private static String password;
private static String driver;
/*
• 文件读取,只需要读取一次即可,使用静态代码块
• */
static {
//读取资源文件,获取值
try {
//1、创建Properties 集合类
Properties pro = new Properties();
//获取src路径下的文件方式--> ClassLoader 类加载器
ClassLoader classLoader = JDBCUtil.class.getClassLoader();
//使用 类加载器 获取资源
URL res = classLoader.getResource("jdbc.properties");
//不符合条件即断言
assert res != null;
//获取路径
String path = res.getPath();
//2、加载文件
//pro.load(new FileReader("src/jdbc.properties"));
pro.load(new FileReader(path));
//3、获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4、注册驱动
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
//释放资源
public static void close(Statement stmt,Connection conn){
if (stmt!=null){
try {
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn!=null){
try {
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
public static void close(ResultSet rs,Statement stmt, Connection conn){
if (rs!=null){
try {
rs.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (stmt!=null){
try {
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn!=null){
try {
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
以上为小编学习总结记录,如有错误,请大佬指出,不胜感激。