五、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()方法生成的保存點。
上面一旦發生任何錯誤那么sql2就會執行失敗,但是如果sql1的語句是對的,那么還可以正常執行
如過此處沒有添加事務的概念,那么即使出現了其它的異常,只要sql語句沒問題,數據庫還是會改動數據,這樣有些需要同步執行的數據操作就會出現錯誤,如轉賬,一個加錢另一個卻沒減錢就很不合理。
七、JDBC批處理
?1.Statement批處理
????????- 使用createStatement()方法o創建Statement對象。
????????- 使用setAutoCommit()將auto-commit設置為false 。 (設置為手動提交事務)
????????- 使用addBatch()方法在創建的語句對象上添加您喜歡的SQL語句到批處理中。
????????- 在創建的語句對象上使用executeBatch()方法執行所有SQL語句。
????????- 最后,使用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 或者負數 使得無限等待( 根據不同連接池配置 ) 。| DBCP | C3P0 | DRUID | |
| 最小連接數 | 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(复习)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年中国无缝钢管行业发展现状及竞争
- 下一篇: HTC M8t unlock Bootl