一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

jdbc預(yù)編譯對(duì)象,事務(wù),數(shù)據(jù)庫(kù)連接池

 印度阿三17 2020-12-13

jdbc預(yù)編譯對(duì)象

原始的jdbc使用聲明對(duì)象進(jìn)行sql的執(zhí)行,對(duì)于執(zhí)行的sql參數(shù)使用字符串拼接的形式進(jìn)行添加

Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/teacher", "root", "root");
Statement statement = con.createStatement();
// 當(dāng)使用原始的jdbc進(jìn)行相應(yīng)操作時(shí),由前臺(tái)獲取相應(yīng)查詢參數(shù),保存至變量。準(zhǔn)備sql時(shí)將參數(shù)
// 使用字符串拼接的方式進(jìn)行數(shù)據(jù)的拼接,這有時(shí)會(huì)導(dǎo)致一些問題
// 如果使用者知道并了解sql的語句,那么就可以使用sql注入的方式混亂查詢結(jié)果
// 從而導(dǎo)致系統(tǒng)的不穩(wěn)定
// 將id與name當(dāng)做賬號(hào)密碼進(jìn)行登錄操作
String studentid = "203213213";
String studentname = "231313' or studentname!='1";
// 登錄的sql語句就會(huì)變?yōu)?String sql = "select * from student where studentid="   studentid   " and studentname= '"   studentname "'";
//select * from student where studentid=203213213 and studentname= '231313' or studentname!='1'
//輸入者可以猜測(cè)數(shù)據(jù)庫(kù)sql語句并將sql以數(shù)據(jù)的形式傳入
//如果使用字符串拼接的形式進(jìn)行sql的生成那么會(huì)導(dǎo)致結(jié)果不符
ResultSet rs = statement.executeQuery(sql);
ArrayList<Student> list = new ArrayList<>();
while (rs.next()) {// 如果結(jié)果集對(duì)象中存在數(shù)據(jù)
Student student = new Student(rs.getString("studentid"), rs.getString("studentname"),
rs.getInt("studentage"), rs.getString("studentsex"), rs.getString("studentaddress"),
rs.getInt("classid"));
list.add(student);
}
con.close();
for (Student student : list) {
System.out.println(student);
}

為了解決sql注入的問題,需要使用sql預(yù)編譯對(duì)象

Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/teacher", "root", "root");
String studentid = "203213213";
String studentname = "231313' or studentname!='1";
// String sql = "select * from student where studentid="   studentid   "
// and studentname= '"   studentname   "'";

// 原始的jdbc先創(chuàng)建聲明對(duì)象在執(zhí)行時(shí)才將sql交由聲明對(duì)象執(zhí)行
// Statement statement = con.createStatement();
// ResultSet rs = statement.executeQuery(sql);

// 預(yù)編譯對(duì)象是先準(zhǔn)備執(zhí)行的sql 將所有參數(shù)使用?占位符替換
String sql = "select * from student where studentid= ? and studentname= ?";
// 使用連接對(duì)象獲取預(yù)編譯對(duì)象并將sql進(jìn)行預(yù)編譯
PreparedStatement ps = con.prepareStatement(sql);
// 為占位符進(jìn)行賦值
ps.setObject(1, studentid);// 為指定占位符賦值
ps.setObject(2, studentname);

ResultSet rs = ps.executeQuery();
ArrayList<Student> list = new ArrayList<>();
while (rs.next()) {// 如果結(jié)果集對(duì)象中存在數(shù)據(jù)
Student student = new Student(rs.getString("studentid"), rs.getString("studentname"),
rs.getInt("studentage"), rs.getString("studentsex"), rs.getString("studentaddress"),
rs.getInt("classid"));
list.add(student);
}
con.close();
for (Student student : list) {
System.out.println(student);
}

事務(wù)

在進(jìn)行數(shù)據(jù)庫(kù)操作時(shí),為了保證數(shù)據(jù)的安全以及減少錯(cuò)誤的發(fā)生,一般都會(huì)進(jìn)行事務(wù)的管理,數(shù)據(jù)庫(kù)在進(jìn)行操作時(shí),內(nèi)部也進(jìn)行了簡(jiǎn)單的事務(wù)管理,只不過在進(jìn)行更復(fù)雜操作時(shí),這種默認(rèn)的事務(wù)不足以進(jìn)行相應(yīng)需求的實(shí)現(xiàn),這個(gè)時(shí)候就需要我們手動(dòng)的進(jìn)行事務(wù)的管理

事務(wù)的ACID原則

· ***事務(wù)的原子性( Atomicity):***一組事務(wù),要么成功;要么撤回。

· ***一致性 (Consistency):***事務(wù)執(zhí)行后,數(shù)據(jù)庫(kù)狀態(tài)與其他業(yè)務(wù)規(guī)則保持一致。如轉(zhuǎn)賬業(yè)務(wù),無論事務(wù)執(zhí)行成功否,參與轉(zhuǎn)賬的兩個(gè)賬號(hào)余額之和應(yīng)該是不變的。

· ***隔離性(Isolation):***事務(wù)獨(dú)立運(yùn)行。一個(gè)事務(wù)處理后的結(jié)果,影響了其他事務(wù),那么其他事務(wù)會(huì)撤回。事務(wù)的100%隔離,需要犧牲速度。

· ***持久性(Durability):***軟、硬件崩潰后,InnoDB數(shù)據(jù)表驅(qū)動(dòng)會(huì)利用日志文件重構(gòu)修改??煽啃院透咚俣炔豢杉娴?, innodb_flush_log_at_trx_commit 選項(xiàng) 決定什么時(shí)候吧事務(wù)保存到日志里。

mysql數(shù)據(jù)庫(kù)中 使用sql語句進(jìn)行事務(wù)處理

#在執(zhí)行多條sql前手動(dòng)開 啟事務(wù)
start transaction;
update student set studentname='Bill' where studentid='2010005';
update student set studentage=88 where studentid='2010005';

#在sql執(zhí)行結(jié)束后手動(dòng)提交事務(wù)
commit;

#mysql中如果事務(wù)在執(zhí)行過程中發(fā)生異常導(dǎo)致事務(wù)執(zhí)行出現(xiàn)問題,會(huì)自動(dòng)進(jìn)行回滾
#將已經(jīng)執(zhí)行的更改進(jìn)行撤銷
rollback;

jdbc中進(jìn)行事務(wù)處理

jdbc進(jìn)行事務(wù)處理的語法

獲取連接對(duì)象con

設(shè)置con.setAutoCommit(false);//關(guān)閉事務(wù)的自動(dòng)提交-》開啟事務(wù)

執(zhí)行多條sql

對(duì)執(zhí)行sql語句進(jìn)行捕獲如果出現(xiàn)異常則con.rollback();回滾事務(wù)

執(zhí)行成功則 con.commit(); 提交事務(wù)

// mysql默認(rèn)開啟事務(wù)的自動(dòng)提交
// 每執(zhí)行1條SQL語句都是一個(gè)事務(wù)
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/teacher", "root", "root");
try {
// 默認(rèn)事務(wù)自動(dòng)提交 每執(zhí)行1條sql一個(gè)事務(wù) 其他事務(wù)不會(huì)影響該事務(wù)的執(zhí)行
String sql = "update student set studentname='Bill' where studentid='2010005' ";
// 事務(wù)的開啟
// 在執(zhí)行sql之前設(shè)置當(dāng)前連接
// 將自動(dòng)提交關(guān)閉
con.setAutoCommit(false);

PreparedStatement ps = con.prepareStatement(sql);
ps.executeUpdate();
// 第二條sql語句報(bào)錯(cuò)沒有執(zhí)行成功 但是第一條數(shù)據(jù)已經(jīng)執(zhí)行成功存入數(shù)據(jù)庫(kù)
String sql2 = "update student set studesntage=28 where studentid='2010005' ";
PreparedStatement ps2 = con.prepareStatement(sql2);
ps2.executeUpdate();
} catch (Exception e) {
// 對(duì)執(zhí)行的sql語句進(jìn)程try catch 如果出現(xiàn)異?;貪L事務(wù)
con.rollback();
}
// 如果執(zhí)行成功則提交事務(wù)將執(zhí)行的結(jié)果保存
con.commit();

事務(wù)的隔離級(jí)別

基于事務(wù)的隔離性,事務(wù)直接獨(dú)立互不影響,但也是取決于對(duì)不同數(shù)據(jù)的操作,如果多個(gè)事務(wù)對(duì)同一個(gè)數(shù)據(jù)進(jìn)行操作可能造成類似于java多線程操作同一變量的問題,從而導(dǎo)致數(shù)據(jù)的不準(zhǔn)確

因?yàn)椴l(fā)事務(wù)導(dǎo)致的問題大致有5類,其中兩類是更新問題三類是讀問題。

· 臟讀(dirty read):讀到另一個(gè)事務(wù)的未提交新數(shù)據(jù),即讀取到了臟數(shù)據(jù);

· 不可重復(fù)讀(unrepeatable):對(duì)同一記錄的兩次讀取不一致,因?yàn)榱硪皇聞?wù)對(duì)該記錄做了修改;

· 幻讀(虛讀)(phantom read):對(duì)同一張表的兩次查詢不一致,因?yàn)榱硪皇聞?wù)插入了一條記錄。

四大隔離級(jí)別

4個(gè)等級(jí)的事務(wù)隔離級(jí)別,在相同的數(shù)據(jù)環(huán)境下,使用相同的輸入,執(zhí)行相同的工作,根據(jù)不同的隔離級(jí)別,可以導(dǎo)致不同的結(jié)果。不同事務(wù)隔離級(jí)別能夠解決的數(shù)據(jù)并發(fā)問題的能力是不同的。

1、SERIALIZABLE(串行化)

所有事務(wù)串行依次執(zhí)行,不會(huì)發(fā)生任何數(shù)據(jù)問題,但是效率最低

2、REPEATABLE READ(可重復(fù)讀)(MySQL)

mysql默認(rèn)的事務(wù)隔離級(jí)別,事務(wù)之間在進(jìn)行操作時(shí),對(duì)操作的數(shù)據(jù)進(jìn)行限制,不允許其他事務(wù)對(duì)當(dāng)前事務(wù)正在處理的數(shù)據(jù)(行)進(jìn)行操作,可以避免臟讀和不可重復(fù)讀,效率比串行化高一點(diǎn)

3、READ COMMITTED(讀已提交數(shù)據(jù))(Oracle)

oracle數(shù)據(jù)庫(kù)默認(rèn)的事務(wù)隔離級(jí)別,多個(gè)事務(wù)進(jìn)行執(zhí)行,除了可以任意讀取操作其他事務(wù)沒有處理的數(shù)據(jù)外,只能讀取其他事務(wù)已經(jīng)提交了的數(shù)據(jù),可以防止臟讀,但是不能防止不可重復(fù)讀與幻讀,效率比可重復(fù)讀高一點(diǎn)

4、READ UNCOMMITTED(讀未提交數(shù)據(jù))

不進(jìn)行任何處理,不能解決任何隔離問題,但效率最高

mysql設(shè)置隔離級(jí)別

MySQL的默認(rèn)隔離級(jí)別為Repeatable read,可以通過下面語句查看:

SELECT @@TX_ISOLATION;

也可以通過下面語句來設(shè)置當(dāng)前連接的隔離級(jí)別:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ ;//[4選1]

JDBC設(shè)置隔離級(jí)別

con.setTransactionIsolation(int level) :參數(shù)可選值如下:

· Connection.TRANSACTION_READ_UNCOMMITTED;

· Connection.TRANSACTION_READ_COMMITTED;

· Connection.TRANSACTION_REPEATABLE_READ;

· Connection.TRANSACTION_READ_SERIALIZABLE。

c3p0數(shù)據(jù)庫(kù)連接池的使用

數(shù)據(jù)庫(kù)連接池:通過配置在程序執(zhí)行時(shí)直接創(chuàng)建多個(gè)數(shù)據(jù)庫(kù)連接并進(jìn)行保存,當(dāng)用戶需要使用連接時(shí)調(diào)用相應(yīng)方法獲取連接,連接的聲生命周期交由連接池控制。

將與數(shù)據(jù)庫(kù)的連接交由連接池進(jìn)行管理,我們只需要在使用時(shí)獲取連接進(jìn)行使用,之后連接池會(huì)自動(dòng)回收相應(yīng)的連接

1、導(dǎo)入c3p0的jar包

注意:c3p0額外依賴另一個(gè)jar包 所以在導(dǎo)入時(shí)需要導(dǎo)入兩個(gè)jar包

2、書寫連接池配置文件

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 這是默認(rèn)配置信息 -->
<default-config>
<!-- 連接四大參數(shù)配置 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/teacher?characterEncoding=UTF-8</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 池參數(shù)配置 -->
<!-- 如果池中數(shù)據(jù)連接不夠時(shí)一次增長(zhǎng)多少個(gè) -->
        <property name="acquireIncrement">5</property>
        <!-- 初始化數(shù)據(jù)庫(kù)連接池時(shí)連接的數(shù)量 -->
        <property name="initialPoolSize">20</property>
        <!-- 數(shù)據(jù)庫(kù)連接池中的最大的數(shù)據(jù)庫(kù)連接數(shù) -->
        <property name="maxPoolSize">25</property>
        <!-- 數(shù)據(jù)庫(kù)連接池中的最小的數(shù)據(jù)庫(kù)連接數(shù) -->
        <property name="minPoolSize">5</property>

</default-config>
</c3p0-config>

3、創(chuàng)建c3p0對(duì)象進(jìn)行使用

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Test {
final static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
// 使用c3p0數(shù)據(jù)庫(kù)連接池獲取連接
public static void main(String[] args) throws SQLException {
//C3P0獲取連接代碼(默認(rèn)獲取src下c3p0-config.xml)
Connection connection = comboPooledDataSource.getConnection();
String sql="select * from student";
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()){
System.out.println(rs.getString(1) "|" rs.getString(2));
}  
}
}

JDBC工具類的集成

//根據(jù)預(yù)編譯對(duì)象預(yù)編譯的sql語句獲取結(jié)果元數(shù)據(jù)
//包含返回?cái)?shù)據(jù)所有列的相應(yīng)信息(沒有行)
ResultSetMetaData metaData = ps.getMetaData();
//獲取返回?cái)?shù)據(jù)的列數(shù)
int columnCount = metaData.getColumnCount();

//獲取元數(shù)據(jù)指定列的名字
String columnLabel = metaData.getColumnLabel(2);
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import com.mchange.v2.c3p0.ComboPooledDataSource;

//數(shù)據(jù)庫(kù)連接工具類
public class AiDButil {
// 注意:本工具類在使用前需要確?;A(chǔ)準(zhǔn)備工作已完成
// 1 mysql c3p0共 3個(gè)jar包(log4j也可以添加)
// 2 c3p0配置文件配置相應(yīng)屬性(如果導(dǎo)入了log4j那么也需要配置log4j配置文件)
// 3 明確調(diào)用方法填入相應(yīng)參數(shù)
// (1)查詢語句返回集合泛型類型屬性必須與數(shù)據(jù)庫(kù)列名一致(能多不能少)
// (2)不確定參數(shù)填入的參數(shù)與sql中占位符?一致 且填入順序一致

// 需要導(dǎo)入mysql連接jar包與c3p0使用的兩個(gè)jar包
final static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();

// 獲取連接方法
// 返回一個(gè)連接對(duì)象
public static Connection getCon() {
// 連接使用c3p0進(jìn)行獲取
// 使用c3p0數(shù)據(jù)庫(kù)連接池獲取連接
Connection connection = null;
try {
connection = comboPooledDataSource.getConnection();
} catch (SQLException e) {
System.err.println("獲取連接失敗");
return null;
}
return connection;
}

// DML方法
// 不支持事務(wù) 單條sql語句執(zhí)行
public static boolean DML(String sql, Object... o) {
// 獲取連接
Connection con = getCon();
// 創(chuàng)建預(yù)編譯對(duì)象
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i = 0; i < o.length; i  ) {
ps.setObject((i   1), o[i]);
}
ps.executeUpdate();
} catch (SQLException e) {
System.out.println("查詢執(zhí)行失敗:"   sql);
return false;
}
return true;
}

// DML方法
// 支持事務(wù) 多條sql語句執(zhí)行
public static boolean DML(Connection con, String sql, Object... o) {
// 創(chuàng)建預(yù)編譯對(duì)象
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i = 0; i < o.length; i  ) {
ps.setObject((i   1), o[i]);
}
ps.executeUpdate();
} catch (SQLException e) {
System.out.println("查詢執(zhí)行失敗:"   sql);
return false;
}
return true;
}

// 查詢dql語句方法
public static <E> ArrayList<E> DQL(String sql, Class<E> c, Object... o) {
ArrayList<E> list = new ArrayList<>();
try {
// 獲取連接
Connection con = getCon();
// 準(zhǔn)備預(yù)編譯對(duì)象
PreparedStatement ps = con.prepareStatement(sql);
// 獲取元數(shù)據(jù) 準(zhǔn)備存儲(chǔ)所有列名的數(shù)組
ResultSetMetaData metaData = ps.getMetaData();
// 創(chuàng)建指定長(zhǎng)度用于存儲(chǔ)列名的數(shù)組
String[] names = new String[metaData.getColumnCount()];
// 循環(huán)為names數(shù)組進(jìn)行賦值
for (int i = 0; i < names.length; i  ) {
names[i] = metaData.getColumnLabel(i   1);// 獲取指定列名
}
// 執(zhí)行sql返回結(jié)果集
ResultSet rs = ps.executeQuery();
while (rs.next()) {

// 每一行數(shù)據(jù)就是一個(gè)對(duì)象
// 使用反射創(chuàng)建對(duì)象
E obj = c.newInstance();

// 當(dāng)前行所有列名 在names數(shù)組中存儲(chǔ)
// 循環(huán)names數(shù)組取出當(dāng)前行對(duì)應(yīng)數(shù)據(jù)
for (String colname : names) {
Object value = rs.getObject(colname);// 獲取列名對(duì)應(yīng)值
// 將值存入相應(yīng)對(duì)象
// 使用反射獲取類中同名的屬性對(duì)象
Field field = c.getDeclaredField(colname);
// 私有屬性使用前必須賦權(quán)
field.setAccessible(true);
// 調(diào)用屬性對(duì)象的set方法為指定對(duì)象進(jìn)行賦值
field.set(obj, value);
}

// 列名循環(huán)結(jié)束后對(duì)應(yīng)對(duì)象屬性已經(jīng)全部進(jìn)行賦值
// 將對(duì)象存儲(chǔ)至集合中
list.add(obj);
}

} catch (Exception e) {
e.printStackTrace();
return null;
}
return list;
}

}
來源:https://www./content-2-784751.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    99国产一区在线播放| 天海翼高清二区三区在线| 少妇特黄av一区二区三区| 韩日黄片在线免费观看| 激情偷拍一区二区三区视频| 亚洲美女国产精品久久| 青青操成人免费在线视频| 国产日韩欧美专区一区| 久草国产精品一区二区| 亚洲一区二区欧美激情| 自拍偷女厕所拍偷区亚洲综合| 国产在线视频好看不卡| 亚洲中文字幕一区三区| 久久精品欧美一区二区三不卡| 欧美午夜视频免费观看| 黄片免费观看一区二区| 久久久免费精品人妻一区二区三区| 亚洲欧美日韩色图七区| 国产又粗又猛又爽又黄| 日本办公室三级在线观看| 日本加勒比系列在线播放| 最近最新中文字幕免费| 黄色片国产一区二区三区| 日本不卡视频在线观看| 亚洲人午夜精品射精日韩 | 国产不卡最新在线视频| av在线免费观看在线免费观看| 国产伦精品一区二区三区高清版| 好吊日成人免费视频公开| 国产一区日韩二区欧美| 久热99中文字幕视频在线| 国产熟女一区二区精品视频| 日韩成人动作片在线观看| 日韩人妻av中文字幕| 观看日韩精品在线视频| 国产精品一区欧美二区| 老司机精品视频免费入口| 国产在线一区中文字幕| 草草视频福利在线观看| 国产一区二区三区四区中文| 免费在线观看欧美喷水黄片|