JDBC
什麼是JDBC
JDBC(Java DataBase Connectivity, Java數據庫連接) ,是一種用於執行SQL語句的Java API,爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成
連接數據庫
mysql8 之前連接
數據庫驅動名:com.mysql.jdbc.Driver
url連接:jdbc:mysql://127.0.0.1:3306/mydb
public class test{
public static void main(String[] args){
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://127.0.0.1:3306/mydb";
String user="root";
String password="root";
Connection conn = DriverManager.getConnection(url,user,password);
}
}
mysql8之後連接
數據庫驅動名:com.mysql.cj.jdbc.Driver
url連接:jdbc:mysql://127.0.0.1:3306/mydbseSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
public class test{
public static void main(String[] args){
* url 同一資源定位符
* 協議 jdbc:mysql:
* ip地址 127.0.0.1/localhost
* 端口號 3306
* 具體的資源路徑 mydb
* useSSL=false 不使用SSL加密機制
* &useUnicode=true 使用unicode字符集
* &characterEncoding=utf8 使用utf8作爲通信字符集
* &serverTimezone=Asia/Shanghai 確定時區爲 Asia/Shanghai
* user 賬號 root
* password 密碼 root
* */
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?seSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url,user,password);
}
}
常見異常
java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver2
未添加jar包 或者 路徑錯誤
SQLException: No suitable driver found for jdbcs
協議錯誤
CommunicationsException: Communications link failure
通信失敗
SQLException: Access denied for user ‘root’@‘localhost’ (using password: YES)
拒絕訪問 密碼錯誤
SQLNonTransientConnectionException: Public Key Retrieval is not allowed
不允許檢索公鑰 用戶名錯誤
SQLIntegrityConstraintViolationException: Duplicate entry ‘50’ for key ‘PRIMARY’
主鍵重複輸入
executeQuert() 和 executeUpdate() 區別
執行查詢命令 : executeQuert()
執行增刪改命令 :executeUpdate()
ResultSet(結果解)接口
ResultSet對象 接收executeQuert() 的返回值
JDBC Statement 接口
用於發送SQL語句到數據庫中,或理解爲執行sql命令
添加數據(insert)
public class TestInsert {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加載驅動
Class.forName("com.mysql.cj.jdbc.Driver2");
//2.創建數據庫連接
String url = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url, user, pwd);
//3.創建SQL命令發送器
Statement st = conn.createStatement();
String sql = "insert into dept values(50,'中部','北京')";
//4.通過Statement發送SQL命令並得到結果
int rows = st.executeUpdate(sql);
System.out.println("執行完畢,對數據中" + rows + "行數據產生了影響");
//5.關閉資源
st.close();
conn.close();
}
}
修改數據(update)
public class TestUpdate {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加載驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//2.創建數據庫連接
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url, user, pwd);
//3.創建SQL命令發送器
Statement st = conn.createStatement();
String sql = "update dept set dname='銷售部'where deptno=50 ";
//4.通過Statement發送SQL命令並得到結果
int rows = st.executeUpdate(sql);
System.out.println("執行完畢,對數據中" + rows + "行數據產生了影響");
//5.關閉資源
st.close();
conn.close();
}
}
刪除數據(delete)
public class TestDelete {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加載驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//2.創建數據庫連接
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url, user, pwd);
//3.創建SQL命令發送器
Statement st = conn.createStatement();
String sql = "delete from dept where deptno=50";
//4.通過Statement發送SQL命令並得到結果
int rows = st.executeUpdate(sql);
System.out.println("執行完畢,對數據中" + rows + "行數據產生了影響");
//5.關閉資源
st.close();
conn.close();
}
}
查詢數據(select)
public class TestExecuteQuery {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
//加載驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//建立練級
Connection conn = DriverManager.getConnection(url, user, pwd);
//創建sql命令發送器
Statement st = conn.createStatement();
String sql = "select * from emp";
//發送sql命令 並返回數據
ResultSet rs = st.executeQuery(sql);
//ResultSet 使用方式2
while (rs.next()) {
//獲取行數據
int enmno = rs.getInt(1);
String eName=rs.getString(2);
String job=rs.getString(3);
int mgr = rs.getInt(4);
Date hireDate= rs.getDate(5);
double sal= rs.getDouble(6);
double comm= rs.getDouble(7);
int deptNo =rs.getInt(8);
StringBuilder str = new StringBuilder();
str.append(enmno+" ").append(eName+" ").append(job+" ").append(mgr+" ").append(hireDate+" ").append(sal+" ").append(comm+" ").append(deptNo+" ");
System.out.println(str.toString());
}
rs.close();
st.close();
conn.close();
//ResultSet 使用方式2
/*while (rs.next()) {
int enmno = rs.getInt("EMPNO");
String eName=rs.getString("ENAME");
String job=rs.getString("JOB");
int mgr = rs.getInt("MGR");
Date hireDate= rs.getDate("HIREDATE");
double sal= rs.getDouble("SAL");
double comm= rs.getDouble("COMM");
int deptNo =rs.getInt("DEPTNO");
StringBuilder str = new StringBuilder();
str.append(enmno+" ").append(eName+" ").append(job+" ").append(mgr+" ").append(hireDate+" ").append(sal+" ").append(comm+" ").append(deptNo+" ");
System.out.println(str.toString());
}
*/
}
}
將數據庫中的數據多條存入實體類中 並遍歷數據
public class TestExecuteQuery2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
List<Emp> list = getAllEmp();
showEmp(list);
}
public static List<Emp> getAllEmp() {
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
ResultSet rs = null;
Connection conn = null;
Statement st = null;
List<Emp> list = new ArrayList<>();
try {
//加載驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//建立連接
conn = DriverManager.getConnection(url, user, pwd);
//創建sql命令發送器
st = conn.createStatement();
String sql = "select * from emp";
//發送sql命令 本返回數據
rs = st.executeQuery(sql);
while (rs.next()) {
//獲取行數據
int enmno = rs.getInt("EMPNO");
String eName = rs.getString("ENAME");
String job = rs.getString("JOB");
int mgr = rs.getInt("MGR");
Date hireDate = rs.getDate("HIREDATE");
double sal = rs.getDouble("SAL");
double comm = rs.getDouble("COMM");
int deptNo = rs.getInt("DEPTNO");
Emp emp = new Emp(enmno,eName,job,mgr,hireDate,sal,comm,deptNo);
list.add(emp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//關閉資源
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != st) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
/**
* 遍歷集合
* */
public static void showEmp(List<Emp> list){
for(Emp e:list){
System.out.println(e);
}
}
}
sql注入風險
SQL語句中拼接的內容破壞了 SQL語句原有的判斷邏輯
select * from user where username='lisi' and password='ll' or '1'='1'
使用Statement
public static User login(String username,String password) {
User users = null;
Connection conn=null;
int n=0;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
conn = DriverManager.getConnection(url, user, pwd);
Statement st = conn.createStatement();
String sql = "select * from user where username='"+username+"' and password='"+password+"'";
System.out.println(sql);
ResultSet rs = st.executeQuery(sql);
if(rs.next()){
int id = rs.getInt("id");
String userName= rs.getString("username");
String pwd2 =rs.getString("password");
users= new User(id,userName,pwd2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return users;
}
sql注入風險解決方式:使用PreparedStatement
public static User login2(String username,String password) {
User users = null;
Connection conn=null;
int n=0;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
conn = DriverManager.getConnection(url, user, pwd);
String sql = "select * from user where username='"+username+"' and password='"+password+"'";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if(rs.next()){
int id = rs.getInt("id");
String userName= rs.getString("username");
String pwd2 =rs.getString("password");
users= new User(id,userName,pwd2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return users;
}
JDBC PreparedStatement 接口
Statement 和 PreparedStatement 區別和聯繫
聯繫 :PreparedStatement extends Statement
區別:1.PreparedStatment安全性高,可以避免SQL注入
2.PreparedStatment簡單不繁瑣,不用進行字符串拼接
3.PreparedStatment性能高,用在執行多個相同數據庫DML操作時
添加數據(insert)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:添加
* @param:
* @return:
*/
public static void insert(int deptno,String dname,String loc) throws Exception{
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "insert into dept values(?,?,?) ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,deptno);
ps.setString(2,dname);
ps.setString(3,loc);
int n = ps.executeUpdate();
ps.close();
conn.close();
}
}
修改數據(update)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:修改
* @param:
* @return:
*/
public static void update(int deptno,String dname) throws Exception{
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "update dept set dname=? where deptno=? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,dname);
ps.setInt(2,deptno);
int n = ps.executeUpdate();
ps.close();
conn.close();
}
}
刪除數據(delete)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:刪除
* @param:
* @return:
*/
public static void delete(int deptno) throws Exception{
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "delete from dept where deptno=? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,deptno);
int n = ps.executeUpdate();
ps.close();
conn.close();
}
}
查詢數據(select)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:模糊查詢
* @param:
* @return:
*/
public static void find(String n) throws Exception {
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "select * from emp where ename like ? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,"%"+n+"%");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int enmno = rs.getInt("EMPNO");
String eName=rs.getString("ENAME");
String job=rs.getString("JOB");
int mgr = rs.getInt("MGR");
Date hireDate= rs.getDate("HIREDATE");
double sal= rs.getDouble("SAL");
double comm= rs.getDouble("COMM");
int deptNo =rs.getInt("DEPTNO");
StringBuilder str = new StringBuilder();
str.append(enmno+" ").append(eName+" ").append(job+" ").append(mgr+" ").append(hireDate+" ").append(sal+" ").append(comm+" ").append(deptNo+" ");
System.out.println(str.toString());
}
rs.close();
ps.close();
conn.close();
}
}
JDBC事務
禁止事務自動提交(setAutoCommit)
setAutoCommit(false);
手動提交事務(commit)
conn.commit()
回滾(rollback)
conn.rollback()
public class TestTransaction {
public static void main(String[] args) {
//1.加載驅動
PreparedStatement pst = null;
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
//2.創建數據庫連接
conn = DriverManager.getConnection(url, user, pwd);
//禁止事務自動提交
conn.setAutoCommit(false);
String sql = "update account set money= money-100 where username=?";
pst = conn.prepareStatement(sql);
pst.setString(1, "張三");
//發送SQL命令
pst.executeUpdate();
sql = "update account set money=money+100 where username=?";
pst = conn.prepareStatement(sql);
pst.setString(1, "李四");
//發送SQL命令
pst.executeUpdate();
} catch (ClassNotFoundException e) {
try {
//回滾
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn) {
try {
//提交事務
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
//關閉資源
if (null != pst) {
try {
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
JDBC API 總結
Connection接口 方法
代表數據庫連接
void |
close() 立即釋放此 Connection 對象的數據庫和 JDBC 資源,而不是等待它們被自動釋放。 |
---|---|
void |
commit() 使所有上一次提交/回滾後進行的更改成爲持久更改,並釋放此 Connection 對象當前持有的所有數據庫鎖。 |
Statement |
createStatement() 創建一個 Statement 對象來將 SQL 語句發送到數據庫。 |
CallableStatement |
prepareCall( Stringsql) 創建一個 CallableStatement 對象來調用數據庫存儲過程。 |
PreparedStatement |
prepareStatement( Stringsql) 創建一個 PreparedStatement 對象來將參數化的 SQL 語句發送到數據庫。 |
PreparedStatement |
[prepareStatement](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/sql/Connection.html#prepareStatement(java.lang.String, int))( Stringsql, int autoGeneratedKeys) 創建一個默認 PreparedStatement 對象,該對象能獲取自動生成的鍵。 |
void |
rollback() 取消在當前事務中進行的所有更改,並釋放此 Connection 對象當前持有的所有數據庫鎖。 |
void |
setAutoCommit(boolean autoCommit) 將此連接的自動提交模式設置爲給定狀態。 |
DriverManager類 方法
管理一組 JDBC 驅動程序的基本服務
方法摘要 | |
---|---|
static Connection |
getConnection( Stringurl) 試圖建立到給定數據庫 URL 的連接。 |
static Connection |
[getConnection](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/sql/DriverManager.html#getConnection(java.lang.String, java.util.Properties))( Stringurl, Propertiesinfo) 試圖建立到給定數據庫 URL 的連接。 |
static Connection |
[getConnection](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/sql/DriverManager.html#getConnection(java.lang.String, java.lang.String, java.lang.String))( Stringurl, Stringuser, Stringpassword) 試圖建立到給定數據庫 URL 的連接。 |
Statement接口 方法
用於將 SQL 語句發送到數據庫中,或理解爲執行sql語句
方法 | 作用 |
---|---|
ResultSet executeQuery(String sql) | 執行SQL查詢並獲取到ResultSet對象 |
boolean execute(String sql) | 可以執行任意SQL語句,然後獲得一個布爾值,表示是否返回ResultSet |
int executeUpdate(String sql) | 可以執行插入、刪除、更新等操作,返回值是執行該操作所影響的行數 |
ResultSet接口 方法
ResultSet裏的數據一行一行排列,每行有多個字段,且有一個記錄指針,指針所指的數據行叫做當前數據行,我們只能來操作當前的數據行。我們如果想要取得某一條記錄,就要使用ResultSet的next()方法 ,如果我們想要得到ResultSet裏的所有記錄,就應該使用while循環
ResultSet對象自動維護指向當前數據行的遊標。每調用一次next()方法,遊標向下移動一行。
方法名 | 說 明 |
---|---|
boolean next() | 將光標從當前位置向下移動一行 |
boolean previous() | 遊標從當前位置向上移動一行 |
void close() | 關閉ResultSet 對象 |
int getInt(int colIndex) | 以int形式獲取結果集當前行指定列號值 |
int getInt(String colLabel) | 以int形式獲取結果集當前行指定列名值 |
float getFloat(int colIndex) | 以float形式獲取結果集當前行指定列號值 |
Float getFloat(String colLabel) | 以float形式獲取結果集當前行指定列名值 |
String getString(int colIndex) | 以String 形式獲取結果集當前行指定列號值 |
StringgetString(String colLabel) | 以String形式獲取結果集當前行指定列名值 |