日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

五、JDBC(复习)

發布時間:2024/3/13 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五、JDBC(复习) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、JDBC核心組件

二、使用步驟

三、連接步驟

1.導包? ??

2.注冊JDBC驅動程序:

?3.數據庫URL配置,創建連接對象

(1)加載驅動

(2)獲得鏈接

(3)定義sql,創建狀態通道

(4)關閉資源

(5)完整代碼

四、SQl注入和預狀態通道PreparedStatement

五、多表操作

1.創建bean下的實體

2.創建接口和實現接口

3.在demo中打印查詢結果

4.結果

六、事務的應用

1.自動提交/手動提交切換

2.事務的提交commit和回滾rollback

3.保存點Savepoints

七、JDBC批處理

?1.Statement批處理

2.PreparedStatement批處理

八、反射處理結果集

九、封裝工具類

十、屬性文件

十一、連接池

1.DBCP(不可以自動回收空閑連接)

2.C3P0(自動回收空閑連接)

3.Druid德魯伊(阿里開發)


JDBC是一種用于執行SQL語句的Java API,可以在各種平臺上使用Java,如Windows,Mac OS和各種版本的UNIX。

一、JDBC核心組件

DriverManager: 此類管理數據庫驅動程序列表。使用通信子協議將來自java應用程序的連接請求 與適當的數據庫驅動程序匹配。
Driver:此接口處理與數據庫服務器的通信,我們很少會直接與Driver對象進行交互。而是使用 DriverManager對象來管理這種類型的對象。
Connection:該界面具有用于聯系數據庫的所有方法。連接對象表示通信上下文,即,與數據庫 的所有通信僅通過連接對象。
Statement:使用從此接口創建的對象將SQL語句提交到數據庫。除了執行存儲過程之外,一些派 生接口還接受參數。
ResultSet:在使用Statement對象執行SQL查詢后,這些對象保存從數據庫檢索的數據。它作為一 個迭代器,允許我們移動其數據。
SQLException:此類處理數據庫應用程序中發生的任何錯誤

二、使用步驟

構建JDBC應用程序涉及以下六個步驟:
- 導入包:需要包含包含數據庫編程所需的JDBC類的包。大多數情況下,使用import java.sql.*就足夠 了。
- 注冊JDBC驅動程序:要求您初始化驅動程序,以便您可以打開與數據庫的通信通道。
- 打開連接:需要使用DriverManager.getConnection()方法創建一個Connection對象,該對象表 示與數據庫的物理連接。
- 執行查詢:需要使用類型為Statement的對象來構建和提交SQL語句到數據庫。
- 從結果集中提取數據:需要使用相應的ResultSet.getXXX()方法從結果集中檢索數據。
- 釋放資源:需要明確地關閉所有數據庫資源,而不依賴于JVM的垃圾收集。

三、連接步驟

1.導包? ??

import java.sql.*

2.注冊JDBC驅動程序:

? ? ? ? 工程下創建lib文件夾,把mysql-connector壓縮包放入lib下,點擊左上角文件復選框-項目結構,打開此界面,點擊依賴

點擊+,單擊第一個JAR或目錄,找到剛剛的lib文件下壓縮包,點擊確定注入。

?

?3.數據庫URL配置,創建連接對象

這是為了創建一個格式正確的地址,指向要連接到的數據庫。

(1)加載驅動

Class.forName("com.mysql.cj.jdbc.Driver");//從本地工程加載驅動

(2)獲得鏈接

創建數據庫連接對象

String userName = "root";//數據庫用戶名 String userPassword = "123456";//數據庫密碼 String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//數據庫mysql8 URL配置 Connection connection = DriverManager.getConnection(url,userName, userPassword);

加載驅動程序后,可以使用DriverManager.getConnection()方法建立連接。
- getConnection(String url)
- getConnection(String url,Properties prop)
- getConnection(String url,String user,String password)

完整的連接地址:
第一種:jdbc:mysql://localhost:3306/yhp2?serverTimezone=UTC
? ? ? ??localhost:數據庫地址,本地就是這個?3306:數據庫所用的端口?yhp2:要打開的數據庫名
第二種:jdbc:mysql://localhost:3306/數據庫名?useSSL=false&useUnicode=true&characterEncoding=UTF-8

(3)定義sql,創建狀態通道

Statement statement = connection.createStatement(); ResultSet resultSet=statement.executeQuery("select * from student;");//執行查詢while (resultSet.next()) {System.out.println("編號:"+resultSet.getInt("stuid")+"\t姓名" +resultSet.getString("name")+"\t\t生日"+resultSet.getDate("birthday")); } 執行查詢的語句:返回的是一個結果集(executeQuery) resultSet=statement.executeQuery("select * from student;");

執行增刪改的語句,返回數大于0成功,否則失敗。(executeUpdate)
int i=statement.executeUpdate("update student set birthday='1011-1-1' ");

ResultSet:
用resultset接收結果集

(4)關閉資源

resultSet.close(); statement.close(); connection.close();

(5)完整代碼

import java.sql.*;public class Demo1 {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String userName = "root";String userPassword = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, userName, userPassword);statement = connection.createStatement();resultSet = statement.executeQuery("select * from student;");while (resultSet.next()) {System.out.println("編號:" + resultSet.getInt("stuid")+ "\t姓名" + resultSet.getString("name")+ "\t\t生日" + resultSet.getDate("birthday"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}} }

四、SQl注入和預狀態通道PreparedStatement

? ? ? ? 現在網站比較安全,但還是要考慮到。sql注入就是在執行sql語句的時候,比如輸入密碼的時候夾帶別的對數據庫安全有威脅的sql語句,如密碼輸入 or 1=1;那樣條件恒等,就可以隨便進入

預狀態通道,PreparedStatement此種方式將sql語句中的輸入用?代替,確保sql語句的本塊在傳到了數據庫執行時帶有引號如錯誤密碼變成了?' 123456 or 1=1',因為有了引號就都變成了字符串,or不會再被當成條件執行,之后按照從1開始1的下標順序以此給?賦值

此代碼塊和第三模塊第(3)定義sql,創建狀態通道相通,經過更改后變成下面,換了案例,用用戶名和密碼為例子

String sql = "select * from userVIP where userName=? and userPass=?";//問號占位 PreparedStatement preparedStatement = connection.prepareStatement(sql);//PreparedStatement接收數據 preparedStatement.setString(1, "張三");//按照從1開始的下標順序給sql語句中的問號賦值 preparedStatement.setString(2, "123456"); resultSet = preparedStatement.executeQuery();

解決了sql注入后的完整代碼

import java.sql.*;public class Demo1 {public static void main(String[] args) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String userName = "root";String userPassword = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";;connection = DriverManager.getConnection(url, userName, userPassword);String sql = "select * from userVIP where userName=? and userPass=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, "張三");preparedStatement.setString(2, "123456");resultSet = preparedStatement.executeQuery();while (resultSet.next()) {System.out.println("編號:"+resultSet.getInt("id")+"\t用戶名" +resultSet.getString("userName")+"\t\t密碼"+resultSet.getString("userPass"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (preparedStatement != null) {preparedStatement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}} }


五、多表操作

? ? ? ? 一對多,多對一,一對一,多對多

記錄一個多對多

一個學生可以學很多課程,一個課程也可以有很多學生在學,形成多對多關系。

1.創建bean下的實體

Student

package bean;import java.util.List;public class Student {private int stuid;private String stuname;private int teacherid;private List<Subject> subjects;public int getStuid() {return stuid;}public void setStuid(int stuid) {this.stuid = stuid;}public String getStuname() {return stuname;}public void setStuname(String stuname) {this.stuname = stuname;}public int getTeacherid() {return teacherid;}public void setTeacherid(int teacherid) {this.teacherid = teacherid;}public List<Subject> getSubjects() {return subjects;}public void setSubjects(List<Subject> subjects) {this.subjects = subjects;} }

Subject

package bean;import java.util.List;public class Subject {private int subid;private String subname;private List<Student> students;public int getSubid() {return subid;}public void setSubid(int subid) {this.subid = subid;}public String getSubname() {return subname;}public void setSubname(String subname) {this.subname = subname;}public List<Student> getStudents() {return students;}public void setStudents(List<Student> students) {this.students = students;} }

2.創建接口和實現接口

接口功能是根據科目id查找誰在學習本課程,或者根據學生id查找這個學生學習了哪些課程。

interface StudentSubjectDao package impl;import bean.Student; import bean.Subject;public interface StudentSubjectDao {Subject getSubjectId(int subid);Student getStudentId(int stuid); } StudentSubjectDaoImp package dao;import bean.Student; import bean.Subject; import impl.StudentSubjectDao;import java.sql.*; import java.util.ArrayList; import java.util.List;public class StudentSubjectDaoImp implements StudentSubjectDao {@Overridepublic Subject getSubjectId(int subid) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String userName = "root";String userPass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, userName, userPass);String SQL = "select * FROM middle m,student st,subject su where m.stuid=st.stuid and m.subid=su.subid and m.subid=?";preparedStatement = connection.prepareStatement(SQL);preparedStatement.setInt(1, subid);resultSet = preparedStatement.executeQuery();Subject subject = new Subject();List<Student> students = new ArrayList<>();while (resultSet.next()) {subject.setSubid(resultSet.getInt("subid"));subject.setSubname(resultSet.getString("subname"));Student student = new Student();student.setStuname(resultSet.getString("stuname"));student.setStuid(resultSet.getInt("stuid"));students.add(student);}subject.setStudents(students);return subject;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}return null;}@Overridepublic Student getStudentId(int stuid) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String user = "root";String pass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, user, pass);String sql = "select * from middle m,student st,subject su where su.subid=m.subid and st.stuid=m.stuid and m.stuid=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, stuid);resultSet = preparedStatement.executeQuery();Student student = new Student();List<Subject> subjects = new ArrayList<>();while (resultSet.next()) {student.setStuid(resultSet.getInt("stuid"));student.setStuname(resultSet.getString("stuname"));Subject subject = new Subject();subject.setSubname(resultSet.getString("subname"));subject.setSubid(resultSet.getInt("subid"));subjects.add(subject);}student.setSubjects(subjects);return student;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (preparedStatement != null) {preparedStatement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return null;} }

3.在demo中打印查詢結果

package com;import bean.Student; import bean.Subject; import dao.StudentSubjectDaoImp; import impl.StudentSubjectDao;import java.util.List;public class Demo2 {public static void main(String[] args) {StudentSubjectDao studentSubjectDao2 = new StudentSubjectDaoImp();Subject subject = studentSubjectDao2.getSubjectId(2);List<Student> students = subject.getStudents();System.out.println(subject.getSubname() + subject.getSubid());for (Student student1 : students) {System.out.println(student1.getStuname() + student1.getStuid());}System.out.println("___________________________");StudentSubjectDao studentSubjectDao = new StudentSubjectDaoImp();Student student = studentSubjectDao.getStudentId(1);List<Subject> subjects = student.getSubjects();System.out.println(student.getStuname());for (Subject subject2 : subjects) {System.out.println(subject2.getSubname());}}}

4.結果

ui2 張三1 李四2 王五3 趙六4 花花5 瀟瀟6 ___________________________ 張三 java ui h5 c++進程已結束,退出代碼0

六、事務的應用

1.自動提交/手動提交切換

如果JDBC連接處于自動提交模式,默認情況下,則每個SQL語句在完成后都會提交到數據庫。 事務使您能夠控制是否和何時更改應用于數據庫。它將單個SQL語句或一組SQL語句視為一個邏輯單 元,如果任何語句失敗,則整個事務將失敗。 要啟用手動事務支持,而不是JDBC驅動程序默認使用的自動提交模式,請使用Connection對象的 setAutoCommit()方法。如果將boolean false傳遞給setAutoCommit(),則關閉自動提交。我們 可以傳遞一個布爾值true來重新打開它。

connection.setAutoCommit(false);//關閉事務自動提交 connection.setAutoCommit(true);

2.事務的提交commit和回滾rollback

conn.commit( );//提交事務 conn.rollback( );//回滾事務

可以在事務寫完之后加上conn.commit( );來提交事務,在catch代碼塊報異常時寫回滾rollback來撤銷此次事務的操作。

3.保存點Savepoints

新的JDBC 3.0 Savepoint接口為提供了額外的事務控制。 設置保存點時,可以在事務中定義邏輯回滾點。如果通過保存點發生錯誤,則可以使用回滾方法來撤消 所有更改或僅保存在保存點之后所做的更改。

Connection對象有兩種新的方法來管理保存點
- setSavepoint(String savepointName):定義新的保存點。它還返回一個Savepoint對象。
- releaseSavepoint(Savepoint savepointName):刪除保存點。請注意,它需要一個Savepoint 對象作為參數。此對象通常是由setSavepoint()方法生成的保存點。

try{ //Assume a valid connection object conn conn.setAutoCommit(false); Statement stmt = conn.createStatement(); String SQL1 = "INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez')"; stmt.executeUpdate(SQL1); Savepoint savepoint1 = conn.setSavepoint("Savepoint1");//設置保存點 String SQL2 = "INSERTED IN Employees VALUES (107, 22, 'Sita', 'Tez')"; stmt.executeUpdate(SQL2); conn.commit(); }catch(Exception se){ conn.rollback(savepoint1); }

上面一旦發生任何錯誤那么sql2就會執行失敗,但是如果sql1的語句是對的,那么還可以正常執行

如過此處沒有添加事務的概念,那么即使出現了其它的異常,只要sql語句沒問題,數據庫還是會改動數據,這樣有些需要同步執行的數據操作就會出現錯誤,如轉賬,一個加錢另一個卻沒減錢就很不合理。

七、JDBC批處理

?1.Statement批處理

????????- 使用createStatement()方法o創建Statement對象。
????????- 使用setAutoCommit()將auto-commit設置為false 。 (設置為手動提交事務)
????????- 使用addBatch()方法在創建的語句對象上添加您喜歡的SQL語句到批處理中。
????????- 在創建的語句對象上使用executeBatch()方法執行所有SQL語句。
????????- 最后,使用commit()方法提交所有更改。

Statement stmt = conn.createStatement(); conn.setAutoCommit(false);String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(200,'Zia','Ali', 30)"; stmt.addBatch(SQL);String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(201,'Raj','Kumar', 35)"; stmt.addBatch(SQL);String SQL = "UPDATE Employees SET age = 35 WHERE id = 100"; stmt.addBatch(SQL);int[] count = stmt.executeBatch(); conn.commit();

2.PreparedStatement批處理

String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(?, ?, ?, ?)";PreparedStatement pstmt = conn.prepareStatement(SQL);//處理sql語句 conn.setAutoCommit(false);//切換手動提交事務pstmt.setInt( 1, 400 );//問號賦值 pstmt.setString( 2, "Pappu" ); pstmt.setString( 3, "Singh" ); pstmt.setInt( 4, 33 );pstmt.addBatch();pstmt.setInt( 1, 401 ); pstmt.setString( 2, "Pawan" ); pstmt.setString( 3, "Singh" ); pstmt.setInt( 4, 31 );pstmt.addBatch();int[] count = stmt.executeBatch();//執行所有sql語句conn.commit();

八、反射處理結果集

????????

interface StudentSubjectDao package impl;import bean.Student;import java.util.List;public interface StudentSubjectDao {List<Student> getAllStudent(Class cla); } StudentSubjectDaoImp implements StudentSubjectDao package dao;import bean.Student; import bean.Subject; import impl.StudentSubjectDao;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.*; import java.util.ArrayList; import java.util.List;public class StudentSubjectDaoImp implements StudentSubjectDao {@Overridepublic List<Student> getAllStudent(Class cla) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String user = "root";String pass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, user, pass);String sql = "select * from student";preparedStatement = connection.prepareStatement(sql);resultSet = preparedStatement.executeQuery();List students = new ArrayList<>();//1.得到數據庫的查詢結果的列信息ResultSetMetaData metaData = resultSet.getMetaData();int columnCount = metaData.getColumnCount();//得到列名,返回列名數量String[] columnNames = new String[columnCount];//列名for (int i = 0; i < columnCount; i++) {columnNames[i]=metaData.getColumnName(i+1);//將結果集中的列名取出來 // System.out.println(columnNames[i]);}//2.得到類中方法Method[] declaredMethods = cla.getDeclaredMethods();//通過傳來的cla得到student方法while (resultSet.next()) {try {Object stu=cla.getDeclaredConstructor().newInstance();//創建對象for (String columnName : columnNames) {//遍歷結果的列名String methodName = "set"+columnName;//set組合列名for (Method declaredMethod : declaredMethods) {//遍歷方法集if (declaredMethod.getName().equalsIgnoreCase(methodName)){//如果student中某個的方法名和set加結果集列名組合的方法名一樣declaredMethod.invoke(stu,resultSet.getObject(columnName));//調用這個set方法將結果集中的數據賦值給這個studen對象break;}}}students.add(stu);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}return students;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (preparedStatement != null) {preparedStatement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return null;} }

demo

package com;import bean.Student; import dao.StudentSubjectDaoImp; import impl.StudentSubjectDao;import java.util.List;public class Demo3 {public static void main(String[] args) {StudentSubjectDao studentSubjectDao = new StudentSubjectDaoImp();List<Student> allStudent = studentSubjectDao.getAllStudent(Student.class);for (Student student : allStudent) {System.out.println(student.getStuid()+student.getStuname()+student.getTeacherid());}} }

結果

1張三3 2李四1 3王五3 4趙六1 5花花1 6瀟瀟2

九、封裝工具類

通過工具類可以極大地簡化代碼

DBUtils package util;import java.sql.*; import java.util.List;public class DBUtils {private Connection connection = null;private PreparedStatement preparedStatement = null;private ResultSet resultSet = null;private int count;//統計增刪改操作受影響的行數String userName = "root";String userPass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//加載驅動static {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 獲得連接*/protected Connection getConnection() {try {connection = DriverManager.getConnection(url, userName, userPass);} catch (SQLException e) {e.printStackTrace();}return connection;}/*** 得到預狀態通道*/protected PreparedStatement getPreparedStatement(String sql) {try {preparedStatement = getConnection().prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return preparedStatement;}/*** 綁定參數* List保存的是給占位符所賦的值,即?部分的值*/protected void param(List list) {if (list != null && list.size() > 0) {for (int i = 0; i < list.size(); i++) {try {preparedStatement.setObject(i + 1, list.get(i));} catch (SQLException e) {e.printStackTrace();}}}}/*** 更新操作*/protected int upData(String sql, List list) {try {getPreparedStatement(sql);//獲得預狀態通道param(list);//補全sql中問號部分count = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return count;}/*** 查詢操作*/protected ResultSet query(String sql, List list) {try {getPreparedStatement(sql);//獲得預狀態通道param(list);//補全sql中問號部分resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}/*** 關閉資源*/protected void closeAll() {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}} StudentSubjectDaoImp extends DBUtils implements StudentSubjectDao(繼承工具類以直接使用工具類DBUtils中的方法) public class StudentSubjectDaoImp extends DBUtils implements StudentSubjectDao { @Overridepublic Student getByStudentId(int stuid) {Student student = new Student();try {String sql="select * from student where stuid=?";List list = new ArrayList();list.add(stuid);ResultSet resultSet = query(sql,list);while (resultSet.next()){student.setStuid(resultSet.getInt("stuid"));student.setStuname(resultSet.getString("stuname"));}} catch (SQLException e) {e.printStackTrace();}return student;} }

demo(通過學號查找人)

package com;import bean.Student; import dao.StudentSubjectDaoImp; import impl.StudentSubjectDao;public class Demo4 {public static void main(String[] args) {StudentSubjectDao studentSubjectDao = new StudentSubjectDaoImp();Student student = studentSubjectDao.getByStudentId(2);System.out.println(student.getStuid()+student.getStuname());} }

十、屬性文件

用來存儲用戶名密碼url等信息

db.properties userName=root userPass=123456 url=jdbc:mysql://localhost:3306/practice?serverTimezone=UTC driver=com.mysql.cj.jdbc.Driver

?加載驅動的兩種方法

//方法1 InputStream inputStream = 當前類名.class.getClassLoader() .getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(inputStream); dirverName = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("user"); password = properties.getProperty("password");//方法2 ResourceBundle bundle = ResourceBundle.getBundle("db"); driver = bundle.getString("driver"); url = bundle.getString("url"); userName = bundle.getString("userName"); userPass = bundle.getString("userPass"); Class.forName(driver);

完整DBUtils

package util;import java.sql.*; import java.util.List; import java.util.ResourceBundle;public class DBUtils {private Connection connection = null;private PreparedStatement preparedStatement = null;private ResultSet resultSet = null;private int count=0;//統計增刪改操作受影響的行數private static String userName;private static String userPass;private static String url;private static String driver;//加載驅動static {try {ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");userName = bundle.getString("userName");userPass = bundle.getString("userPass");Class.forName(driver);} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 獲得連接*/protected Connection getConnection() {try {connection = DriverManager.getConnection(url, userName, userPass);} catch (SQLException e) {e.printStackTrace();}return connection;}/*** 得到預狀態通道*/protected PreparedStatement getPreparedStatement(String sql) {try {preparedStatement = getConnection().prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return preparedStatement;}/*** 綁定參數* List保存的是給占位符所賦的值,即?部分的值*/protected void param(List list) {if (list != null && list.size() > 0) {for (int i = 0; i < list.size(); i++) {try {preparedStatement.setObject(i + 1, list.get(i));} catch (SQLException e) {e.printStackTrace();}}}}/*** 更新操作* 參數含義(sql語句,?占位符上的值)* @return 返回受影響的行數*/protected int upData(String sql, List list) {try {getPreparedStatement(sql);//獲得預狀態通道param(list);//補全sql中問號部分count = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return count;}/*** 查詢操作* 參數含義(sql語句,?占位符上的值)* @return 查詢數據庫返回的結果集*/protected ResultSet query(String sql, List list) {try {getPreparedStatement(sql);//獲得預狀態通道param(list);//補全sql中問號部分resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}/*** 關閉資源*/protected void closeAll() {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}}

十一、連接池

*連接池基本的思想是在系統初始化的時候,將數據庫連接作為對象存儲在內存中,當用戶需要訪問數 據庫時,并非建立一個新的連接,而是從連接池中取出一個已建立的空閑連接對象。使用完畢后,用戶 也并非將連接關閉,而是將連接放回連接池中,以供下一個請求訪問使用。而連接的建立、斷開都由連 接池自身來管理。同時,還可以通過設置連接池的參數來控制連接池中的初始連接數、連接的上下限數 以及每個連接的最大使用次數、最大空閑時間等等,也可以通過其自身的管理機制來監視數據庫連接的數量、使用情況等。

*連接池用linklist默認初始化十個連接,其中有commit,rollback等常規方法,其中close方法在關閉資源時并不是真的關閉了資源,而是使用linklist的addlast方法將這個連接放在了連接池尾部,以待下次調用。 *最小連接數 : 是數據庫一直保持的數據庫連接數,所以如果應用程序對數據庫連接的使用量不大,將有大量的數據庫資源被浪費。 *初始化連接數: 連接池啟動時創建的初始化數據庫連接數量。 *最大連接數 是連接池能申請的最大連接數,如果數據庫連接請求超過此數,后面的數據庫連接請求被加入到等待隊列中。 *最大等待時間: 當沒有可用連接時,連接池等待連接被歸還的最大時間,超過時間則拋出異常,可設置參數為 0 或者負數 使得無限等待( 根據不同連接池配置 )
DBCPC3P0DRUID
最小連接數minldle(0)minPoolSize(3)mindle(o)
初始化連接數initialSize(0)initialPoolSize(3)initialSize(0)
最大連接數maxTotal(8)maxPoolSize(15)maxActive(8)
最大等待時間maxWaitMillis(毫秒)maxldleTime(0秒)maxWait(毫秒)

1.DBCP(不可以自動回收空閑連接)

先在lib文件夾下注入jia包

?將DBUtils部分的加載驅動和獲得連接部分做修改

private static BasicDataSource basicDataSource = new BasicDataSource(); //加載驅動static {ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");userName = bundle.getString("userName");userPass = bundle.getString("userPass");basicDataSource.setUsername(userName);//獲取用戶名basicDataSource.setPassword(userPass);//獲取密碼basicDataSource.setUrl(url);//獲取urlbasicDataSource.setDriverClassName(driver);//獲取驅動位置basicDataSource.setInitialSize(10);//設置初始連接數}/*** 獲得連接*/protected Connection getConnection() {try {connection = basicDataSource.getConnection();//獲得連接} catch (SQLException e) {e.printStackTrace();}return connection;}

2.C3P0(自動回收空閑連接)

在lib下注入jar包,src目錄下創建c3p0-config.xml文件

C3P0通過配置文件來完成所有操作,因此將原先db.properties中的信息寫入配置文件

<?xml version="1.0" encoding="UTF-8"?> <c3p0-config><default-config><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/practice?serverTimezone=UTC</property><property name="user">root</property><property name="password">123456</property><!-- 等待連接的超時時間,默認為0,代表無限等待,單位是毫秒 --><property name="checkoutTimeout">30000</property><!-- 檢查空閑連接 默認為0 代表不檢查 --><property name="idleConnectionTestPeriod">30</property><!-- 初始化連接 --><property name="initialPoolSize">10</property><!-- 最大空閑時間,超過這個時間的連接將被丟棄,默認為0,代表永遠不關閉 --><property name="maxIdleTime">30</property><!-- 最大連接數 --><property name="maxPoolSize">100</property><!-- 最小連接數 --><property name="minPoolSize">10</property><!-- preparedStatement的緩存大小 --><property name="maxStatements">200</property><!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。默認值: 3 --> <property name="AcquireIncrement">5</property></default-config></c3p0-config>

寫入配置文件后不用再手動加載驅動?,static加載驅動部分不用再寫

private static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();/*** 獲得連接*/protected Connection getConnection() {try {connection = comboPooledDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}

3.Druid德魯伊(阿里開發)

????????它不僅僅是一個數據庫連接池,它還包含一個 ProxyDriver(代理驅動),一系列內置的JDBC 組件庫,一個 SQL Parser(sql 解析器 ) 。支持所有 JDBC 兼 容的數據庫,包括Oracle MySql Derby Postgresql SQL Server H2 等等。 ????????Druid針對 Oracle MySql 做了特別優化,比如 Oracle PS Cache 內存占用優化, MySql ping 檢測優化。 ????????Druid提供了 MySql Oracle Postgresql SQL-92 SQL 的完整支持,這是一個手寫的高性能 SQL Parser,支持 Visitor 模式,使得分析 SQL 的抽象語法樹很方便。 簡單SQL 語句用時 10 微秒以內,復雜 SQL 用時 30 微秒。 ????????通過Druid 提供的 SQL Parser 可以在 JDBC 層攔截 SQL 做相應處理,比如說分庫分表、審計等。 Druid 防御SQL注入攻擊的WallFilter 就是通過 Druid SQL Parser 分析語義實現的。 ????????Druid 是目前比較流行的高性能的,分布式列存儲的 OLAP 框架 ( 具體來說是 MOLAP) 。它有如下幾個特點 . 亞秒級查詢 ????????druid提供了快速的聚合能力以及亞秒級的 OLAP 查詢能力,多租戶的設計,是面向用戶分析應用的理想方式。 . 實時數據注入 druid 支持流數據的注入,并提供了數據的事件驅動,保證在實時和離線環境下事件的實效性和統一性 . 可擴展的 PB 級存儲 druid 集群可以很方便的擴容到 PB 的數據量,每秒百 萬級別的數據注入。即便在加大數據規模的情況下,也能保證時其效性 . 多環境部署 druid 既可以運行在商業的硬件上,也可以運行在云上。它可以從多種數據系統中注入數據,包括 hadoop spark kafka storm samza . 豐富的社區 使用方法: 在lib下注入jar包 獲得對象,手動獲取地址,需要注意德魯伊默認最大活躍連接數量是8因此如果要設置大于8的活躍連接數應該先設置上限

?

//Druid對象private static DruidDataSource druidDataSource = new DruidDataSource();//加載驅動static {ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");userName = bundle.getString("userName");userPass = bundle.getString("userPass");druidDataSource.setUrl(url);druidDataSource.setUsername(userName);druidDataSource.setPassword(userPass);druidDataSource.setDriverClassName(driver);druidDataSource.setMaxActive(20);//設置活躍連接上限druidDataSource.setInitialSize(20);//設置連接數}/*** 獲得連接*/protected Connection getConnection() {try {connection = druidDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}

總結

以上是生活随笔為你收集整理的五、JDBC(复习)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。