這篇文章帶給大家的內容是詳解什麼是JDBC? JDBC是如何使用的? 。有一定的參考價值,有需要的朋友可以參考一下,希望對你們有幫助。
什麼是JDBC
JDBC(Java Database Connectivity),即Java資料庫連接,是一種用於執行SQL語句的Java API ,可以為多種關係資料庫提供相同訪問,它由一組用Java語言編寫的類別和介面組成。 JDBC提供了一種基準,根據這種基準可以建立更高級的工具和接口,使資料庫開發人員能夠編寫資料庫應用程式。總而言之,JDBC做了三件事:
#與資料庫建立連線
傳送操作資料庫的語句
處理結果
JDBC簡單範例
下面的程式碼示範如何利用JDBC從資料庫查詢若干條符合要求的資料出來,使用的資料庫是MySql。
1、建立一個資料庫和一張表,我的習慣是在CLASSPATH底下建立一個.sql的檔案用來存放sql語句
create database school; use school; create table student ( studentId int primary key auto_increment not null, studentName varchar(10) not null, studentAge int, studentPhone varchar(15) ) insert into student values(null,'Betty', '20', '00000000'); insert into student values(null,'Jerry', '18', '11111111'); insert into student values(null,'Betty', '21', '22222222'); insert into student values(null,'Steve', '27', '33333333'); insert into student values(null,'James', '22', '44444444'); commit;
2、建立一個.properties檔用於儲存MySql連接的幾個屬性。為什麼要建立.properties而不在程式碼裡面寫死,由於這個不是Java設計模式的分類,就不細講了,只需要記住:從設計的角度看,把內容寫在配置文件中永遠好過把內容寫死在程式碼中。
mysqlpackage=com.mysql.jdbc.Driver mysqlurl=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8 mysqlname=root mysqlpassword=root
3、根據表格欄位建立實體類別
public class Student { private int studentId; private String studentName; private int studentAge; private String studentPhone; public Student(int studentId, String studentName, int studentAge, String studentPhone) { this.studentId = studentId; this.studentName = studentName; this.studentAge = studentAge; this.studentPhone = studentPhone; } public int getStudentId() { return studentId; } public String getStudentName() { return studentName; } public int getStudentAge() { return studentAge; } public String getStudentPhone() { return studentPhone; } public String toString() { return "studentId = " + studentId + ", studentName = " + studentName + ", studentAge = " + studentAge + ", studentPhone = " + studentPhone; } }
4、寫一個DBConnection類別專門用來向外提供資料庫連線。我這裡用了MySql,所以只有一個mysqlConnection,如果還用到了Oracle,當然還可以向外提供一個oracleConnection。把這些連線設為全域的可能有人會想是否會有線程安全問題,這是一個很好的問題。那因為我們只從Connection裡面讀取一個PreparedStatement出來,而不會去寫它,只讀不修改,是不會引發線程安全問題的。另外把Connection設定為static的保證了Connection在記憶體中只有一份,不會佔多大資源,每次使用完不呼叫close()方法去關閉它也沒事。
public class DBConnection { private static Properties properties = new Properties(); static { /** 要从CLASSPATH下取.properties文件,因此要加"/" */ InputStream is = DBConnection.class.getResourceAsStream("/db.properties"); try { properties.load(is); } catch (IOException e) { e.printStackTrace(); } } /** 这个mysqlConnection只是为了用来从里面读一个PreparedStatement,不会往里面写数据,因此没有线程安全问题,可以作为一个全局变量 */ public static Connection mysqlConnection = getConnection(); public static Connection getConnection() { Connection con = null; try { Class.forName((String)properties.getProperty("mysqlpackage")); con = DriverManager.getConnection((String)properties.getProperty("mysqlurl"), (String)properties.getProperty("mysqlname"), (String)properties.getProperty("mysqlpassword")); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return con; } }
5、建立一個工具類,用來寫各種方法,專門和資料庫進行互動。這種工具類別最好搞成單例的,這樣就不用每次去new出來了(實際上new出來也沒看出來會有什麼好處),節省資源
package com.xrq.test11; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class StudentManager { private static StudentManager instance = new StudentManager(); private StudentManager() { } public static StudentManager getInstance() { return instance; } public List<Student> querySomeStudents(String studentName) throws Exception { List<Student> studentList = new ArrayList<Student>(); Connection connection = DBConnection.mysqlConnection; PreparedStatement ps = connection.prepareStatement("select * from student where studentName = ?"); ps.setString(1, studentName); ResultSet rs = ps.executeQuery(); Student student = null; while (rs.next()) { student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4)); studentList.add(student); } ps.close(); rs.close(); return studentList; } }
6、寫個main函數去呼叫一下
List<Student> studentList = StudentManager.getInstance().querySomeStudents("Betty"); for (Student student : studentList) { System.out.println(student); }
7、看一下運行結果,和資料庫裡面的一樣,成功
studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000 studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222
為什麼要用佔位符"?"
看第5點,大家一定注意到了,寫sql語句的時候用了"?"佔位符,當然有美化代碼的因素,不用佔位符就要在括號裡寫" "來拼接參數,如果要拼接的參數一多,程式碼一定不好看,可讀性不強。但除了這個原因,還有另一個重要的原因,就是避免一個安全問題。假設我們不用佔位符寫sql語句,那"querySomeStudents(String name) throws Exception"方法就要這麼寫:
public List<Student> querySomeStudents(String studentName) throws Exception { List<Student> studentList = new ArrayList<Student>(); Connection connection = DBConnection.mysqlConnection; PreparedStatement ps = connection.prepareStatement("select * from student where studentName = '" + studentName + "'"); ResultSet rs = ps.executeQuery(); Student student = null; while (rs.next()) { student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4)); studentList.add(student); } ps.close(); rs.close(); return studentList; }
上面的main函數一樣可以取得到兩個數據,但是問題來了,如果我這麼呼叫呢:
public static void main(String[] args) throws Exception { List<Student> studentList = new ArrayList<Student>(); studentList = StudentManager.getInstance().querySomeStudents("' or '1' = '1"); for (Student student : studentList) System.out.println(student); }
看下運行結果:
studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000 studentId = 2, studentName = Jerry, studentAge = 18, studentPhone = 11111111 studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222 studentId = 4, studentName = Steve, studentAge = 27, studentPhone = 33333333 studentId = 5, studentName = James, studentAge = 22, studentPhone = 44444444
為什麼?看下拼接之後的sql語句就知道了:
select * from student where studentName = '' or '1' = '1'
'1'='1'永遠成立,所以前面的查詢條件是什麼都沒用。這種問題是有應用場景的,不是隨便寫一下。 Java越來越多的用在Web上,既然是Web,那麼查詢的時候有一種情況就是用戶輸入一個條件,後台獲取到查詢條件,拼接sql語句查數據庫,有經驗的用戶完全可以輸入一個"' '' or '1' = '1",這樣就拿到了庫裡面的所有資料了。
Statement 和PreparedStatement之間的關係和區別.
關係:PreparedStatement繼承自Statement,都是介面
區別:PreparedStatement可以使用佔位符,是預先編譯的,批次比Statement效率高
JDBC交易
#什麼是交易:交易就是操作一組資料庫的操作集合。如果一組處理步驟或全部發生或一步也不執行,我們稱改組處理為一個事務。
交易的基本特性:原子性,一致性,隔離性,持久性。
原子性: 原子性是指交易是不可再分割的工作單元,事務中的操作要麼都發生,要麼都不發生。
一致性:一致性是指在交易開始之前和交易結束以後,資料庫的完整性約束沒有被破壞。這是說資料庫事務不能破壞關係資料的完整性以及業務邏輯上的一致性。
如A給B轉賬,不論轉帳的事務操作是否成功,其兩者的存款總額不變。
隔離性:多個交易並發存取時,交易之間是隔離的,而一個交易不應該影響其它交易運作效果。
在並發環境中,當不同的交易同時操縱相同的資料時,每個交易都有各自的完整資料空間。由並發事務所所做的修改必須與任何其他並發事務所所做的修改隔離。當交易檢視資料更新時,資料所處的狀態要麼是另一筆交易修改它之前的狀態,要麼是另一交易修改它之後的狀態,交易不會檢視到中間狀態的資料。
事務最複雜的問題都是由事務隔離性所造成。完全的隔離性是不切實際的,完全的隔離性要求資料庫在同一時間只執行一條事務,這樣會嚴重影響效能。
持久性:意味著在事務完成以後,該事務所對資料庫所做的更改便持久的保存在資料庫之中,並不會被回滾。
總結:以上就是這篇文章的全部內容,希望能對大家的學習有所幫助。更多相關教學請造訪Java影片教學,java開發圖文教學,bootstrap影片教學!
以上是詳解什麼是JDBC? JDBC是如何使用的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!