五、JDBC(复习)
目錄
一、JDBC核心組件
二、使用步驟
三、連接步驟
1.導(dǎo)包? ??
2.注冊(cè)JDBC驅(qū)動(dòng)程序:
?3.數(shù)據(jù)庫(kù)URL配置,創(chuàng)建連接對(duì)象
(1)加載驅(qū)動(dòng)
(2)獲得鏈接
(3)定義sql,創(chuàng)建狀態(tài)通道
(4)關(guān)閉資源
(5)完整代碼
四、SQl注入和預(yù)狀態(tài)通道PreparedStatement
五、多表操作
1.創(chuàng)建bean下的實(shí)體
2.創(chuàng)建接口和實(shí)現(xiàn)接口
3.在demo中打印查詢(xún)結(jié)果
4.結(jié)果
六、事務(wù)的應(yīng)用
1.自動(dòng)提交/手動(dòng)提交切換
2.事務(wù)的提交commit和回滾rollback
3.保存點(diǎn)Savepoints
七、JDBC批處理
?1.Statement批處理
2.PreparedStatement批處理
八、反射處理結(jié)果集
九、封裝工具類(lèi)
十、屬性文件
十一、連接池
1.DBCP(不可以自動(dòng)回收空閑連接)
2.C3P0(自動(dòng)回收空閑連接)
3.Druid德魯伊(阿里開(kāi)發(fā))
JDBC是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以在各種平臺(tái)上使用Java,如Windows,Mac OS和各種版本的UNIX。
一、JDBC核心組件
DriverManager: 此類(lèi)管理數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序列表。使用通信子協(xié)議將來(lái)自java應(yīng)用程序的連接請(qǐng)求 與適當(dāng)?shù)臄?shù)據(jù)庫(kù)驅(qū)動(dòng)程序匹配。
Driver:此接口處理與數(shù)據(jù)庫(kù)服務(wù)器的通信,我們很少會(huì)直接與Driver對(duì)象進(jìn)行交互。而是使用 DriverManager對(duì)象來(lái)管理這種類(lèi)型的對(duì)象。
Connection:該界面具有用于聯(lián)系數(shù)據(jù)庫(kù)的所有方法。連接對(duì)象表示通信上下文,即,與數(shù)據(jù)庫(kù) 的所有通信僅通過(guò)連接對(duì)象。
Statement:使用從此接口創(chuàng)建的對(duì)象將SQL語(yǔ)句提交到數(shù)據(jù)庫(kù)。除了執(zhí)行存儲(chǔ)過(guò)程之外,一些派 生接口還接受參數(shù)。
ResultSet:在使用Statement對(duì)象執(zhí)行SQL查詢(xún)后,這些對(duì)象保存從數(shù)據(jù)庫(kù)檢索的數(shù)據(jù)。它作為一 個(gè)迭代器,允許我們移動(dòng)其數(shù)據(jù)。
SQLException:此類(lèi)處理數(shù)據(jù)庫(kù)應(yīng)用程序中發(fā)生的任何錯(cuò)誤
二、使用步驟
構(gòu)建JDBC應(yīng)用程序涉及以下六個(gè)步驟:
- 導(dǎo)入包:需要包含包含數(shù)據(jù)庫(kù)編程所需的JDBC類(lèi)的包。大多數(shù)情況下,使用import java.sql.*就足夠 了。
- 注冊(cè)JDBC驅(qū)動(dòng)程序:要求您初始化驅(qū)動(dòng)程序,以便您可以打開(kāi)與數(shù)據(jù)庫(kù)的通信通道。
- 打開(kāi)連接:需要使用DriverManager.getConnection()方法創(chuàng)建一個(gè)Connection對(duì)象,該對(duì)象表 示與數(shù)據(jù)庫(kù)的物理連接。
- 執(zhí)行查詢(xún):需要使用類(lèi)型為Statement的對(duì)象來(lái)構(gòu)建和提交SQL語(yǔ)句到數(shù)據(jù)庫(kù)。
- 從結(jié)果集中提取數(shù)據(jù):需要使用相應(yīng)的ResultSet.getXXX()方法從結(jié)果集中檢索數(shù)據(jù)。
- 釋放資源:需要明確地關(guān)閉所有數(shù)據(jù)庫(kù)資源,而不依賴(lài)于JVM的垃圾收集。
三、連接步驟
1.導(dǎo)包? ??
import java.sql.*2.注冊(cè)JDBC驅(qū)動(dòng)程序:
? ? ? ? 工程下創(chuàng)建lib文件夾,把mysql-connector壓縮包放入lib下,點(diǎn)擊左上角文件復(fù)選框-項(xiàng)目結(jié)構(gòu),打開(kāi)此界面,點(diǎn)擊依賴(lài)
點(diǎn)擊+,單擊第一個(gè)JAR或目錄,找到剛剛的lib文件下壓縮包,點(diǎn)擊確定注入。
?
?3.數(shù)據(jù)庫(kù)URL配置,創(chuàng)建連接對(duì)象
這是為了創(chuàng)建一個(gè)格式正確的地址,指向要連接到的數(shù)據(jù)庫(kù)。
(1)加載驅(qū)動(dòng)
Class.forName("com.mysql.cj.jdbc.Driver");//從本地工程加載驅(qū)動(dòng)(2)獲得鏈接
創(chuàng)建數(shù)據(jù)庫(kù)連接對(duì)象
String userName = "root";//數(shù)據(jù)庫(kù)用戶(hù)名 String userPassword = "123456";//數(shù)據(jù)庫(kù)密碼 String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//數(shù)據(jù)庫(kù)mysql8 URL配置 Connection connection = DriverManager.getConnection(url,userName, userPassword);加載驅(qū)動(dòng)程序后,可以使用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:數(shù)據(jù)庫(kù)地址,本地就是這個(gè)?3306:數(shù)據(jù)庫(kù)所用的端口?yhp2:要打開(kāi)的數(shù)據(jù)庫(kù)名
第二種:jdbc:mysql://localhost:3306/數(shù)據(jù)庫(kù)名?useSSL=false&useUnicode=true&characterEncoding=UTF-8
(3)定義sql,創(chuàng)建狀態(tài)通道
Statement statement = connection.createStatement(); ResultSet resultSet=statement.executeQuery("select * from student;");//執(zhí)行查詢(xún)while (resultSet.next()) {System.out.println("編號(hào):"+resultSet.getInt("stuid")+"\t姓名" +resultSet.getString("name")+"\t\t生日"+resultSet.getDate("birthday")); } 執(zhí)行查詢(xún)的語(yǔ)句:返回的是一個(gè)結(jié)果集(executeQuery) resultSet=statement.executeQuery("select * from student;");執(zhí)行增刪改的語(yǔ)句,返回?cái)?shù)大于0成功,否則失敗。(executeUpdate)
int i=statement.executeUpdate("update student set birthday='1011-1-1' ");
ResultSet:
用resultset接收結(jié)果集
(4)關(guān)閉資源
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("編號(hào):" + 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注入和預(yù)狀態(tài)通道PreparedStatement
? ? ? ? 現(xiàn)在網(wǎng)站比較安全,但還是要考慮到。sql注入就是在執(zhí)行sql語(yǔ)句的時(shí)候,比如輸入密碼的時(shí)候夾帶別的對(duì)數(shù)據(jù)庫(kù)安全有威脅的sql語(yǔ)句,如密碼輸入 or 1=1;那樣條件恒等,就可以隨便進(jìn)入
預(yù)狀態(tài)通道,PreparedStatement此種方式將sql語(yǔ)句中的輸入用?代替,確保sql語(yǔ)句的本塊在傳到了數(shù)據(jù)庫(kù)執(zhí)行時(shí)帶有引號(hào)如錯(cuò)誤密碼變成了?' 123456 or 1=1',因?yàn)橛辛艘?hào)就都變成了字符串,or不會(huì)再被當(dāng)成條件執(zhí)行,之后按照從1開(kāi)始1的下標(biāo)順序以此給?賦值
此代碼塊和第三模塊第(3)定義sql,創(chuàng)建狀態(tài)通道相通,經(jīng)過(guò)更改后變成下面,換了案例,用用戶(hù)名和密碼為例子
String sql = "select * from userVIP where userName=? and userPass=?";//問(wèn)號(hào)占位 PreparedStatement preparedStatement = connection.prepareStatement(sql);//PreparedStatement接收數(shù)據(jù) preparedStatement.setString(1, "張三");//按照從1開(kāi)始的下標(biāo)順序給sql語(yǔ)句中的問(wèn)號(hào)賦值 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("編號(hào):"+resultSet.getInt("id")+"\t用戶(hù)名" +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();}}} }
五、多表操作
? ? ? ? 一對(duì)多,多對(duì)一,一對(duì)一,多對(duì)多
記錄一個(gè)多對(duì)多
一個(gè)學(xué)生可以學(xué)很多課程,一個(gè)課程也可以有很多學(xué)生在學(xué),形成多對(duì)多關(guān)系。
1.創(chuàng)建bean下的實(shí)體
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.創(chuàng)建接口和實(shí)現(xiàn)接口
接口功能是根據(jù)科目id查找誰(shuí)在學(xué)習(xí)本課程,或者根據(jù)學(xué)生id查找這個(gè)學(xué)生學(xué)習(xí)了哪些課程。
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中打印查詢(xún)結(jié)果
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.結(jié)果
ui2 張三1 李四2 王五3 趙六4 花花5 瀟瀟6 ___________________________ 張三 java ui h5 c++進(jìn)程已結(jié)束,退出代碼0六、事務(wù)的應(yīng)用
1.自動(dòng)提交/手動(dòng)提交切換
如果JDBC連接處于自動(dòng)提交模式,默認(rèn)情況下,則每個(gè)SQL語(yǔ)句在完成后都會(huì)提交到數(shù)據(jù)庫(kù)。 事務(wù)使您能夠控制是否和何時(shí)更改應(yīng)用于數(shù)據(jù)庫(kù)。它將單個(gè)SQL語(yǔ)句或一組SQL語(yǔ)句視為一個(gè)邏輯單 元,如果任何語(yǔ)句失敗,則整個(gè)事務(wù)將失敗。 要啟用手動(dòng)事務(wù)支持,而不是JDBC驅(qū)動(dòng)程序默認(rèn)使用的自動(dòng)提交模式,請(qǐng)使用Connection對(duì)象的 setAutoCommit()方法。如果將boolean false傳遞給setAutoCommit(),則關(guān)閉自動(dòng)提交。我們 可以傳遞一個(gè)布爾值true來(lái)重新打開(kāi)它。
connection.setAutoCommit(false);//關(guān)閉事務(wù)自動(dòng)提交 connection.setAutoCommit(true);2.事務(wù)的提交commit和回滾rollback
conn.commit( );//提交事務(wù) conn.rollback( );//回滾事務(wù)可以在事務(wù)寫(xiě)完之后加上conn.commit( );來(lái)提交事務(wù),在catch代碼塊報(bào)異常時(shí)寫(xiě)回滾rollback來(lái)撤銷(xiāo)此次事務(wù)的操作。
3.保存點(diǎn)Savepoints
新的JDBC 3.0 Savepoint接口為提供了額外的事務(wù)控制。 設(shè)置保存點(diǎn)時(shí),可以在事務(wù)中定義邏輯回滾點(diǎn)。如果通過(guò)保存點(diǎn)發(fā)生錯(cuò)誤,則可以使用回滾方法來(lái)撤消 所有更改或僅保存在保存點(diǎn)之后所做的更改。
Connection對(duì)象有兩種新的方法來(lái)管理保存點(diǎn)
- setSavepoint(String savepointName):定義新的保存點(diǎn)。它還返回一個(gè)Savepoint對(duì)象。
- releaseSavepoint(Savepoint savepointName):刪除保存點(diǎn)。請(qǐng)注意,它需要一個(gè)Savepoint 對(duì)象作為參數(shù)。此對(duì)象通常是由setSavepoint()方法生成的保存點(diǎn)。
上面一旦發(fā)生任何錯(cuò)誤那么sql2就會(huì)執(zhí)行失敗,但是如果sql1的語(yǔ)句是對(duì)的,那么還可以正常執(zhí)行
如過(guò)此處沒(méi)有添加事務(wù)的概念,那么即使出現(xiàn)了其它的異常,只要sql語(yǔ)句沒(méi)問(wèn)題,數(shù)據(jù)庫(kù)還是會(huì)改動(dòng)數(shù)據(jù),這樣有些需要同步執(zhí)行的數(shù)據(jù)操作就會(huì)出現(xiàn)錯(cuò)誤,如轉(zhuǎn)賬,一個(gè)加錢(qián)另一個(gè)卻沒(méi)減錢(qián)就很不合理。
七、JDBC批處理
?1.Statement批處理
????????- 使用createStatement()方法o創(chuàng)建Statement對(duì)象。
????????- 使用setAutoCommit()將auto-commit設(shè)置為false 。 (設(shè)置為手動(dòng)提交事務(wù))
????????- 使用addBatch()方法在創(chuàng)建的語(yǔ)句對(duì)象上添加您喜歡的SQL語(yǔ)句到批處理中。
????????- 在創(chuàng)建的語(yǔ)句對(duì)象上使用executeBatch()方法執(zhí)行所有SQL語(yǔ)句。
????????- 最后,使用commit()方法提交所有更改。
2.PreparedStatement批處理
String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(?, ?, ?, ?)";PreparedStatement pstmt = conn.prepareStatement(SQL);//處理sql語(yǔ)句 conn.setAutoCommit(false);//切換手動(dòng)提交事務(wù)pstmt.setInt( 1, 400 );//問(wèn)號(hào)賦值 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();//執(zhí)行所有sql語(yǔ)句conn.commit();八、反射處理結(jié)果集
????????
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.得到數(shù)據(jù)庫(kù)的查詢(xún)結(jié)果的列信息ResultSetMetaData metaData = resultSet.getMetaData();int columnCount = metaData.getColumnCount();//得到列名,返回列名數(shù)量String[] columnNames = new String[columnCount];//列名for (int i = 0; i < columnCount; i++) {columnNames[i]=metaData.getColumnName(i+1);//將結(jié)果集中的列名取出來(lái) // System.out.println(columnNames[i]);}//2.得到類(lèi)中方法Method[] declaredMethods = cla.getDeclaredMethods();//通過(guò)傳來(lái)的cla得到student方法while (resultSet.next()) {try {Object stu=cla.getDeclaredConstructor().newInstance();//創(chuàng)建對(duì)象for (String columnName : columnNames) {//遍歷結(jié)果的列名String methodName = "set"+columnName;//set組合列名for (Method declaredMethod : declaredMethods) {//遍歷方法集if (declaredMethod.getName().equalsIgnoreCase(methodName)){//如果student中某個(gè)的方法名和set加結(jié)果集列名組合的方法名一樣declaredMethod.invoke(stu,resultSet.getObject(columnName));//調(diào)用這個(gè)set方法將結(jié)果集中的數(shù)據(jù)賦值給這個(gè)studen對(duì)象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());}} }結(jié)果
1張三3 2李四1 3王五3 4趙六1 5花花1 6瀟瀟2九、封裝工具類(lèi)
通過(guò)工具類(lèi)可以極大地簡(jiǎn)化代碼
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;//統(tǒng)計(jì)增刪改操作受影響的行數(shù)String userName = "root";String userPass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//加載驅(qū)動(dòng)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;}/*** 得到預(yù)狀態(tài)通道*/protected PreparedStatement getPreparedStatement(String sql) {try {preparedStatement = getConnection().prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return preparedStatement;}/*** 綁定參數(shù)* 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);//獲得預(yù)狀態(tài)通道param(list);//補(bǔ)全sql中問(wèn)號(hào)部分count = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return count;}/*** 查詢(xún)操作*/protected ResultSet query(String sql, List list) {try {getPreparedStatement(sql);//獲得預(yù)狀態(tài)通道param(list);//補(bǔ)全sql中問(wèn)號(hào)部分resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}/*** 關(guān)閉資源*/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(繼承工具類(lèi)以直接使用工具類(lèi)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(通過(guò)學(xué)號(hào)查找人)
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());} }十、屬性文件
用來(lái)存儲(chǔ)用戶(hù)名密碼url等信息
db.properties userName=root userPass=123456 url=jdbc:mysql://localhost:3306/practice?serverTimezone=UTC driver=com.mysql.cj.jdbc.Driver?加載驅(qū)動(dòng)的兩種方法
//方法1 InputStream inputStream = 當(dāng)前類(lèi)名.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;//統(tǒng)計(jì)增刪改操作受影響的行數(shù)private static String userName;private static String userPass;private static String url;private static String driver;//加載驅(qū)動(dòng)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;}/*** 得到預(yù)狀態(tài)通道*/protected PreparedStatement getPreparedStatement(String sql) {try {preparedStatement = getConnection().prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return preparedStatement;}/*** 綁定參數(shù)* 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();}}}}/*** 更新操作* 參數(shù)含義(sql語(yǔ)句,?占位符上的值)* @return 返回受影響的行數(shù)*/protected int upData(String sql, List list) {try {getPreparedStatement(sql);//獲得預(yù)狀態(tài)通道param(list);//補(bǔ)全sql中問(wèn)號(hào)部分count = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return count;}/*** 查詢(xún)操作* 參數(shù)含義(sql語(yǔ)句,?占位符上的值)* @return 查詢(xún)數(shù)據(jù)庫(kù)返回的結(jié)果集*/protected ResultSet query(String sql, List list) {try {getPreparedStatement(sql);//獲得預(yù)狀態(tài)通道param(list);//補(bǔ)全sql中問(wèn)號(hào)部分resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}/*** 關(guān)閉資源*/protected void closeAll() {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}}十一、連接池
*連接池基本的思想是在系統(tǒng)初始化的時(shí)候,將數(shù)據(jù)庫(kù)連接作為對(duì)象存儲(chǔ)在內(nèi)存中,當(dāng)用戶(hù)需要訪問(wèn)數(shù) 據(jù)庫(kù)時(shí),并非建立一個(gè)新的連接,而是從連接池中取出一個(gè)已建立的空閑連接對(duì)象。使用完畢后,用戶(hù) 也并非將連接關(guān)閉,而是將連接放回連接池中,以供下一個(gè)請(qǐng)求訪問(wèn)使用。而連接的建立、斷開(kāi)都由連 接池自身來(lái)管理。同時(shí),還可以通過(guò)設(shè)置連接池的參數(shù)來(lái)控制連接池中的初始連接數(shù)、連接的上下限數(shù) 以及每個(gè)連接的最大使用次數(shù)、最大空閑時(shí)間等等,也可以通過(guò)其自身的管理機(jī)制來(lái)監(jiān)視數(shù)據(jù)庫(kù)連接的數(shù)量、使用情況等。
*連接池用linklist默認(rèn)初始化十個(gè)連接,其中有commit,rollback等常規(guī)方法,其中close方法在關(guān)閉資源時(shí)并不是真的關(guān)閉了資源,而是使用linklist的addlast方法將這個(gè)連接放在了連接池尾部,以待下次調(diào)用。 *最小連接數(shù) : 是數(shù)據(jù)庫(kù)一直保持的數(shù)據(jù)庫(kù)連接數(shù),所以如果應(yīng)用程序?qū)?shù)據(jù)庫(kù)連接的使用量不大,將有大量的數(shù)據(jù)庫(kù)資源被浪費(fèi)。 *初始化連接數(shù): 連接池啟動(dòng)時(shí)創(chuàng)建的初始化數(shù)據(jù)庫(kù)連接數(shù)量。 *最大連接數(shù): 是連接池能申請(qǐng)的最大連接數(shù),如果數(shù)據(jù)庫(kù)連接請(qǐng)求超過(guò)此數(shù),后面的數(shù)據(jù)庫(kù)連接請(qǐng)求被加入到等待隊(duì)列中。 *最大等待時(shí)間: 當(dāng)沒(méi)有可用連接時(shí),連接池等待連接被歸還的最大時(shí)間,超過(guò)時(shí)間則拋出異常,可設(shè)置參數(shù)為 0 或者負(fù)數(shù) 使得無(wú)限等待( 根據(jù)不同連接池配置 ) 。| DBCP | C3P0 | DRUID | |
| 最小連接數(shù) | minldle(0) | minPoolSize(3) | mindle(o) |
| 初始化連接數(shù) | initialSize(0) | initialPoolSize(3) | initialSize(0) |
| 最大連接數(shù) | maxTotal(8) | maxPoolSize(15) | maxActive(8) |
| 最大等待時(shí)間 | maxWaitMillis(毫秒) | maxldleTime(0秒) | maxWait(毫秒) |
1.DBCP(不可以自動(dòng)回收空閑連接)
先在lib文件夾下注入jia包
?將DBUtils部分的加載驅(qū)動(dòng)和獲得連接部分做修改
private static BasicDataSource basicDataSource = new BasicDataSource(); //加載驅(qū)動(dòng)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);//獲取用戶(hù)名basicDataSource.setPassword(userPass);//獲取密碼basicDataSource.setUrl(url);//獲取urlbasicDataSource.setDriverClassName(driver);//獲取驅(qū)動(dòng)位置basicDataSource.setInitialSize(10);//設(shè)置初始連接數(shù)}/*** 獲得連接*/protected Connection getConnection() {try {connection = basicDataSource.getConnection();//獲得連接} catch (SQLException e) {e.printStackTrace();}return connection;}2.C3P0(自動(dòng)回收空閑連接)
在lib下注入jar包,src目錄下創(chuàng)建c3p0-config.xml文件
C3P0通過(guò)配置文件來(lái)完成所有操作,因此將原先db.properties中的信息寫(xiě)入配置文件
<?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><!-- 等待連接的超時(shí)時(shí)間,默認(rèn)為0,代表無(wú)限等待,單位是毫秒 --><property name="checkoutTimeout">30000</property><!-- 檢查空閑連接 默認(rèn)為0 代表不檢查 --><property name="idleConnectionTestPeriod">30</property><!-- 初始化連接 --><property name="initialPoolSize">10</property><!-- 最大空閑時(shí)間,超過(guò)這個(gè)時(shí)間的連接將被丟棄,默認(rèn)為0,代表永遠(yuǎn)不關(guān)閉 --><property name="maxIdleTime">30</property><!-- 最大連接數(shù) --><property name="maxPoolSize">100</property><!-- 最小連接數(shù) --><property name="minPoolSize">10</property><!-- preparedStatement的緩存大小 --><property name="maxStatements">200</property><!--當(dāng)連接池中的連接耗盡的時(shí)候c3p0一次同時(shí)獲取的連接數(shù)。默認(rèn)值: 3 --> <property name="AcquireIncrement">5</property></default-config></c3p0-config>寫(xiě)入配置文件后不用再手動(dòng)加載驅(qū)動(dòng)?,static加載驅(qū)動(dòng)部分不用再寫(xiě)
private static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();/*** 獲得連接*/protected Connection getConnection() {try {connection = comboPooledDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}3.Druid德魯伊(阿里開(kāi)發(fā))
????????它不僅僅是一個(gè)數(shù)據(jù)庫(kù)連接池,它還包含一個(gè) ProxyDriver(代理驅(qū)動(dòng)),一系列內(nèi)置的JDBC 組件庫(kù),一個(gè) SQL Parser(sql 解析器 ) 。支持所有 JDBC 兼 容的數(shù)據(jù)庫(kù),包括Oracle 、 MySql 、 Derby 、 Postgresql 、 SQL Server 、 H2 等等。 ????????Druid針對(duì) Oracle 和 MySql 做了特別優(yōu)化,比如 Oracle 的 PS Cache 內(nèi)存占用優(yōu)化, MySql 的 ping 檢測(cè)優(yōu)化。 ????????Druid提供了 MySql 、 Oracle 、 Postgresql 、 SQL-92 的 SQL 的完整支持,這是一個(gè)手寫(xiě)的高性能 SQL Parser,支持 Visitor 模式,使得分析 SQL 的抽象語(yǔ)法樹(shù)很方便。 簡(jiǎn)單SQL 語(yǔ)句用時(shí) 10 微秒以?xún)?nèi),復(fù)雜 SQL 用時(shí) 30 微秒。 ????????通過(guò)Druid 提供的 SQL Parser 可以在 JDBC 層攔截 SQL 做相應(yīng)處理,比如說(shuō)分庫(kù)分表、審計(jì)等。 Druid 防御SQL注入攻擊的WallFilter 就是通過(guò) Druid 的 SQL Parser 分析語(yǔ)義實(shí)現(xiàn)的。 ????????Druid 是目前比較流行的高性能的,分布式列存儲(chǔ)的 OLAP 框架 ( 具體來(lái)說(shuō)是 MOLAP) 。它有如下幾個(gè)特點(diǎn) 一 . 亞秒級(jí)查詢(xún) ????????druid提供了快速的聚合能力以及亞秒級(jí)的 OLAP 查詢(xún)能力,多租戶(hù)的設(shè)計(jì),是面向用戶(hù)分析應(yīng)用的理想方式。 二 . 實(shí)時(shí)數(shù)據(jù)注入 druid 支持流數(shù)據(jù)的注入,并提供了數(shù)據(jù)的事件驅(qū)動(dòng),保證在實(shí)時(shí)和離線環(huán)境下事件的實(shí)效性和統(tǒng)一性 三 . 可擴(kuò)展的 PB 級(jí)存儲(chǔ) druid 集群可以很方便的擴(kuò)容到 PB 的數(shù)據(jù)量,每秒百 萬(wàn)級(jí)別的數(shù)據(jù)注入。即便在加大數(shù)據(jù)規(guī)模的情況下,也能保證時(shí)其效性 四 . 多環(huán)境部署 druid 既可以運(yùn)行在商業(yè)的硬件上,也可以運(yùn)行在云上。它可以從多種數(shù)據(jù)系統(tǒng)中注入數(shù)據(jù),包括 hadoop , spark , kafka , storm 和 samza 等 五 . 豐富的社區(qū) 使用方法: 在lib下注入jar包 獲得對(duì)象,手動(dòng)獲取地址,需要注意德魯伊默認(rèn)最大活躍連接數(shù)量是8因此如果要設(shè)置大于8的活躍連接數(shù)應(yīng)該先設(shè)置上限?
//Druid對(duì)象private static DruidDataSource druidDataSource = new DruidDataSource();//加載驅(qū)動(dòng)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);//設(shè)置活躍連接上限druidDataSource.setInitialSize(20);//設(shè)置連接數(shù)}/*** 獲得連接*/protected Connection getConnection() {try {connection = druidDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}總結(jié)
以上是生活随笔為你收集整理的五、JDBC(复习)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2020年中国无缝钢管行业发展现状及竞争
- 下一篇: HTC M8t unlock Bootl