1. 程式人生 > >JDBC和分包

JDBC和分包

JDBC(Java Data Base Connectivity,java資料庫連線)

JDBC是一種用於執行SQL語句的Java API,可以為多種關係資料庫提供統一訪問,它由一組用Java語言編寫的類和介面組成。是Java訪問資料庫的標準規範。

JDBC提供了一種基準,據此可以構建更高階的工具和介面,使資料庫開發人員能夠編寫資料庫應用程式。

JDBC需要連線驅動(就是實現類),由資料庫廠商提供。

 

1 JDBC原理

是面向介面程式設計

Java提供訪問資料庫規範稱為JDBC,而生產廠商提供規範的實現類稱為驅動。

 

JDBC是介面,驅動是介面的實現,沒有驅動將無法完成資料庫連線,從而不能操作資料庫。

 

2 JDBC開發步驟

1)導驅動包

專案上new一個資料夾lib(右鍵--new--Folder--輸入lib),把驅動包(下載下來的,如下圖)

 

把這個檔案複製進lib中,右鍵--build path--add to build path,可以看到專案多了一些檔案

 

每個專案這樣導一次就可以。

 

2)註冊驅動

程式碼為:Class.forName("com.mysql.jdbc.Driver");

意思是將Driver類載入到記憶體,讓其執行。

Driver類就在剛才匯入的驅動包中:

 

寫完後會有異常,因為傳引數是字串,出錯可能性大(一般按格式傳字串的,都會拋異常)。

 

這裡可以先throws,實際做專案時,再try/catch。

 

還有另一種註冊方法,但不推薦

 

 

3)獲取連線

程式碼:Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb”,”root”,”root”);

三個引數分別表示:

url 需要連線資料庫的位置(網址)

user使用者名稱  

password 密碼

 

JDBC規定url的格式由三部分組成,每個部分中間使用冒號分隔。

第一部分是jdbc,這是固定的;

第二部分是資料庫名稱,連線mysql資料庫,當然就寫mysql;

第三部分是由資料庫廠商規定的,我們需要了解每個資料庫廠商的要求。

mysql的第三部分分別由資料庫伺服器的IP地址(localhost)、埠號(3306),以及DATABASE資料庫名稱(mydb)組成。

 

這裡有可能連線不成功,所以還要thorws異常

 

 

4)獲得語句執行平臺

格式:

獲取Statement語句執行平臺:Statement sta = con.createStatement();

注意導包要導sql下的

 

 

String sql = "某SQL語句";

常用方法為:

int executeUpdate(String sql); --執行insert update delete語句,(增,刪,改都用這個)

ResultSet executeQuery(String sql); --執行select語句(查詢用這個)

 

5)處理結果集(只查詢時需要)

ResultSet實際上就是一張二維的表格,可以呼叫其boolean next()方法指向某行記錄,當第一次呼叫next()方法時,便指向第一行記錄的位置,這時就可以使用ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的資料:

rs.next();//指向第一行

rs.getInt(1);//獲取第一行第一列的資料

常用方法:

Object getObject(int index) / Object getObject(String name) 獲得任意物件

String getString(int index) / Object getObject(String name) 獲得字串

int getInt(int index) / Object getObject(String name) 獲得整形

double getDouble(int index) / Object getObject(String name) 獲得雙精度浮點型

 

也就是資料庫中的欄位是什麼型別的,就用相應的型別的方法來獲取。

 

6)釋放資源

原則是先開後關。

rs.close();

stmt.close();

con.close();

 

例:

首先建一個數據庫market0929,再建一個user表

插入一條資料

  

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class Test1 {
	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		//註冊驅動
		Class.forName("com.mysql.jdbc.Driver");
		//獲得連線物件
		String url="jdbc:mysql://127.0.0.1:3306/market0929?useUnicode=true&characterEncoding=UTF-8";
		String user="root";
		String password="123456";		
		Connection conn=DriverManager.getConnection(url, user, password);
		//獲取語句執行平臺
		Statement sta=conn.createStatement();
		
		//讓使用者輸入使用者名稱和密碼
		Scanner sc=new Scanner(System.in);
		System.out.println("請輸入使用者名稱:");
		String uname=sc.next();
		System.out.println("請輸入密碼:");
		String pwd=sc.next();		
		
		//執行sql
		String sql="select count(*) from user where uname='"+uname+"' and password='"+pwd+"'";
		
		//處理結果集
		ResultSet rs=sta.executeQuery(sql);		
		int count=0;
		while(rs.next()){
			count=rs.getInt(1);//取第一列
		} 
		System.out.println(count);
		
		//釋放 先開後關
		rs.close();
		sta.close();
		conn.close();
	}
}

 

Tips:

1)返回1,說明登入成功。

2)裡面?useUnicode=true&characterEncoding=UTF-8"; 這樣寫是為了和資料庫的字符集統一,避免新增資料時全是亂碼。

3)字串拼接技巧:先寫兩個雙引,在裡面寫兩個加號,再在加號裡面寫上變數

 

3 SQL注入問題

上面那個登入的例子,如果這樣輸入:

 

可以看到,返回了1,說明登入成功了。

 

因為這樣輸入時,實際的sql為:

SELECT COUNT(*) FROM USER WHERE uname='suiyishu' AND PASSWORD='1' OR '1=1';

  

這條查詢語句永遠可以查詢出結果,那麼使用者就直接登入成功了,這便是SQL注入問題。

 

4預處理物件

為了解決SQL注入問題,使用PreparedStatement預處理物件。

每條sql語句所有的實際引數都先用?佔位,引數使用逗號分隔,然後再給?賦值。這樣保證sql語句的結構不會再變了,不管使用者輸入什麼,都被認為是值。

 

4.1格式:

String sql = "insert into sort(sid,sname) values(?,?)";

PreparedStatement psmt = conn.prepareStatement(sql);

 

4.2設定實際引數

void setXxx(int index, Xxx xx) 將指定引數設定為給定Javaxx值。

 

4.3常用方法:

PreparedStatement是繼承Statement的,所以其方法都一樣:

增刪改用:int executeUpdate();

查詢用:ResultSet executeQuery();

 

查詢的還要處理結果集,都是一樣的。就只是執行sql時不同,以後都用PreparedStatement來寫。

 

5 JDBC工具類

“獲得資料庫連線”操作,將在以後的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連線物件的方法,從而達到程式碼的重複利用。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBCUtils {
	//工具類
	public static Connection getConn(){
		Connection conn=null; //定義成成員變數
		try {
			//註冊驅動
			Class.forName("com.mysql.jdbc.Driver");
			//獲得連線物件
			String url="jdbc:mysql://127.0.0.1:3306/market0929?useUnicode=true&characterEncoding=UTF-8";
			String user="root";
			String password="123456";		
			conn=DriverManager.getConnection(url, user, password);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return conn;
	}
	
	//釋放增刪改資源
	public static void close(Connection conn,PreparedStatement pst){		
		if(pst!=null){
			try {
				pst.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}		
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	//釋放查詢資源
	public static void close(Connection conn,PreparedStatement pst,ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(pst!=null){
			try {
				pst.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}	
}

 

6上面登入的例子修改為:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

public class Test3 {
	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		//讓使用者輸入使用者名稱和密碼
		Scanner sc=new Scanner(System.in);
		System.out.println("請輸入使用者名稱:");
		String uname=sc.next();
		System.out.println("請輸入密碼:");
		String pwd=sc.next();	
		
		//獲取連線物件
		Connection conn=JDBCUtils.getConn();		
		
		//獲取語句執行平臺
		String sql="select count(*) from user where uname=? and password=?";
		PreparedStatement pst=conn.prepareStatement(sql); //注意導sql包   是Statement子類
		
		//給問號賦值
		pst.setString(1, uname);
		pst.setString(2, pwd);
		
		//執行sql
		ResultSet rs=pst.executeQuery();
		
		//處理結果集		
		int count=0;
		while(rs.next()){
			count=rs.getInt(1);//取第一列
		} 
		System.out.println(count);
		
		//釋放資源
		JDBCUtils.close(conn,pst,rs);
	}
}

 

再輸入一下:

 

 

7專案分層(分包)

  • view層作用: 檢視層,即專案中的介面
  • controller層作用: 控制層, 獲取介面上的資料,為介面設定資料; 將要實現的功能交給業務層處理。連線前後端的類,接收前臺封裝 和頁面
  • service層作用: 業務層, 功能的實現, 與controller控制層和資料訪問層DAO互動, 將對資料庫的操作交給DAO資料訪問層來處理
  • dao層(Data Access Object))作用: 資料訪問層, 用來操作資料庫表的資料
  • db資料庫: 這裡指MySQL
  • domain 實體包: 存放JavaBean
  • tools工具包:存放專案中使用到的工具類
  • test 測試包: 存放專案功能測試的程式碼 

 

Tips:

1)用引數列表 返回值,一層調一層

2)View層:只有ScannerSystem.out.println,(及一些簡單的處理, 正則表示式,驗證使用者輸入等,相當於js)

3)Controller層:用於封裝資料

4)Service層:處理業務邏輯

5)Dao:與資料庫有關的所有。一個類對應一個表

6)一般在dao層throws異常。在Servicetry/catch 

 

例:

建一個商品分類表:sort

 

 

專案結構為:

 

 

(方便複製

test

view

tools

domain

controller

service

dao

 

實現步驟:

1)寫view,建一個run方法建立Controller層物件,在該呼叫Controller層方法的地方先加好註釋

2)建實體類,成員變數就是資料庫中的欄位名,點出get,set方法和toString方法

3)tools中放工具類

4)寫dao層

5)寫Service層,建立dao層物件呼叫dao層方法

6)寫Controller層,建立Service層物件呼叫Service層方法,如果view層傳的引數過多,可以封裝成一個物件,再向後傳

7)回到view呼叫Controller層方法

8)test層中寫main方法,呼叫view層的run方法

 

例項程式碼下載: