1.Connection/Statement/ResultSet接口
如下jdbc是父类引用
如下mchange. .和c3p0. .一起。
如下代码第一行new Driver()是导入com.mysql.jdbc(用mysql实现好的,就是上面导入的mysql-connector..jar包)
而不是java.sql(自己不会重写抽象方法)下,参数是接口类型需要传入接口的实现类对象即new Driver()。
如下DriverManager等4个都是java.sql包下的。registerDriver相当于set方法,get获取的是mysql.Driver.connect方法返回的Connection类即com.mysql.jdbc.JDBC4Connection。
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驱动包的彻底解耦
*/
// 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();
}
}
不是返回一行数据,而是带有id=…。返回一行数据如 10孙悟空男,不知道怎么解析。
2.释放资源
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);
}
}
//1111111111111111111111111111111111111111111111111111111111111111111
private static void closeIo(AutoCloseable... ios) {
for (AutoCloseable io : ios) {
if(io != null){
try {
io.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
3.工具类封装
package com.itheima05.utils;
import java.sql.*;
/**
* 作者: 大师兄
* 时间: 2019-10-07
* 用途: 你猜
* 参照 : xx
*
* 工具类:
* 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
/**
* 作用: 获取连接
* @return 连接
*/
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
/**
* 文档注释 -> /** xx *斜杠
* a. 写在类上面 : 描述类的用途
* b. 写在方法上面 : 描述方法的用途 (返回值,参数)
* @param conn
* @param statement
* @param resultSet
*/
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();
}
}
}
}
B站/知乎/微信公众号:码农编程录