B029-JDBC增強

目錄

      • PreparedStatement 查詢
        • 1.sql注入
        • 2.Statement分析 (面試題)
        • 3.PreparedStatement (面試題)
      • 登錄功能的完善
      • 事務
      • 鏈接池
        • 概念
        • 實現
          • DBCP連接池實現
            • 第一種配置方式
            • 第二種配置方式
      • 返回主鍵
      • BaseDao的抽取

PreparedStatement 查詢

1.sql注入

就是在sql的字符串拼接的時候,加入了特定的條件判斷,

如:SELECT * FROM student where name=’ 小坤坤255255 ’ OR 1=1

代碼

public class StudentDaoImpl  implements IStudentDao{//Statement的寫法@Overridepublic Student login(String name, String Password) {//通過工具類獲取連接Connection conn = JDBCUtil.Instance().getconn();Statement State =null;ResultSet rs=null;Student student = new Student();try {State = conn.createStatement();rs = State.executeQuery("select * from student where name='"+name+"'and password ='"+Password+"'");while (rs.next()) {student.setId(rs.getInt("id"));student.setName(rs.getString("name"));student.setPassword(rs.getString("password"));} } catch (SQLException e) {e.printStackTrace();}finally {JDBCUtil.Instance().close(rs, State, conn);}return student;}
}
public class JDBCTest {@Testpublic void testName() throws Exception {StudentDaoImpl studentDaoImpl = new  StudentDaoImpl();//正常的代碼
//		Student stu = studentDaoImpl.login("網通", "123");//sql注入的代碼Student stu = studentDaoImpl.login("網通", "123' or '1=1");System.out.println(stu);if(stu.getName()!=null){System.out.println("賬號存在登錄成功");}else{System.out.println("賬號不存在  ..登錄失敗");}}
}
2.Statement分析 (面試題)

1.通過上面sql注入的案例我們發現 Statement 它可能會導致sql注入的問題
2.通過這幾天的sql的書寫我發現 Statement 拼接sql相當復雜,稍微有一點點差錯就會導致sql語句有問題

解決方法:PreparedStatement

3.PreparedStatement (面試題)

PreparedStatement 很好的解決了Statement的問題
1.不用擔心注入問題(雙引號之內看成一個整體的字符串而不是兩個字符串和一個關鍵字),
2.sql語句不用復雜拼接,
3.會預處理sql語句,執行速度也更快

代碼:
StudentDaoImpl

	//PreparedStatement寫法@Overridepublic Student login(String name, String Password) {Connection conn = JDBCUtil2.Instance().getconn();PreparedStatement ps=null;ResultSet rs =null;Student student = new Student();try {ps= conn.prepareStatement("select * from student  where name=? and password=?");ps.setString(1, name);ps.setString(2, Password);rs = ps.executeQuery();while(rs.next()){student.setId(rs.getInt("id"));student.setName(rs.getString("name"));student.setPassword(rs.getString("password"));}} catch (SQLException e) {e.printStackTrace();}finally {JDBCUtil2.Instance().close(rs, ps, conn);}return student;}

JDBCTest

	@Testpublic void testName() throws Exception {StudentDaoImpl studentDaoImpl = new  StudentDaoImpl();//正常的代碼
//		Student stu = studentDaoImpl.login("網通", "123");//sql注入的代碼Student stu = studentDaoImpl.login("網通", "123' or '1=1");System.out.println(stu);if(stu.getName()!=null){System.out.println("賬號存在登錄成功");}else{System.out.println("賬號不存在  ..登錄失敗");}}

問題:PreparedStatement和Statement 不是同一個類為什么關資源的時候可以傳PreparedStatement
因為 PreparedStatement 繼承了 Statement,(多態)

PreparedStatement :

  // 預處理 這時候就會把sql發送到數據庫了,只是這時還不會執行sqlselect * from student  where name=? and password=? 		//變量位置使用?先占住,(這時已經發了sql語句了)ps= conn.prepareStatement("select * from student  where name=? and password=?");// 把?替換成對應的值ps.setString(1, name);ps.setString(2, Password);// 執行sql  這時的執行就是一個執行命令,不會發sql語句(前面已發)rs = ps.executeQuery();

Statement:

  //創建 Statement 對象 State = conn.createStatement();// 發送并執行sql rs = State.executeQuery("select * from student where name='"+name+"'and password ='"+Password+"'");

PreparedStatement 是 Statement 子類,速度比Statement 快,能避免sql 注入,可以不用拼接sql語句

登錄功能的完善

StudentDaoImpl

	@Overridepublic Student QueryByUsername(String name) {Connection conn = JDBCUtil2.Instance().getconn();PreparedStatement ps = null;ResultSet rs = null;Student student = new Student();try {ps = conn.prepareStatement("select * from student where name=?");ps.setString(1, name);rs = ps.executeQuery();while (rs.next()) {student.setId(rs.getInt("id"));student.setName(rs.getString("name"));student.setPassword(rs.getString("password"));}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtil2.Instance().close(rs, ps, conn);}return student;}

JDBCTest

	// 登錄的第二種實現方式@Testpublic void login() throws Exception {StudentDaoImpl studentDaoImpl = new StudentDaoImpl();// 查詢是小坤坤(用戶名)的信息,這個用戶名 應該是前臺(瀏覽器) 用戶 傳過來的 -- 模擬Student student = studentDaoImpl.QueryByUsername("小坤坤");// 判斷用戶名是否存在if (student.getName() == null) {System.out.println("賬號不存在");}// else 就是賬號存在else {// 判斷這個賬號的密碼是否正確 (這個密碼應該是前臺(瀏覽器) 用戶 傳過來的)if (!"8848".equals(student.getPassword())) {System.err.println("密碼錯誤");} else {System.out.println("登錄成功");}}}

事務

	@Testpublic void Testtrans() throws Exception {Connection connection = null;PreparedStatement ps = null;PreparedStatement ps2 = null;try {connection = JDBCUtil2.Instance().getconn();// 不提交事務 (sql執行了,改變了數據庫的數據,但是后面沒有寫提交事務數據庫就不能有變化),connection.setAutoCommit(false);String sql = "update bank set money=money-1000 where name='過兒'";ps = connection.prepareStatement(sql);ps.execute();// 在這個位置 出現異常int a=0/0;String sql2 = "update bank set money=money+1000 where name='姑姑'";ps2 = connection.prepareStatement(sql2);ps2.execute();// 提交事物 (數據庫可以發生變化了)connection.commit();} catch (Exception e) {// 回滾 (你數據庫改變了之后我還是可以回滾)/*當我們把自動提交關閉,那sql就不是提交執行,于是我們一定要記住,當我們一個整體功能完成之后,自己要手動進行提交;--conn.commit但是失敗之后,要記住數據回滾*/connection.rollback();} finally {ps2.close();ps.close();connection.close();}}

ACID (面試)
事務 : 一組操作 要么都成功 要么都失敗
事務具有4個特征,分別是原子性、一致性、隔離性和持久性,簡稱事務的ACID特性;
原子性(atomicity) :一個事務要么全部提交成功,要么全部失敗回滾,不能只執行其中的一部分操作
一致性(consistency) : 一個事務執行前后,數據庫都處于一致性狀態
隔離性(isolation): 每一個事務都是單獨的,事務和事務之間不影響
持久性(durability): 事務執行完了, 持久化到數據庫

鏈接池

概念

在這里插入圖片描述
你創建了一個池塘 池塘里面你放了很多鏈接 用完了就放回去 -->節省開關鏈接的時間

實現

在Java中,連接池使用javax.sql.DataSource接口來表示連接池,這里的DataSource就是連接池,連接池就是DataSource。
DataSource是接口,和JDBC一樣,是Sun公司開發的一套接口,需要各大廠商實現;
需要導入相應包—導包…
所以使用連接池,首先需要導包;

常用的DataSource的實現有下面兩種方式:
DBCP: Spring推薦的(Spring框架已經集成DBCP)
C3P0: Hibernate推薦的(早期)(Hibernate框架已經集成C3P0)持久層

DBCP連接池實現

1.導入jar包
commons-dbcp-1.3.jar,commons-pool-1.5.6.jar

2.代碼
BasicDataSource就是DBCP的連接池實現

第一種配置方式
public class JDBCUtil {// 構造方法私有化private JDBCUtil() {};private static JDBCUtil instance;// 一啟動就加載驅動 只執行一次static Properties ps = null;static BasicDataSource ds = null;static {ps = new Properties();try {ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));ds = new BasicDataSource();ds.setDriverClassName(ps.getProperty("dirverClassName"));ds.setUsername(ps.getProperty("username"));ds.setPassword(ps.getProperty("password"));ds.setUrl(ps.getProperty("url"));} catch (IOException e) {e.printStackTrace();}/*		 try {ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));Class.forName(ps.getProperty("dirverClassName"));} catch (Exception e) {e.printStackTrace();}*/instance = new JDBCUtil();}public static JDBCUtil Instance() {return instance;}// 寫加載數據庫的驅動public Connection getconn() {Connection connection = null;try {//換成新的獲取連接池的方式connection = ds.getConnection();// connection = DriverManager.getConnection(ps.getProperty("url"),// ps.getProperty("username"), ps.getProperty("password"));} catch (Exception e) {e.printStackTrace();}return connection;}// 關閉資源public void close(ResultSet rs, Statement State, Connection conn) {try {if (rs != null) {rs.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (State != null) {State.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (conn != null) {conn.close();}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
}
public class test {public static void main(String[] args) {Connection connection = JDBCUtil.Instance().getconn();try {String sql = "update bank set money=money-500 where name='過兒'";PreparedStatement ps = connection.prepareStatement(sql);ps.execute();} catch (SQLException e) {e.printStackTrace();}}
}
第二種配置方式
public class JDBCUtil2 {// 構造方法私有化private JDBCUtil2() {};private static JDBCUtil2 instance;// 一啟動就加載驅動 只執行一次static Properties ps = null;static DataSource ds = null;static {ps = new Properties();try {ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));// 創建連接池ds = BasicDataSourceFactory.createDataSource(ps);} catch (Exception e) {e.printStackTrace();}// try {// 		ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));// 		Class.forName(ps.getProperty("dirverClassName"));// } catch (Exception e) {// 		e.printStackTrace();// }instance = new JDBCUtil2();}public static JDBCUtil2 Instance() {return instance;}// 寫加載數據庫的驅動public Connection getconn() {Connection connection = null;try {//換成新的獲取連接池的方式connection = ds.getConnection();// connection = DriverManager.getConnection(ps.getProperty("url"),// ps.getProperty("username"), ps.getProperty("password"));} catch (Exception e) {e.printStackTrace();}return connection;}// 關閉資源public void close(ResultSet rs, Statement State, Connection conn) {try {if (rs != null) {rs.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (State != null) {State.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}}}
}
public class test {public static void main(String[] args) {Connection connection = JDBCUtil2.Instance().getconn();try {String sql = "update bank set money=money-500 where name='過兒'";PreparedStatement ps = connection.prepareStatement(sql);ps.execute();} catch (SQLException e) {e.printStackTrace();}}
}

返回主鍵

場景舉例:先后添加product和product_stock時,需要拿到product插入時自增的id存到product_stock的product_id里

看文檔做

StudentDaoImpl

	@Overridepublic void insert(Student stu) {Connection conn = JDBCUtil.Instance().getconn();PreparedStatement ps = null;try {String sql = "insert into student(name,password) values(?,?)";ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);ps.setString(1, stu.getName());ps.setString(2, stu.getPassword());ps.executeUpdate();ResultSet rs = ps.getGeneratedKeys();while (rs.next()) {System.err.println(rs.getInt(1));}} catch (SQLException e) {e.printStackTrace();}}

JDBCTest

	@Testpublic void addStudent() throws Exception {StudentDaoImpl studentDaoImpl = new StudentDaoImpl();Student stu = new Student();stu.setName("小波波");stu.setPassword("857857958958");studentDaoImpl.insert(stu);}

BaseDao的抽取

BaseDao

public class BaseDao {public void excuteUpdate(String sql, Object... objects) {Connection conn = JDBCUtil2.Instance().getconn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql);for (int i = 0; i < objects.length; i++) {ps.setObject(i + 1, objects[i]);}ps.execute();} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtil2.Instance().close(null, ps, conn);}}
}

實現類:

public class StudentDaoImpl extends BaseDao  implements IStudentDao{@Overridepublic void insert(Student stu) {String  sql="insert into student(name,password) values(?,?)";excuteUpdate(sql, stu.getName(),stu.getPassword());}@Overridepublic void update(Student stu) {String sql = "update student set name=?,password=? where id =?";excuteUpdate(sql, stu.getName(),stu.getPassword(),stu.getId());}@Overridepublic void delete(Student stu) {String sql = "delete from student where id = ?";excuteUpdate(sql, stu.getId());}
}

JDBCTest

	@Testpublic void addStudent() throws Exception {StudentDaoImpl studentDaoImpl = new StudentDaoImpl();Student stu = new Student();stu.setName("小波波");stu.setPassword("857857");stu.setId(254172);
//		studentDaoImpl.insert(stu);
//		studentDaoImpl.delete(stu);studentDaoImpl.update(stu);}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215710.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215710.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215710.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于單片機的定時插座在智能家居中的應用

近年來&#xff0c;隨著科學技術的發展迅速&#xff0c;人們對智能化的要求越來越高。越來越多的智能化產品進入千家萬戶&#xff0c;如電腦電視、掃地機器人、智能空氣凈化器等。這些家居電器和電子產品大都需要連接電源&#xff0c;為滿足多種用電器的正常使用&#xff0c;延…

DevEco Studio 生成HPK文件

DevEco Studio 生成HPK文件 一、安裝環境 操作系統: Windows 10 專業版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、生成HPK文件 生成的HPK文件存放在entry文件夾下。下圖是未生成HPK的樣式。 生成HPK&#xff1a;菜單Build->Build Hap(s)/APP(s)->Build Hap(s)…

啟動jar包命令

一、Windows環境 找到jar包的位置&#xff1b; 按shift鍵&#xff0c;點擊鼠標右鍵&#xff0c;選中在此處打開PowerShell窗口&#xff1b; 此時進入命令行工具 輸入java -jar .\java_web-0.0.1-SNAPSHOT.jar&#xff08;注意空格&#xff09;。 二、Linux環境 2.1 方式一 …

039.Python面向對象_三大特性綜合案例2

我 的 個 人 主 頁&#xff1a;&#x1f449;&#x1f449; 失心瘋的個人主頁 &#x1f448;&#x1f448; 入 門 教 程 推 薦 &#xff1a;&#x1f449;&#x1f449; Python零基礎入門教程合集 &#x1f448;&#x1f448; 虛 擬 環 境 搭 建 &#xff1a;&#x1f449;&…

一、微前端目標、前端架構的前生今世、微前端架構優勢和劣勢、軟件設計原則與分層

1、目標 2、前端架構的前世今生 ① 初始&#xff1a;無架構&#xff0c;前端代碼內嵌到后端應用中 ② 后端 MVC 架構&#xff1a;將視圖層、數據層、控制層做分離 缺點&#xff1a;重度依賴開發環境&#xff0c;代碼混淆嚴重&#xff08;在調試時&#xff0c;需要啟動后端所有…

小型洗衣機哪個牌子質量好?迷你洗衣機排名前十名

隨著內衣洗衣機的流行&#xff0c;很多小伙伴在糾結該不該入手一款內衣洗衣機&#xff0c;專門來洗一些貼身衣物&#xff0c;答案是非常有必要的&#xff0c;因為我們現在市面上的大型洗衣機只能做清潔&#xff0c;無法對我們的貼身衣物進行一個高強度的清潔&#xff0c;而小小…

【CCF BDCI 2023】多模態多方對話場景下的發言人識別 Baseline 0.71 NLP 部分

【CCF BDCI 2023】多模態多方對話場景下的發言人識別 Baseline 0.71 NLP 部分 概述NLP 簡介文本處理詞嵌入上下文理解 文本數據加載to_device 函數構造數據加載樣本數量 len獲取樣本 getitem 分詞構造函數調用函數輪次嵌入 RobertaRoberta 創新點NSP (Next Sentence Prediction…

23種設計模式之裝飾者模式(被裝飾者,接口層,裝飾抽象層,具體裝飾者)

23種設計模式之裝飾者模式 文章目錄 23種設計模式之裝飾者模式設計思想裝飾者模式的優點裝飾者模式的缺點裝飾者模式的優化方法UML 解析預設場景 代碼釋義總結 設計思想 原文:裝飾器模式&#xff08;Decorator Pattern&#xff09;允許向一個現有的對象添加新的功能&#xff0…

應用在LED燈光控制觸摸屏中的觸摸芯片

LED燈光控制觸摸屏方法&#xff0c;包括&#xff1a;建立觸摸屏的觸摸軌跡信息與LED燈光驅動程序的映射關系&#xff1b;檢測用戶施加在觸摸屏上的觸摸軌跡&#xff0c;生成觸摸軌跡信息&#xff1b;根據生成的觸摸軌跡信息&#xff0c;調用對應的LED燈光驅動程序&#xff0c;控…

HJ14 字符串排序

一、題目 描述 給定 n 個字符串&#xff0c;請對 n 個字符串按照字典序排列。數據范圍&#xff1a; 1 \le n \le 1000 \1≤n≤1000 &#xff0c;字符串長度滿足 1 \le len \le 100 \1≤len≤100 輸入描述&#xff1a; 輸入第一行為一個正整數n(1≤n≤1000),下面n行為n個字符…

智能優化算法應用:基于頭腦風暴算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用&#xff1a;基于頭腦風暴算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用&#xff1a;基于頭腦風暴算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.頭腦風暴算法4.實驗參數設定5.算法結果6.…

說說React中的虛擬dom?在虛擬dom計算的時候diff和key之間有什么關系?

虛擬 DOM&#xff08;Virtual DOM&#xff09;是 React 中的一種機制&#xff0c;通過在內存中構建一棵輕量級的虛擬 DOM 樹來代替操作瀏覽器 DOM&#xff0c;從而提高組件的渲染性能和用戶體驗。 在 React 中&#xff0c;當組件的 Props 或 State 發生變化時&#xff0c;Reac…

智能優化算法應用:基于蝙蝠算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用&#xff1a;基于蝙蝠算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用&#xff1a;基于蝙蝠算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.蝙蝠算法4.實驗參數設定5.算法結果6.參考文獻7.MA…

酷開科技多維度賦能營銷,實力斬獲三項大獎

在數智化新階段、廣告新生態、傳播新業態的背景下&#xff0c;“第30屆中國國際廣告節廣告主盛典暨網易傳媒態度營銷峰會”于11月18日在廈門國際會展中心盛大舉行。來自全國的品牌方、戰略決策者、媒體平臺和品牌服務機構等匯聚一堂。在50000&#xff0b;現場觀眾和數千萬線上觀…

openssl的x509命令工具

X509命令是一個多用途的證書工具。它可以顯示證書信息、轉換證書格式、簽名證書請求以及改變證書的信任設置等。 用法&#xff1a; openssl x509 [-inform DER|PEM|NET] [-outform DER|PEM|NET] [-keyform DER|PEM] [-CAform DER|PEM] [-CAkeyform DER|PEM] [-in filename…

vue elementui點擊按鈕新增輸入框(點多少次就新增多少個輸入框,無限新增)

效果如圖&#xff1a; 核心代碼&#xff1a; <div v-for"(item,index) in arrayData" :key"item.id">//上面這個是關鍵代碼&#xff0c;所有思路靠這個打通<el-inputtype"input" //除了輸入框&#xff0c;還有textarea等placeholder&…

SequentialChain

以下是使用SequentialChain創建Java代碼的單元測試代碼的示例&#xff1a; import sequentialchain.SequentialChain; import static org.junit.Assert.assertEquals; import org.junit.Test;public class SequentialChainTest {Testpublic void testAdd() {SequentialChain&l…

k8s詳細教程(一)

—————————————————————————————————————————————— 博主介紹&#xff1a;Java領域優質創作者,博客之星城市賽道TOP20、專注于前端流行技術框架、Java后端技術領域、項目實戰運維以及GIS地理信息領域。 &#x1f345;文末獲取源碼…

《Spring Cloud Alibaba 從入門到實戰》分布式消息(事件)驅動

分布式消息&#xff08;事件&#xff09;驅動 1、簡介 事件驅動架構(Event-driven 架構&#xff0c;簡稱 EDA)是軟件設計領域內的一套程序設計模型。 這套模型的意義是所有的操作通過事件的發送/接收來完成。 傳統軟件設計 舉個例子&#xff0c;比如一個訂單的創建在傳統軟…

「差生文具多系列」推薦兩個好看的 Redis 客戶端

&#x1f4e2;?聲明&#xff1a; &#x1f344; 大家好&#xff0c;我是風箏 &#x1f30d; 作者主頁&#xff1a;【古時的風箏CSDN主頁】。 ?? 本文目的為個人學習記錄及知識分享。如果有什么不正確、不嚴謹的地方請及時指正&#xff0c;不勝感激。 直達博主&#xff1a;「…