JDBC学习笔记
1. JDBC概念
- JDBC就是使用Java语言操作关系型数据库的一套API
- java研发者定义一套规则(接口),数据库厂商提供实现类(驱动)
- 面向接口编程
2. JDBC快速入门
2.1 导入驱动jar包
- jar包拷贝进工程里
- Add as library
2.2 mysql.properties
user=root
password=****
url=jdbc:mysql://localhost:3306/db01
driver=com.mysql.cj.jdbc.Driver
2.3 JDBC
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Date;
import java.util.Properties;
public class ResultSet_ {
public static void main(String[] args) throws Exception {
//创建properties对象
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//注册驱动
Class.forName(driver);
//创建连接
Connection conn = DriverManager.getConnection(url, user, password);
//SQL语句
String sql = "insert t1 values(1,'aw','****',0101)";
//stmt是用来执行SQL的对象
Statement stmt = conn.createStatement();
//执行SQL
int count = stmt.executeUpdate(sql);//count是受影响的行数
//打印结果
System.out.println(i);
//释放资源
stmt.close();
conn.close();
}
}
3 JDBC API
3.1 DriverManager
用于管理一组JDBC驱动的基本服务。
3.1.1 Driver.class
package com.mysql.cj.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
3.1.2 DriverManager(驱动管理类)的作用
注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
MySQL 5之后的驱动包,可以省略不写上面这句代码↑,原因:
-
Driver.class源码里有静态代码块,可以在类加载的时候自动执行
-
自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
获取连接
Connection conn = DriverManager.getConnection(url, user, password);
-
url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…
示例:jdbc:mysql://127.0.0.1:3306/db01
细节:
-
如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,可简写为:
jdbc:mysql:///数据库名称?参数键值对1&参数键值对2…
-
配置useSSL=false(别加空格)参数,禁用安全连接方式,解决警告提示
-
-
user:用户名
-
password:密码
3.2 Connection
3.2.1 获取执行SQL的对象
-
普通执行SQL对象
Statement stmt = conn.createStatement();
-
预编译SQL的执行SQL对象:防止SLQ注入
PreparedStatement ps = conn.prepareStatement(sql);
-
执行存储过程的对象
CallableStatement cs = conn.prepareCall(sql);
3.2.2 事务管理
-
MySQL事物管理
#开启事务 BEGIN;#或者 START TRANSACTION; #提交事务 COMMIT; #回滚事务 ROLLBACK; #MySQL默认自动提交事物
-
JDBC事务管理:Connection接口中定义了3个对应的方法
try{ //开启事务 conn.setAutoCommit(false); //执行SQL int count1 = stmt.executeUpdate(sql1); //打印结果 System.out.println(count1); //设置一个异常 //int i = 1/0; //执行SQL int count2 = stmt.executeUpdate(sql2); //打印结果 System.out.println(count2); //提交事物 conn.commit(); }catch(Execption e){ //回滚事物 conn.roolback(); e.printStackTrace(); }
3.3 Statement
作用:执行SQL语句
-
执行DML、DDL语句
DDL和DML:
- DML:对数据的增删改操作
- DDL:对表和库的增删改查操作
int count = stmt.executeUpdate(sql);
返回值:
- DML语句影响的行数
- DDL语句执行后,执行成功也可能返回0
-
执行DQL语句
DQL:对数据的查询操作
ResultSet rs = stmt.execudtQuery(sql);
返回值:ResultSet结果集对象
3.4 ResultSet
ResultSet(结果集对象):封装了DQL查询语句的结果
ResultSet rs = stmt.execudtQuery(sql);
-
rs.next()
bollean flag = rs.next(); //next():指针下移,然后判断当前行是否为有效行
-
rs.getXxx()
int id = rs.getInt("id"); String name = rs.getString(2); String pwd = rs.getString(3); Date birthday = rs.getDate(4);
括号里可以有两种参数:
- int :列的编号,从1开始
- String:列的名称
-
ResultSet的使用
ResultSet rs = stmt.executeQuery(sql); while(rs.next()){ int id = rs.getInt(1); String name = rs.getString(2); String pwd = rs.getString(3); Date birthday = rs.getDate(4); System.out.println(id + "\t" + name + "\t" + pwd + "\t" + birthday); }
3.5 ResultSet案例
需求:查询account账户表数据,封装为Account对象中,把这些对象存储到ArrayList中
- Account类
public class Account {
private int id;
private String name;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
- mysql.properties
user=root
password=****
url=jdbc:mysql://localhost:3306/db01
driver=com.mysql.cj.jdbc.Driver
- ResultSetDemo
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class ResultSetDemo {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
Connection conn = DriverManager.getConnection(url, user, password);
String sql = "select * from account";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
List<Account> list = new ArrayList<>();
while(rs.next()){
Account account = new Account();
int id = rs.getInt(1);
String name = rs.getString(2);
double money = rs.getDouble(3);
account.setId(id);
account.setName(name);
account.setMoney(money);
list.add(account);
}
rs.close();
stmt.close();
conn.close();
}
}
3.6 PreparedStatement
- 通过转义敏感字符来防止SQL注入
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;
public class PreparedStatementDemo {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
Connection conn = DriverManager.getConnection(url, user, password);
String sql = "select * from account where name = ? and password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"awsama");
pstmt.setString(2,"13579");
ResultSet rs = pstmt.executeQuery();
System.out.println(rs.next() ? "登陆成功" : "登陆失败" );
rs.close();
pstmt.close();
conn.close();
}
}
-
预编译SQL,性能更高
用Statement重复执行同一条SQL时,每次都要检查语法、编译、再执行
用PreparedStatement重复执行同一条SQL时,只是在第一次的时候完成检查语法、编译、执行,从第二次开始就可以跳过前两步直接执行语句了
PreparedStatement的预编译功能默认是关闭的,开启方式如下:
在url后面加上useServerPrepStmts=true
url = "jdbc:mysql:///db01?useServerPrepStmts=true";
//或者用properties的方法↓
String url = properties.getProperty("url") + "?useServerPrepStmts=true";