Mysql3jdbc:DriverManager.getConnection(url, user, pwd)
Posted 码农编程录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql3jdbc:DriverManager.getConnection(url, user, pwd)相关的知识,希望对你有一定的参考价值。
文章目录
1.四个接口:左java.sql包下的DCSR,右com.mysql.jdbc.Driver
如下jdbc是父类引用。
如下mchange. .和c3p0. .一起。第一个导入的是mysql-connector…。
如下代码第一行new Driver()是导入com.mysql.jdbc(用mysql实现好的,就是上面导入的mysql-connector..jar包)
而不是java.sql(自己不会重写抽象方法)下,参数是接口类型需要传入接口的实现类对象即new Driver()。
registerDriver相当于set方法,get获取的是mysql.Driver.connect方法返回的Connection类即com.mysql.jdbc.JDBC4Connection(有mysql.的都是导入的jar包)。
package com.itheima01.jdbc;
import com.mysql.jdbc.Driver;
import java.sql.*;
public class JdbcDemo {
public static void main(String[] args) throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException {
//1. 注册驱动 (注意: 导入的mysql的驱动)
/*
* A. 查看mysql.Driver源码: 点new Driver()中Driver看源码
* 发现static 代码块里 已经注册了驱动 -> 驱动自注册 相当于set一次就行
* 带来问题: 外部的注册没有意义(重复注册)
*
* 解决: 保证mysql.Driver类被加载(静态代码块就会执行),如下两种方案:
* 1. 创建对象
* 2. 反射:a. 节省内存
* b. 跟驱动包的关联只剩一个字符串:"com.mysql.jdbc.Driver"
* 待会将字符串写入配置文件,只要改配置文件就行 就会跟 mysql驱动包的彻底解耦
*/
//111111111111111111111111111111111111111111111111111111111111111111111111111111111111
// DriverManager.registerDriver(new Driver()); //这行重复注册,下行new了就会加载源码里的静态代码块,所以这行=下行
//new Driver(); // Class对象 + 普通实例 //只要用了这个类,这个类就会被加载内存中方法区 //自动导包
// new Driver()的内存消耗等价于下面两行: 其实只需要calss对象,不需要实例
// Class<?> clazz = Class.forName("com.mysql.jdbc.Driver"); //获取这个类的class对象
// Object obj = clazz.newInstance(); //利用class对象调用其空参构造来创建一个实例
Class.forName("com.mysql.jdbc.Driver"); //Class对象,没有普通实例,因为普通实例没有意义 //用反射,com.mysql.jdbc.Driver这个类也会被加载
//111111111111111111111111111111111111111111111111111111111111111111111111111111111111
//2. 获取连接
/*
* 只要涉及两个软件通信 : 网络三要素(必要非充分:一定要,但是有它们三不一定够如多了资源位置)
* 1. 协议 : jdbc:mysql (主协议:子协议)
* 2. ip : 数据库所在的计算机(自己:localhost或127.0.0.1)
* 3. port : mysql数据库3306
* 资源位置: 数据仓库的名称
*
* 协议://ip:port/资源位置
* https://www.baidu.com:443
*/
// String url = "jdbc:mysql://localhost:3306/day03"; //day03是数据库
String url = "jdbc:mysql:///day03"; //ip:localhost port:3306 可以省略
String user = "root";
String pwd = "1234";
Connection conn = DriverManager.getConnection(url, user, pwd);
System.out.println("conn:" + conn); //引用类型打印地址
//1111111111111111111111111111111111111111111111111111111111111111111111111111111111
//3. 创建执行sql的语句对象
/*
* Connection 接口的一些方法
* <1>. Statement createStatement(); 创建执行sql的语句对象,相当于创建一个流
* <2>. PreparedStatement prepareStatement(sql); 创建一个预编译sql的语句对象
* <3>. 事务操作相关
*/
Statement statement = conn.createStatement();
System.out.println("statement:" + statement);
//11111111111111111111111111111111111111111111111111111111111111111111111111111111111
//4. 执行sql,返回结果
/*
* Statetment 接口的api
* 1. ResultSet statement.executeQuery(sql);
* 执行的查询语句 : DQL
* 返回的查询结果: 结果集
*
* 2. int executeUpdate(sql) :
* 执行的增删改语句: DML
* 返回的结果: 被影响的行数
*
* 3. boolean execute(sql); -> 不需要掌握,知道即可
* 万能 : DDL等 如create成功或失败是和异常相关,和返回值无关
* 返回值: 非查询语句返回false,查询语句返回true
*/
String sql = "select * from emp";
ResultSet resultSet = statement.executeQuery(sql);
//11111111111111111111111111111111111111111111111111111111111111111111111111111111111
//5. 处理结果
while(resultSet.next()){
String name = resultSet.getString("name");
// String id = resultSet.getString("id"); //也可以,java程序以外的所有数据对java来说都是字符串
int id = resultSet.getInt("id"); //底层先调用getString再parse int
System.out.println(id+ ":" + name);
}
//11111111111111111111111111111111111111111111111111111111111111111111111111111111111
//6. 释放资源
resultSet.close();
statement.close();
conn.close();
}
}
resultset不是返回一行数据,而是带有id=…。因为返回一行数据如 11孙悟空男,不知道怎么解析。
2.释放资源:finally
package com.itheima04.release;
import com.itheima05.utils.JdbcUtil;
import java.io.Closeable;
import java.io.IOException;
import java.sql.*;
public class ReleaseDemo {
public static void main(String[] args) {
ResultSet resultSet = null;
Statement statement = null;
Connection conn = null;
try {
/*Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/day03";
String user = "root";
String pwd = "1234";
conn = DriverManager.getConnection(url, user, pwd);*/
conn = JdbcUtil.getConnection(); //查询要获取连接,getConnection方法调用多遍,所以getConnection方法不写try catch,查询提示 查询失败,删除提示 删除失败,封装时不知道是查询还是删除,不好提示,所以往外抛。
conn = JdbcUtil.getConnection(); //增删改也要获取连接
//111111111111111111111111111111111111111111111111111111111111111111111111
statement = conn.createStatement();
String sql = "select * from emp";
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
String name = resultSet.getString("name");
System.out.println(name);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
/* if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}*/
// closeIo(resultSet,statement,conn);
JdbcUtil.release(conn,statement,resultSet);
}
}
//1111111111111111111111111111111111111111111111111111111111111111111111
private static void closeIo(AutoCloseable... ios) { //AutoCloseable接口位于java.lang包下,不用导包
for (AutoCloseable io : ios) {
if(io != null){
try {
io.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
3.工具类封装:new Properties()
package com.itheima05.utils;
import java.sql.*;
/**
* 工具类:
* 0. 拥有很多 工具方法(重复的代码封装) 的类
* 命名规范: utils 包 -> xxUtil 类 (xx : 某个模块的名称)
* Objects,Arrays,Collections...(JDK提供的)
*
* 1. 一般工具类中方法是静态的,不用实例化,节省内存
*
* 2. 封装方法的步骤
* 1. 先把要把封装的代码写出来
* 2. 观察不断重复的部分
* 3. 定义方法,然后直接复制过来
* 4. 设置参数和返回值
*
* 注意点:
* 1. 扩展性 : 不要导入mysql包中的类, 要导入java包中的类(因为换成oracle也可用)
* 2. 工具类中的异常一般是往外抛 : 一般异常是要在业务中处理
*/
public class JdbcUtil {
static{
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//1111111111111111111111111111111111111111111111111111111111111111111111111111111
public static Connection getConnection() throws SQLException {
//此方法会被多次调用,注册驱动只需要一次 -> 所以用静态代码块 如上
// Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/day03";
String user = "root";
String pwd = "1234";
Connection conn = DriverManager.getConnection(url, user, pwd);
return conn;
}
//1111111111111111111111111111111111111111111111111111111111111111111111111111111
/**
* 文档注释:
* a. 写在类上面 : 描述类的用途
* b. 写在方法上面 : 描述方法的用途 (返回值,参数)
*/
public static void release(Connection conn, Statement statement, ResultSet resultSet){
//java.sql.Connection
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
如下改进上面工具类。
/*
* 问题: 驱动,url,用户名和密码等信息 是有可能会变的, 变动频率比较低
* 1. 如果不变,直接写死在代码中
* 2. 变,但是频率高 : 一般设置成参数
* 3. 变,但是频率不高: 放在配置文件
* 1. 解耦 : 信息要改变的话,只要改配置文件,代码不用改,程序不需要重新编译和部署
* 2. 代码简化 : 无需调用的时候传参了
*/
//jdbc.properties文件,每个月改一次 //文件里没有关键字,也没有双引号,本来就是字符串
driverName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/day03
user = root
pwd = 1234
package com.itheima05.utils;
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtil02 {
static String driverName;
static String url;
static String user;
static String pwd;
static{
try {
Properties p = new Properties();
p.load(new FileInputStream("src/jdbc.properties"));
driverName = p.getProperty("driverName");
url = p.getProperty("url");
user = p.getProperty("user");
pwd = p.getProperty("pwd");
Class.forName(driverName);
} catch (Exception e) {
e.printStackTrace();
}
}
//1111111111111111111111111111111111111111111111111111111111111111111111111111111111
public static Connection getConnection() throws SQLException {
Connection conn = DriverManager.getConnection(url, user, pwd);
return conn;
}
//11111111111111111111111111111111111111111111111111111111111111111111111111111111111
public static void release(Connection conn, Statement statement, ResultSet resultSet){
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
4.总结: SPI (Service Provider Interface), API (Application Programming Interface)
JDBC是java的数据库连接规范,里面有两个重要的接口:Driver接口
定义了一个connect方法,也就是说你通过一个第三方数据库的Driver,运行它的connect方法(输入连接的字符串)就能得到一个Connection类型的对象。
Connection本身也是一个接口,Connection中定义了许多具体的执行sql方法,也就是我们真正操作数据库最核心的接口类就是Connection接口
。它的方式就是各家的数据库分别去实现一系列JDBC定义的接口中的方法。
如下是接口的开发模式即没有涉及到打破双亲委派和SPI,是jdbc早期的开发方式。
如下.getConnection方法中有registerDriver(通过类加载器),还是要实体的数据库jar包,但不需要程序import。
如下SPI配置:文件名就是需要实现的接口的全限定名即java.sql.Driver 。第一个java.sql.Driver文件里写的是org.h3.Driver(org.h3.Driver这个类实现java.sql.Driver接口),第二个java.sql.Driver写的是com.mysql.cg.jdbc.Driver。
打破双亲类加载机制:DriverManager是jdk自带的类,DriverManager类使用的是bootstrap引用类加载器
,数据库是用户类用bootstrap加载不合适,所以DriverManager去加载h2的Driver需要把当前引用类加载器替换为当前系统或当前线程的应用app类加载器
。
以上是关于Mysql3jdbc:DriverManager.getConnection(url, user, pwd)的主要内容,如果未能解决你的问题,请参考以下文章
UnsupportedOperationException 与 Android 上的 DriverManager.getConnection()