首先你要有一個Java項目,然後依賴了mysql驅動,過程略,這裏介紹一下jdbc的基本使用,實際開發是用不到的,都是Spring結合Mybatis或者Hibernate。
基本使用
public void f2() throws Exception{
//註冊驅動
//Class.forName("com.mysql.jdbc.Driver"); // 除了Driver是jdbc的類,其餘都是Java的類
DriverManager.registerDriver(new Driver());
//獲取連接 ctrl+o 整理包
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/day07", "root", "1234"); // 高版本的有一個警告,用SSL:jdbc:mysql://localhost:3306/test?useSSL=true
//編寫sql
String sql="select * from category";
//創建語句執行者
PreparedStatement st=conn.prepareStatement(sql);
//設置參數
//執行sql
ResultSet rs=st.executeQuery();
//處理結果
while(rs.next()){
System.out.println(rs.getString("cid")+"::"+rs.getString("cname"));
}
//釋放資源.
rs.close();
st.close();
conn.close();
}
//插入一條數據 注:JdbcUtils是自己封裝的類
public void f3(){
Connection conn=null;
ResultSet rs=null;
PreparedStatement st=null;
try {
//獲取連接
conn=JdbcUtils.getConnection();
//編寫sql
String sql="insert into category values(?,?)";
//獲取語句執行者
st=conn.prepareStatement(sql);
//設置參數
st.setString(1, "c006");
st.setString(2, "戶外");
//執行sql
int i=st.executeUpdate();
//處理結果
if(i==1){
System.out.println("success");
}else{
System.out.println("fail");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//釋放資源
JdbcUtils.closeResource(conn, st, rs);
}
}
public class JdbcUtils {
// 獲取連接
public static Connection getConnection() throws ClassNotFoundException, SQLException {
// 註冊驅動 ctrl+shift+f格式化代碼
Class.forName("com.mysql.jdbc.Driver");
// 獲取連接 ctrl+o 整理包
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day07", "root", "1234");
return conn;
}
/**
* 釋放資源
* @param conn 連接
* @param st 語句執行者
* @param rs 結果集
*/
public static void closeResource(Connection conn, Statement st, ResultSet rs) {
closeResultSet(rs);
closeStatement(st);
closeConn(conn);
}
/**
* 釋放連接
* @param conn 連接
*/
public static void closeConn(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn=null;
}
}
/**
* 釋放語句執行者
* @param st 語句執行者
*/
public static void closeStatement(Statement st){
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
st=null;
}
}
/**
* 釋放結果集
* @param rs 結果集
*/
public static void closeResultSet(ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs=null;
}
}
}
jdbc-api詳解
所有的包 都是 java.sql 或者 javax.sql
DriverManager:管理了一組jdbc的操作 類
常用方法:
瞭解:註冊驅動
static void registerDriver(Driver driver) :
通過查看 com.mysql.jdbc.Driver的源碼 有如下代碼
static {
try {
java.sql.DriverManager.registerDriver(new Driver());//這段代碼我們已經寫過
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
驅動註冊了兩次.我們只需要將靜態代碼塊執行一次,類被加載到內存中會執行靜態代碼塊,並且只執行一次.
現在只需要將類加載到內存中即可:
方式1:
★Class.forName("全限定名");//包名+類名 com.mysql.jdbc.Driver
方式2:
類名.class;
方式3:
對象.getClass();
掌握:獲取連接
static Connection getConnection(String url, String user, String password)
參數1:告訴我們連接什麼類型的數據庫及連接那個數據庫
協議:數據庫類型:子協議 參數
mysql: jdbc:mysql://localhost:3306/數據庫名稱
oracle: jdbc:oracle:thin@localhost:1521@實例
參數2:賬戶名 root
參數3:密碼
Connection:連接 接口
常用方法:
獲取語句執行者:
(瞭解)Statement createStatement() :獲取普通的語句執行者 會出現sql注入問題
★PreparedStatement prepareStatement(String sql) :獲取預編譯語句執行者
(瞭解)CallableStatement prepareCall(String sql):獲取調用存儲過程的語句執行者
瞭解:
setAutoCommit(false) :手動開啓事務
commit():提交事務
rollback():事務回滾
Statement:語句執行者 接口
PreparedStatement:預編譯語句執行者 接口
常用方法:
設置參數:
setXxx(int 第幾個問號,Object 實際參數);
常見的方法:
setInt
setString
setObject
執行sql:
ResultSet executeQuery() :執行 r 語句 返回值:結果集
int executeUpdate() :執行cud 語句 返回值:影響的行數
ResultSet:結果集 接口
執行查詢語句之後返回的結果
常用方法:
boolean next():判斷是否有下一條記錄,若有返回true且將光標移到下一行,若沒有呢則返回false
光標一開始處於第一條記錄的上面
獲取具體內容
getXxx(int|string)
若參數爲int :第幾列
若參數爲string:列名(字段名)
例如:
獲取cname的內容可以通過
getString(2)
getString("cname")
常用方法:
getInt
getString 也可以獲取int值
getObject 可以獲取任意
事務
事務總結:
事務的特性:★★★
ACID
原子性:事務裏面的操作單元不可切割,要麼全部成功,要麼全部失敗
一致性:事務執行前後,業務狀態和其他業務狀態保持一致.
隔離性:一個事務執行的時候最好不要受到其他事務的影響
持久性:一旦事務提交或者回滾.這個狀態都要持久化到數據庫中
不考慮隔離性會出現的讀問題(都是對於兩個事務來說的)★★
髒讀:在一個事務中讀取到另一個事務沒有提交的數據
不可重複讀:在一個事務中,兩次查詢的結果不一致(針對的update操作)
虛讀(幻讀):在一個事務中,兩次查詢的結果不一致(針對的insert操作)
通過設置數據庫的隔離級別來避免上面的問題(理解)
read uncommitted 讀未提交 上面的三個問題都會出現
read committed 讀已提交 可以避免髒讀的發生
repeatable read 可重複讀 可以避免髒讀和不可重複讀的發生
serializable 串行化 可以避免所有的問題
瞭解
演示髒讀的發生:
將數據庫的隔離級別設置成 讀未提交
set session transaction isolation level read uncommitted;
查看數據庫的隔離級別
select @@tx_isolation;
避免髒讀的發生,將隔離級別設置成 讀已提交
set session transaction isolation level read committed;
不可避免不可重複讀的發生.
避免不可重複讀的發生 經隔離級別設置成 可重複讀
set session transaction isolation level repeatable read;
演示串行化 可以避免所有的問題
set session transaction isolation level serializable;
鎖表的操作.
四種隔離級別的效率
read uncommitted>read committed>repeatable read>serializable
四種隔離級別的安全性
read uncommitted<read committed<repeatable read<serializable
開發中絕對不允許髒讀發生.
mysql中默認級別:repeatable read
oracle中默認級別:read committed
java中控制隔離級別:(瞭解)
Connection的api
void setTransactionIsolation(int level)
level是常量
package com.itheima.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
// 數據庫工具另一種封裝,使用了第三方連接池
public class DataSourceUtils {
private static ComboPooledDataSource ds=new ComboPooledDataSource();
private static ThreadLocal<Connection> tl=new ThreadLocal<>();
/**
* 獲取數據源
* @return 連接池
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 從當前線程上獲取連接
* @return 連接
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
Connection conn = tl.get();
if(conn==null){
//第一次獲取 創建一個連接 和當前的線程綁定
conn=ds.getConnection();
//綁定
tl.set(conn);
}
return conn;
}
/**
* 釋放資源
*
* @param conn
* 連接
* @param st
* 語句執行者
* @param rs
* 結果集
*/
public static void closeResource(Connection conn, Statement st, ResultSet rs) {
closeResource(st, rs);
closeConn(conn);
}
public static void closeResource(Statement st, ResultSet rs) {
closeResultSet(rs);
closeStatement(st);
}
/**
* 釋放連接
*
* @param conn
* 連接
*/
public static void closeConn(Connection conn) {
if (conn != null) {
try {
conn.close();
//和當前的線程解綁
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
/**
* 釋放語句執行者
*
* @param st
* 語句執行者
*/
public static void closeStatement(Statement st) {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
st = null;
}
}
/**
* 釋放結果集
*
* @param rs
* 結果集
*/
public static void closeResultSet(ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
}
/**
* 開啓事務
* @throws SQLException
*/
public static void startTransaction() throws SQLException{
//獲取連接//開啓事務
getConnection().setAutoCommit(false);;
}
/**
* 事務提交
*/
public static void commitAndClose(){
try {
//獲取連接
Connection conn = getConnection();
//提交事務
conn.commit();
//釋放資源
conn.close();
//解除綁定
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 事務回滾
*/
public static void rollbackAndClose(){
try {
//獲取連接
Connection conn = getConnection();
//事務回滾
conn.rollback();
//釋放資源
conn.close();
//解除綁定
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class AccountDao4DB {
public void accountOut(String fromUser, String money) throws SQLException {
//創建queryrunner
QueryRunner qr = new QueryRunner();
//編寫sql
String sql="update account set money =money - ? where name =?";
//執行sql
qr.update(DataSourceUtils.getConnection(), sql, money,fromUser);
}
public void accountIn(String toUser, String money) throws SQLException {
// TODO Auto-generated method stub
QueryRunner qr=new QueryRunner();
String sql="update account set money =money + ? where name =?";
qr.update(DataSourceUtils.getConnection(), sql, money,toUser);
}
}
public class AccountService4DB {
/**
* 轉賬
* @param fromUser 轉出方
* @param toUser 轉入方
* @param money 金額
* @throws Exception
*/
public void account(String fromUser, String toUser, String money) throws Exception {
AccountDao4DB dao = new AccountDao4DB();
try {
//0.開啓事務
DataSourceUtils.startTransaction();
//1.轉出
dao.accountOut(fromUser,money);
int i=1/0;
//2.轉入
dao.accountIn(toUser,money);
//3.事務提交
DataSourceUtils.commitAndClose();
} catch (Exception e) {
e.printStackTrace();
DataSourceUtils.rollbackAndClose();
throw e;
}
}
}