JDBC技術詳解
JDBC基礎
1.JDBC介紹
JDBC是java訪問[物件型資料庫/關係型資料庫]資料庫的規則,是原SUN公司開發的.
原來我們程式設計師需要針對具體的資料庫操作,費時費力;
自從有了JDBC規則後,程式設計師只需要針對JDBC規則程式設計,不用管底層具體資料庫的實現,
好處在於:寫一份JDBC程式碼,可以在很多資料庫在執行,即可移植性
2.驅動的原理及使用
就是JDBC規則,在具體資料庫中的實現類,且用java書寫(需要安裝JDK)
3.JDBC核心使用
做jdbc程式碼,需要用到如下幾個固定步驟,以查詢為例:
- 1_註冊mysql資料庫伺服器的驅動,DriverManager
- 2_獲取mysql資料庫伺服器的連線,Connection
- 3_獲取封裝sql語句的物件,Statement
- 4_執行sql語句,並返回結果集合,ResultSet
- 5_迭代這個結果集合,while(){}
- 6_按輕到重的原則關閉連線物件,ResultSet-Statement-Connection,在必要情況下,Connection可重用
4.DriverManager(類)、Connection(介面)、Statement(介面)、ResultSet(介面)詳細使用
-
DriverManager:
它是一個類,由原SUN公司提供,負責管理一個或一組訪問具體資料庫的驅動,
即你想訪問Oracle資料庫伺服器的話,就讓DriverManager載入Oracle驅動,
只需註冊一次就行 -
Connection:
是原SUN公司提供的介面,是屬於重量級物件,建議少建立,要重用
只要你想與資料庫進行操作,必須獲取連線物件jdbc:mysql://127.0.0.1:3306/mydb1","root","123" jdbc:主協議,你只要使用jdbc技術訪問資料庫,都是jdbc主協議 mysql:子協議 127.0.0.1:MySQL資料庫伺服器所在PC的IP地址或域名,建議用IP 3306:MySQL資料庫伺服器所在的PC的埠號 mydb1:訪問資料庫伺服器中哪一個具體的資料庫 root:使用者名稱 123:密碼,如果沒有密碼的話,也需要寫""空字串
-
Statement:
負責封裝SQL語句並執行的物件,是原SUN公司提供的介面SQL語句在JDBC中分為二大類 1_靜態SQL:SQL語句中無?符號,即select id,name from users where name = '張三'(上) 2_動態SQL:SQL語句中有?符號,即select id,name from users where name = ? ?號由程式在執行時動態設定的值
Statement常用的API:
-
查詢:executeQuery(引數為靜態SQL),返回值為ResultSet
增刪改:executeUpdate(引數為靜態SQL),返回值為Int,表示影響表格行數 -
ResultSet:
負責裝查詢語句的結果,預設情況下,遊標位於第一條記錄的前邊。
next()方法就能向下移動一行,如果有結果,返回true
5.jdbc的crud
- 增刪改:Statment.executeUpdate(),返回值為int,表示這次操作影響了表中的幾條記錄
- 查詢:Statment.executeQuery(),返回值為ResultSet,表示這次查詢操作結果記錄數形成的集合
6.sql注入
- 客戶端利用jdbc-Statement的缺點,傳入非法引數,從而讓jdbc返回不合法的值,我們利用這種情況,通稱為sql注入.
-
現在專案中不直接使用Statement,使用PreparedStatement,PreparedStatement它除了具有Statement是所有功能外,還有動態sql處理能力,包括:程式執行時動態為?符設定值,安全檢查,避免sql注入問題,預處理能力
-
?表示佔位符,只能出現在欄位值的位置,不能替代表名,不能替代列名;
?表示的欄位值,不管是什麼型別,都不用加”符號 -
Statement和PreparedStatement的區別:
Statement只能處理靜態SQL;
PreparedStatement既能處理靜態sql也能處理動態sql,它繼承了Statement的特點 -
站在預處理角度:
PreparedStatement適合做連續多次結構相同的sql語句,有優勢.
Statement適合做連續多次不同結構的sql語句,有優勢. -
專案中,我們都用子介面,
1_支援動態sql,也支援靜態sql
2_預處理---相同結構的sql select id,name,from users where id=1; select id,name,gender from users where id=2; 是不相同結構 ---不同結構的sql
宣告:
-
靜態sql也可以用PreparedStatement
適合:
靜態sql—優先Statement;
動態sql—優先PreparedStatement
Statement程式碼實現:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC開發
*/
public class Demo {
static{
//1)註冊一個MySQL資料庫驅動,因為你現在要訪問的是MySQL資料庫伺服器,用反射
//好處:只向DriverManager註冊一次MySQL驅動
//好處:無需匯入MySQL具體的類名
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 查詢所有使用者
*/
public void findAllUser() throws Exception{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//NO2)獲取JavaApp與MySQL資料庫伺服器的連線
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb1","root","123");
//NO3)建立封裝SQL語句的物件
stmt = conn.createStatement();
//NO4)執行SQL語句,返回結果集合,裡面存放裝SQL語句執行結果,即是四條記錄
rs = stmt.executeQuery("select id,username,gender,hiredate from users");
//NO5)迭代結果集合,在預設情況下,遊標指向第一條記錄之前,通過next方法將遊標下移一條,如果有記錄存在,返回true;否則false
while(rs.next()){
//獲取一條中id列名對應的值
int id = rs.getInt("id");
String username = rs.getString("username");
String gender = rs.getString("gender");
//在與JDBC訪問時,MySQL中的date,對應java中的java.sql.Date
java.sql.Date hiredate = rs.getDate("hiredate");
System.out.println(id+"#"+username+"#"+gender+"#"+hiredate);
}
} catch (SQLException e) {
e.printStackTrace();
//通知呼叫者,給前臺使用者提示,html/jsp
throw e;
} finally{
//NO6)關閉上述用過的連線物件
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//GC回收
rs = null;
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//GC回收
stmt = null;
}
}
//後期重用Connection
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//GC回收
conn = null;
}
}
}
}
/**
* 主方法
*/
public static void main(String[] args) throws Exception{
Demo dao = new Demo();
dao.findAllUser();
}
}
PreparedStatement完成對users表的CURD操作,程式碼實現:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import cn.itheima.entity.User;
import cn.itheima.utils.JdbcUtils;
/**
* 演示PreparedStatement完成對users表的CURD操作
*/
public class Demo01 {
/**
* 增加使用者
*/
public void add(User user){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "insert into users(username,gender,hiredate) values(?,?,?)";
try{
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,user.getUsername());
pstmt.setString(2,user.getGender());
pstmt.setDate(3,new java.sql.Date(user.getHiredate().getTime()));
int i = pstmt.executeUpdate();
System.out.println(i>0?"成功":"失敗");
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException("增加使用者失敗");
}finally{
JdbcUtils.close(rs);
JdbcUtils.close(pstmt);
JdbcUtils.close(conn);
}
}
/**
* 修改使用者
*/
public void update(String oldUsername,String newUsername){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "update users set username = ? where username = ?";
try{
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,newUsername);
pstmt.setString(2,oldUsername);
int i = pstmt.executeUpdate();
System.out.println(i>0?"成功":"失敗");
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException("增加使用者失敗");
}finally{
JdbcUtils.close(rs);
JdbcUtils.close(pstmt);
JdbcUtils.close(conn);
}
}
/**
* 查詢使用者
* @param lastname 在這裡表示姓
* @param gender 性別
*/
public void find(String lastname,String gender){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//String sql = "select * from users where username like '趙%' and gender = '男'";
String sql = "select id,username,gender,hiredate from users where username like ? and gender = ?";
try{
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,lastname+"%");
pstmt.setString(2,gender);
rs = pstmt.executeQuery();
while(rs.next()){
int id = rs.getInt("id");
String username = rs.getString("username");
gender = rs.getString("gender");
java.sql.Date hiredate = rs.getDate("hiredate");
System.out.println(id+"#"+username+"#"+gender+"#"+hiredate);
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException("查詢使用者 失敗");
}finally{
JdbcUtils.close(rs);
JdbcUtils.close(pstmt);
JdbcUtils.close(conn);
}
}
/**
* 批量刪除使用者
*/
public void delete(int... ids){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
StringBuffer sb = new StringBuffer("delete from users where id in (");
for(int id : ids){
sb.append(id+",");
}
//刪除最後一個逗號
sb.deleteCharAt(sb.length()-1);
//在最後拼接)
sb.append(")");
String sql = sb.toString();
try{
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
int i = pstmt.executeUpdate();
System.out.println(i>0?"成功":"失敗");
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException("批量刪除使用者失敗");
}finally{
JdbcUtils.close(rs);
JdbcUtils.close(pstmt);
JdbcUtils.close(conn);
}
}
public static void main(String[] args) {
Demo01 test = new Demo01();
User user = new User();
user.setUsername("張三");
user.setGender("男");
user.setHiredate(new java.util.Date());
//test.add(user);
//test.update("張三","李四");
//test.find("趙","男");
test.delete(1,6,7);
}
}
摘自:https://blog.csdn.net/shuaicihai/article/details/53416045?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160965081316780263098257%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=160965081316780263098257&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-2-53416045.pc_search_result_cache&utm_term=JDBC%E6%8A%80%E6%9C%AF