回顧:
臟讀:未提交事務(wù)的數(shù)據(jù)
不可重復(fù)讀:已提交數(shù)據(jù) update
幻讀或者虛讀:已經(jīng)提交了數(shù)據(jù)的行數(shù) insert delete
JDBC介紹(掌握)
核心API
1.DriverManager 驅(qū)動管理類
2.connection連接接口
3.Statement 發(fā)送SQL語句的接口 Statement的子接口PreparedStatement 預(yù)編譯接口,防止SQL注入問題
4.ResultSet 結(jié)果集 接收查詢的數(shù)據(jù)
JDBC編程六步(掌握)
注冊驅(qū)動
?Class.forName("com.mysql.jdbc.Driver");
數(shù)據(jù)庫獲取連接
使用驅(qū)動管理類DriverManager中的靜態(tài)方法:
??????? static Connection getConnection(String url, String user, String password)試圖建立到給定數(shù)據(jù)庫 URL 的連接。
參數(shù):
??????????????????? url -連接數(shù)據(jù)庫的地址
??????????????????????? url整體格式:jdbc:mysql://連接數(shù)據(jù)庫服務(wù)器的ip地址:連接數(shù)據(jù)庫的端口號/具體的數(shù)據(jù)庫名
??????? ????????????user -數(shù)據(jù)庫用戶,root
??????????????????? password -用戶的密碼1234
?*/
//2.獲取和數(shù)據(jù)庫的連接String url = "jdbc:mysql://localhost:3306/day04_db";//連接數(shù)據(jù)庫的地址String user = "root";//數(shù)據(jù)庫用戶String password = "1234";//用戶的密碼Connection conn = DriverManager.getConnection(url, user, password);
獲取發(fā)送SQL語句對象
使用驅(qū)動管理類DriverManager中的靜態(tài)方法:
??????? static Connection getConnection(String url, String user, String password)試圖建立到給定數(shù)據(jù)庫 URL 的連接。
參數(shù):
??????????????????? url -連接數(shù)據(jù)庫的地址
??????????????????????? url整體格式:jdbc:mysql://連接數(shù)據(jù)庫服務(wù)器的ip地址:連接數(shù)據(jù)庫的端口號/具體的數(shù)據(jù)庫名
??????? ????????????user -數(shù)據(jù)庫用戶,root
??????????????????? password -用戶的密碼1234
?*/
//2.獲取和數(shù)據(jù)庫的連接String url = "jdbc:mysql://localhost:3306/day04_db";//連接數(shù)據(jù)庫的地址String user = "root";//數(shù)據(jù)庫用戶String password = "1234";//用戶的密碼Connection conn = DriverManager.getConnection(url, user, password);
3.獲取Statement對象
在java.sql.Connection接口中有如下方法獲取到Statement對象
Statement的API介紹
int executeUpdate(String sql)
根據(jù)執(zhí)行的DML(insert、update、delete)語句,發(fā)揮影響的行數(shù)
2.resultSet excuteQuery(String sql)
根據(jù)執(zhí)行的結(jié)果集,只能執(zhí)行select語句
注意:在MySQL中,只要不是查詢就是修改。
executeUpdate:用于執(zhí)行增刪改
executeQuery:用于執(zhí)行查詢
使用步驟
1.注冊驅(qū)動
2。獲取連接
3.獲取Statement對象
4.使用Statement對象執(zhí)行SQL語句
5.釋放資源
JDBC實現(xiàn)對單標查詢
Result原理
1.ResultSet內(nèi)部有一個指針,開始記錄開始位置
2.調(diào)用next方法,ResultSet內(nèi)部指針就會移動到下一行數(shù)據(jù)
3.我們可以通過ResultSet得到一行數(shù)據(jù)getXxx得到某列數(shù)據(jù)
public class Demo04 {
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///day04_db", "root", "1234");
Statement stmt = conn.createStatement();
SString sql = "select * from user";
ResultSet rs = stmt.executeQuery(sql);
// 內(nèi)部有一個指針,只能取指針指向的那條記錄
? ? ? ? while(rs.next()){// 指針移動一行,有數(shù)據(jù)才返回true
int id = rs.getInt("id");
String name = rs.getString(2);
String pwd= rs.getString(3);
System.out.println(id+"+++"+name+"++++"+pwd);
}
// 關(guān)閉資源
rs.close();
stmt.close();
conn.close();
}
}
JDBC事務(wù)
開啟事務(wù)(coon.setAutoCommit(false))——>執(zhí)行一組SQL語句——>一切正常提交事務(wù) coon.commit();
開啟事務(wù)(coon.setAutoCommit(false))——>執(zhí)行一組SQL語句——> 出現(xiàn)異常,回滾事務(wù)coon.rollback;
Connection 接口中與事務(wù)有關(guān)的方法
void setAutoCommit(boolean autoCommit)throws SQLException;
false:開啟事務(wù),true:關(guān)閉事務(wù)
voidcommit()throwsSQLException;
提交事務(wù)
voidrollback()throwsSQLException;
回滾事務(wù)
注意:在jdbc事務(wù)操作中,事務(wù)的控制都是通過Connection對象完成的,當一個完整的業(yè)務(wù)操作前,我們首先使用coon.setAutoCommit(false)來開啟事務(wù)。默認情況下是true的,表示關(guān)閉事務(wù),那么一條SQL語句就是一個事務(wù),默認提交事務(wù)。如果設(shè)置為false,那么表示開啟事務(wù),所有的SQL語句就會都在一個事務(wù)中。
當業(yè)務(wù)操作完成后,如果整個操作沒有問題,我們需要使用coon.commmit()來提交事務(wù)。當然了,如果出現(xiàn)了異常,我們需要使用coon.rollback()撤銷所有的操作,所以出現(xiàn)事務(wù)的異常,需要進行事務(wù)的回滾。
使用步驟
1.注冊驅(qū)動
2.獲取連接
3.開啟事務(wù)
4.獲取Statement
5.使用Statement執(zhí)行SQL
6.提交或回滾事務(wù)
7.關(guān)閉資源
package com.day04;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC {
public static void main(String[] args)throws SQLException, ClassNotFoundException {
/* DriverManager.registerDriver(new Driver());
使用 DriverManager.registerDriver(new Driver());,存在以下不足,注冊被注冊兩次
*/
? ? ? Class.forName("com.mysql.jdbc.Driver");//注冊驅(qū)動
//獲取連接
? ? ? ? Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day04_db","root","root");
System.out.println(connection);
//從連接中拿到一個Statement對象
? ? ? ? Statement statement = connection.createStatement();
//1.插入記錄
/*String sql ="insert into user values(null,'zhaoliu','abc')";
int i=statement.executeUpdate(sql);
System.out.println("影響的行數(shù):"+i );*/
//2.修改記錄
/*? String? sql="update user set? username='tianqi'where username='zhaoliu'";
int? i=statement.executeUpdate(sql);
System.out.println("影響的行數(shù):"+i );*/
//刪除記錄
? ? ? ? String sql ="delete from user where id=4";
int i=statement.executeUpdate(sql);
System.out.println("影響的行數(shù):"+i );
statement.close();
connection.close();
}
}
編寫JDBC工具類
在目錄下創(chuàng)建jdbc.properties
jdbc.properties文件中的配置信息
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day04_db
user=root
password=root
如何讀取外部文件的內(nèi)容?
public static void main(String[]args) {
? ? ? ? // 需求: 通過properties對象讀取 外部配置的內(nèi)容
? ? ? ? Propertiesprop=newProperties();
? ? ? ? try{
//對于FileInputStream流相對的路徑是當前模塊
FileInputStreamin=newFileInputStream("jdbc.properties");
? ? ? ? ? ? // 加載外部的配置文件
? ? ? ? ? ? prop.load(in);
? ? ? ? }catch(IOExceptione) {
? ? ? ? ? ? // TODO Auto-generated catch block
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? // 讀取外部配置文件的內(nèi)容
? ? ? ? StringdriverClass=prop.getProperty("driverClass");
? ? ? ? Stringurl=prop.getProperty("url");
? ? ? ? Stringuser=prop.getProperty("user");
? ? ? ? Stringpassword=prop.getProperty("password");
?
? ? ? ? System.out.println(driverClass);
? ? }
獲得連接的最終版
public class JDBCUtils {
static String driverClass = null;
static String url = null;
static String user = null;
static String password = null;
static {
// 需求: 通過properties對象讀取 外部配置的內(nèi)容
Properties prop = new Properties();
try {
FileInputStream in=new FileInputStream("jdbc.properties");
// 加載外部的配置文件
prop.load(in);
// 讀取外部配置文件的內(nèi)容
? ? driverClass = prop.getProperty("driverClass");
? ? url = prop.getProperty("url");
? ? user = prop.getProperty("user");
? ? password = prop.getProperty("password");
// 注冊驅(qū)動
Class.forName(driverClass);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 獲得連接
public static Connection getConnection() {
Connection con = null;
? try? {
? ? ? ? ? con = DriverManager.getConnection(url, user, password);
? ? ? ? } catch (Exception e)
{
? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return con;
}
}
關(guān)閉資源
public static void release(Connection conn, Statement stmt, ResultSet rs) {
// 釋放資源
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
優(yōu)化后的delete方法
@Test
? ? publicvoiddelete() {
? ? ? ? // 需求: 刪除id=3的記錄
? ? ? ? Connectionconn=null;
? ? ? ? Statementstmt=null;
?
? ? ? ? try{
? ? ? ? ? ? // 獲得連接
? ? ? ? ? ? conn=JDBCUtils.getConnection();
? ? ? ? ? ? // 獲得發(fā)送sql的對象
? ? ? ? ? ? stmt=conn.createStatement();
? ? ? ? ? ? // 執(zhí)行sql 獲得結(jié)果
? ? ? ? ? ? Stringsql="delete from user where id=3";
? ? ? ? ? ? intsum=stmt.executeUpdate(sql);
? ? ? ? ? ? // 處理結(jié)果
? ? ? ? ? ? System.out.println(sum);
? ? ? ? }catch(Exceptione) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }finally{
? ? ? ? ? ? // 釋放資源
? ? ? ? ? ? JDBCUtils.release(conn,stmt,null);
? ? ? ? }
? ? }