jdbc筆記doc

一、JDBC概述

爲什麼要使用JDBC?
JDBC:java database connectivity SUN公司提供的一套操作數據庫的標準規範。
JDBC與數據庫驅動的關係:接口與實現的關係。
在這裏插入圖片描述

JDBC規範(掌握四個核心對象):

  • DriverManager:用於註冊驅動
  • Connection: 表示與數據庫創建的連接
  • Statement: 操作數據庫sql語句的對象
  • ResultSet: 結果集或一張虛擬表

開發一個JDBC程序的準備工作:

JDBC規範在哪裏:
JDK中:
java.sql.;
javax.sql.
;
數據庫廠商提供的驅動:jar文件
*.jar

在這裏插入圖片描述

二、開發一個JDBC程序(重要)

實現查詢數據庫中的數據顯示在java的控制檯中

1 、創建數據庫表,並向表中添加測試數據

create database day06;
use day06;

create table users(
	id int primary key auto_increment,
	name varchar(40),
	password varchar(40),
	email varchar(60),
	birthday date
)character set utf8 collate utf8_general_ci;

insert into users(name,password,email,birthday) values('zs','123456','[email protected]','1980-12-04');
insert into users(name,password,email,birthday) values('lisi','123456','[email protected]','1981-12-04');
insert into users(name,password,email,birthday) values('wangwu','123456','[email protected]','1979-12-04');

2、創建java project項目,添加數據庫驅動(mysql-connector-java-5.0.8-bin.jar)

3、實現JDBC操作

	//1、註冊驅動
	//2、創建連接
	//3、得到執行sql語句的Statement對象
	//4、執行sql語句,並返回結果
	//5、處理結果
	//6關閉資源
    //註冊驅動
	DriverManager.registerDriver(new com.mysql.jdbc.Driver());
	//獲取連接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "abc");
	//得到執行sequel語句的對象Statement
	Statement stmt = conn.createStatement();
	//執行sql語句,並返回結果
	java.sql.ResultSet rs = stmt.executeQuery("select password,email,birthday,id,name from users");
	//處理結果 
	while(rs.next()){ 
		System.out.println(rs.getObject("password"));
		System.out.println(rs.getObject("id"));
		System.out.println(rs.getObject("name"));
		System.out.println(rs.getObject("birthday"));
		System.out.println(rs.getObject("email"));
		System.out.println("-----------------");
	}
	//關閉資源
	rs.close();
	stmt.close();
	conn.close();

在這裏插入圖片描述

三、JDBC常用的類和接口詳解

1、java.sql.Drivermanager類 : 創建連接

a、註冊驅動

DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建議使用

原因有2個:

  • 導致驅動被註冊2次。
  • 強烈依賴數據庫的驅動jar
    缺點:由new com.mysql.jdbc.Driver()可以知道,這裏需要創建一個類的實例。創建類的實例就需要在java文件中將該類通過import導入,否則就會報錯,即採用這種方式,程序在編譯的時候不能脫離驅動類包,爲程序切換到其他數據庫帶來麻煩。實際上這個地方還做了一次無用功,Driver類中本身已經含有靜態塊將instance放入驅動列表中。(詳細說明可以參照mysql的Driver類)
    可見,在創建Driver類的時候,其實已經調用一次registerDriver方法了
    https://wenku.baidu.com/view/a542eb0d79563c1ec4da7105.html
  • 解決辦法:
    Class.forName(“com.mysql.jdbc.Driver”);註冊一遍,在driver.class裏面

關於 forName 和 loadClass

關於forName()方法
這個方法總是返回要加載的類的Class類的實例
1、forName(String className)單參數時, initialize=true
a.總是使用當前類裝載器(也就是裝載執行forName()請求的類 的類裝載器)
b.總是初始化這個被裝載的類(當然也包括:裝載、連接、初始化)

2、forName(String className, boolean initialize, ClassLoader loader)
a.loader指定裝載參數類所用的類裝載器,如果null則用bootstrap裝載器。
b.initialize=true時,肯定連接,而且初始化了;
c.false時,絕對不會初始化,但是可能被連接了,但是這裏有個例外,如果在調用這個forName()前,已經被初始化了(當然,這裏也暗含着:className是被同一個loader所裝載的,即被參數中的loader所裝載的,而且這個類被初始化了),那麼返回的類型也肯定是被初始化的

public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);

關於用戶自定義的類裝載器的loadClass()方法
1、loadClass(String name)單參數時, resolve=false
a.如果這個類已經被這個類裝載器所裝載,那麼,返回這個已經被裝載的類型的Class的實例,否則,就用這個自定義的類裝載器來裝載這個class,這時不知道是否被連接。絕對不會被初始化
b.這時唯一可以保證的是,這個類被裝載了。但是不知道這個類是不是被連接和初始化了
2、loadClass(String name, boolean resolve)
a.resolve=true時,則保證已經裝載,而且已經連接了。resolve=falses時,則僅僅是去裝載這個類,不關心是否連接了,所以此時可能被連接了,也可能沒有被連接

另外:這裏所謂的“初始化”是指類的初始化,即執行了className字節碼的方法

再者:類是這麼加載的
1、裝載
2、連接
a)驗證–>檢查類格式等
b)準備–>給類變量分配內存,並根據類變量類型設置默認值(即內存中置0)
c)解析–>常量池解析
3、初始化
即執行Java代碼的字節碼的方法,給類變量賦予程序員需要的值

在這裏插入圖片描述

b、與數據庫建立連接

static Connection getConnection(String url, String user, String password) 
          試圖建立到給定數據庫 URL 的連接。

getConnection("jdbc:mysql://localhost:3306/day06", "root", "root");

URL:SUN公司與數據庫廠商之間的一種協議。

jdbc:mysql://localhost:3306/day06

協議 子協議 IP :端口號 數據庫

mysql: jdbc:mysql://localhost:3306/day14 或者 jdbc:mysql:///day14(默認本機連接)
oracle: jdbc:oracle:thin:@localhost:1521:sid

要參考數據庫文檔

	Properties info = new Properties();//要參考數據庫文檔
	info.setProperty("user", "root");
	info.setProperty("password","root");

getConnection(String url, Properties info) 

getConnection(String url) 
DriverManager.getConnection("jdbc:mysql://localhost:3306/day14?user=root&password=root");

2、java.sql.Connection接口:一個連接

接口的實現在數據庫驅動中。所有與數據庫交互都是基於連接對象的。

Statement  createStatement(); //創建操作sql語句的對象

3、java.sql.Statement接口: 操作sql語句,並返回相應結果的對象(小貨車)

接口的實現在數據庫驅動中。用於執行靜態 SQL 語句並返回它所生成結果的對象。

ResultSet  executeQuery(String sql) 根據查詢語句返回結果集。只能執行select語句。
int executeUpdate(String sql) 根據執行的DML(insert update delete)語句,返回受影響的行數。
boolean execute(String sql)  此方法可以執行任意sql語句。返回boolean值,表示是否返回ResultSet結果集。僅當執行select語句,且有返回結果時返回true, 其它語句都返回false;

4、java.sql.ResultSet接口: 結果集(客戶端存表數據的對象)

a、封裝結果集的。

提供一個遊標,默認遊標指向結果集第一行之前。
調用一次next(),遊標向下移動一行。
提供一些get方法。

封裝數據的方法

Object getObject(int columnIndex); 根據序號取值,索引從1開始
Object getObject(String ColomnName); 根據列名取值。

將結果集中的數據封裝到javaBean中

java的數據類型與數據庫中的類型的關係

byte          tityint
short         smallint
int           int
long          bigint
float         float
double        double
String        char varchar 
 Date         date


boolean next()	將光標從當前位置向下移動一行
int getInt(int colIndex)	以int形式獲取ResultSet結果集當前行指定列號值
int getInt(String colLabel)	以int形式獲取ResultSet結果集當前行指定列名值
float getFloat(int colIndex)	以float形式獲取ResultSet結果集當前行指定列號值
float getFloat(String colLabel)	以float形式獲取ResultSet結果集當前行指定列名值
String getString(int colIndex)	以String 形式獲取ResultSet結果集當前行指定列號值
String getString(String colLabel)	以String形式獲取ResultSet結果集當前行指定列名值
Date getDate(int columnIndex);  
Date getDate(String columnName); 返回的date類是sql中的,但一般用util包中的date接收
父類util兼容sql子類
void close()	關閉ResultSet 對象

b、可移動遊標的方法

 boolean next()  將光標從當前位置向前移一行。 
boolean previous()     將光標移動到此 ResultSet 對象的上一行。 
 boolean absolute(int row) 參數是當前行的索引,從1開始	根據行的索引定位移動的指定索引行。
 void afterLast() 將光標移動到末尾,正好位於最後一行之後。 
 void beforeFirst()   將光標移動到開頭,正好位於第一行之前。 

5、釋放資源

資源有限,要正確關閉。

		//獲取連接Connection
	Connection conn = null;
	//得到執行sql語句的對象Statement
	Statement stmt = null;
	//執行sql語句,並返回結果
	java.sql.ResultSet rs = null;
	try {
		//加載驅動
		Class.forName("com.mysql.jdbc.Driver");
		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
		stmt = conn.createStatement();
		rs = stmt.executeQuery("select id,name,password,email,birthday form users");
		//處理結果 
		while(rs.next()){ 
			System.out.println(rs.getObject(1));
			~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			System.out.println(rs.getObject(5));
			System.out.println("-----------------");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		//關閉資源
		if(rs!=null){
			try {
				rs.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			rs = null;
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			conn = null;
		}
		
	}

四、使用JDBC實現CRUD操作

第一種

TestCRUD

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;




public class TestCRUD {

@Test
public void testSelect() throws Exception{
	//加載驅動
	Class.forName("com.mysql.jdbc.Driver");
	//獲取連接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "abc");
	//得到執行sql語句的對象Statement
	Statement stmt = conn.createStatement();
	//執行sql語句,並返回結果
	ResultSet rs = stmt.executeQuery("select password,email,birthday,id,name from users");
	List<User> list = new ArrayList<User>();
	//處理結果 
	while(rs.next()){ 
		User u = new User();
		u.setId(rs.getInt("id"));
		u.setName(rs.getString("name"));
		u.setPassword(rs.getString("password"));
		u.setEmail(rs.getString("email"));
		u.setBirthday(rs.getDate("birthday"));
		list.add(u);
	}
	//關閉資源
	rs.close();
	stmt.close();
	conn.close();
	
	for (User user : list) {
		System.out.println(user);
	}
}

@Test
public void testSelect1() throws Exception{
	//加載驅動
	Class.forName("com.mysql.jdbc.Driver");
	//獲取連接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "abc");
	//得到執行sql語句的對象Statement
	Statement stmt = conn.createStatement();
	//執行sql語句,並返回結果
	ResultSet rs = stmt.executeQuery("select password,email,birthday,id,name from users");
	List<User> list = new ArrayList<User>();
	
	rs.afterLast();
	rs.previous();
	//處理結果 
	//while(rs.next()){ 
	User u = new User();
		u.setId(rs.getInt("id"));
		u.setName(rs.getString("name"));
		u.setPassword(rs.getString("password"));
		u.setEmail(rs.getString("email"));
		u.setBirthday(rs.getDate("birthday"));
		list.add(u);
	//}
	//關閉資源
	rs.close();
	stmt.close();
	conn.close();
	System.out.println(u);	
}
@Test
public void testInsert() throws Exception{
			//加載驅動
			Class.forName("com.mysql.jdbc.Driver");
			//獲取連接Connection
			Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
			//得到執行sql語句的對象Statement
			Statement stmt = conn.createStatement();
			//執行sql語句,並返回結果
			int i = stmt.executeUpdate("INSERT INTO users VALUES(4,'tom','123','[email protected]','2015-09-28')");
			if(i>0){
				System.out.println("success");
			}
			//關閉資源
			stmt.close();
			conn.close();
}

@Test
public void testUpdate() throws Exception{
	//加載驅動
	Class.forName("com.mysql.jdbc.Driver");
	//獲取連接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
	//得到執行sql語句的對象Statement
	Statement stmt = conn.createStatement();
	//執行sql語句,並返回結果
	int i = stmt.executeUpdate("UPDATE users SET NAME='jerry',PASSWORD='333',email='[email protected]' WHERE id=3");
	if(i>0){
		System.out.println("success"+" 修改了"+i+"行");
	}else{
		System.out.println("修改了"+i+"行");
	}
	
	//關閉資源
	stmt.close();
	conn.close();
	
}


@Test
public void testDelete() throws Exception{
	//加載驅動
	Class.forName("com.mysql.jdbc.Driver");
	//獲取連接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
	//得到執行sql語句的對象Statement
	Statement stmt = conn.createStatement();
	//執行sql語句,並返回結果
	int i = stmt.executeUpdate("DELETE FROM users WHERE id=4");
	if(i>0){
		System.out.println("success");
	}
	//關閉資源
	stmt.close();
	conn.close();
	
}

}

第二種 Dbutils_自己實現

Apache也有一個dbutils注意區分,其實應該叫他jdbcutils

dbinfo.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day06
username=root
password=abc

DBUtils

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

public class DBUtils {
	private static String driverClass;
	private static String url;
	private static String username;
	private static String password;

static{
	//此對象是用於加載properties文件數據的
	ResourceBundle rb = ResourceBundle.getBundle("dbinfo");
	driverClass = rb.getString("driverClass");
	url = rb.getString("url");
	username = rb.getString("username");
	password = rb.getString("password");
	try {
		Class.forName(driverClass);
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}
}

//得到連接的方法
public static Connection getConnection() throws Exception{
	return DriverManager.getConnection(url, username, password);
}

//關閉資源的方法
public static void closeAll(ResultSet rs,Statement stmt,Connection conn){
	//關閉資源
	if(rs!=null){
		try {
			rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		rs = null;
	}
	if(stmt!=null){
		try {
			stmt.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		stmt = null;
	}
	if(conn!=null){
		try {
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		conn = null;
	}
}
}

TestCRUD

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.junit.Test;

import com.itheima.entity.User;
import com.itheima.util.DBUtils;

public class TestCRUD {
	@Test
	public void testSelect(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
	
	try {
		conn = DBUtils.getConnection();
		stmt = conn.createStatement();
		rs = stmt.executeQuery("select * from users");
		List<User> list = new ArrayList<User>();
		while(rs.next()){
			User u = new User();
			u.setId(rs.getInt(1));
			u.setName(rs.getString(2));
			u.setPassword(rs.getString(3));
			u.setEmail(rs.getString(4));
			u.setBirthday(rs.getDate(5));
			list.add(u);
		}
		
		for (User user : list) {
			System.out.println(user);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(rs, stmt, conn);
	}
}

@Test
public void testInsert(){
	Connection conn = null;
	PreparedStatement stmt = null;

	try {
		conn = DBUtils.getConnection();
		stmt = conn.prepareStatement("INSERT INTO users VALUES(?,?,?,?,?)");
		stmt.setInt(1, 5);
		stmt.setString(2, "tom");
		stmt.setString(3, "333");
		stmt.setString(4, "[email protected]");
		//stmt.setDate(5, new java.sql.Date(System.currentTimeMillis()));
		stmt.setString(5, "2015-09-11");
		
		int i = stmt.executeUpdate();
		if(i>0){
			System.out.println("success");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(null, stmt, conn);
	}
}

@Test
public void testUpdate(){
	Connection conn = null;
	PreparedStatement stmt = null;

	try {
		conn = DBUtils.getConnection();
		stmt = conn.prepareStatement("UPDATE users SET NAME=?,PASSWORD=?,email=? WHERE id=?");
		stmt.setString(1, "jerry123");
		stmt.setString(2, "123");
		stmt.setString(3, "[email protected]");
		stmt.setInt(4, 5);
		
		int i = stmt.executeUpdate();
		if(i>0){
			System.out.println("success");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(null, stmt, conn);
	}
}

@Test
public void testDelete(){
	Connection conn = null;
	Statement stmt = null;

	try {
		conn = DBUtils.getConnection();
		stmt = conn.createStatement();
		int i = stmt.executeUpdate("DELETE FROM users WHERE id=4");
		if(i>0){
			System.out.println("success");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(null, stmt, conn);
	}
}

}

五、實現一個用戶登錄的功能

在這裏插入圖片描述

六、SQL注入問題:preparedStatement

preparedStatement:預編譯對象, 是Statement對象的子類。
特點:
性能要高
會把sql語句先編譯
sql語句中的參數會發生變化,過濾掉用戶輸入的關鍵字。

補充例子:

在這裏插入圖片描述

七、分頁理論

轉自 傳播智客

什麼是分頁及其作用

分頁就是將數據以多頁展示出來,使用分頁的目的是爲了提高用戶的感受

分頁分類

物理分頁

只從數據庫中查詢出要顯示的數據
優點:不佔用很多內存
缺點:速度比較低,每一次都要從數據庫中獲取

邏輯分頁

從數據庫中將所有記錄查找到,存儲到內存中,需要什麼數據
直接從內存中獲取.
優點:速度比較快
缺點:佔用比較多的內存,如果數據比較多,可以出現內在溢出。
數據實時更新需要單獨處理.

mysql中limit介紹

利用mysql的limit,進行物理分頁。

select * from 表名  limit m,n;
m是從0開始,代表是第幾條記錄   
n代表顯示多少條記錄

例如

select * from person limit 4,10;
從第五條記錄開始,顯示10條.

分頁實現原理分析

1.知道一共有多少條記錄

select count(*) from 表;

2.知道每一頁顯示多少條記錄
人爲定義的.
3.一共有多少頁
1.總頁數=總條數%每頁條數==0?總條數/每頁條數:總條數/每頁條數+1
2.總頁數=Math.ceil(總條數*1.0/每頁條數);
4.當前頁碼
默認值爲1,代表第一頁.
當點擊上一頁,下一頁,就是對頁碼進行+1 -1操作.
5.需要當前頁的數據
例如:每頁顯示五條,要查詢第三頁數據

	select * from 表 limit(3-1)*5,5;
    用(當前頁碼-1)*每頁條數,就求出了開始的記錄位置,在向下查找每頁數個     記錄。就得到了這頁的數據.

(currentPage-1)*pageSize

八、數據庫連接池

1、連接池原理:(面試)

應用程序直接獲取鏈接的缺點
在這裏插入圖片描述

數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重複使用一個現有的數據庫連接,而不是再重新建立一個;
釋放空閒時間超過最大空閒時間的數據庫連接來避免因爲沒有釋放數據庫連接而引起的數據庫連接遺漏。這
項技術能明顯提高對數據庫操作的性能

在這裏插入圖片描述
目的:解決建立數據庫連接耗費資源和時間很多的問題,提高性能。

2、編寫標準的數據源

//模擬數據庫連接池,但不具備實際開發意義,這裏用到的dbutils是我們自己開發的一個工具類,代碼在上邊
在這裏插入圖片描述
在這裏插入圖片描述

自定義數據庫連接池要實現javax.sql.DataSource接口,一般都叫數據源。

在這裏插入圖片描述

3、編寫數據源時遇到的問題及解決辦法

在這裏插入圖片描述

a、裝飾設計模式:使用頻率很高

目的:改寫已存在的類的某個方法或某些方法,裝飾設計模式(包裝模式)
口訣:
1、編寫一個類,實現與被包裝類相同的接口。(具備相同的行爲)
2、定義一個被包裝類類型的變量。
3、定義構造方法,把被包裝類的對象注入,給被包裝類變量賦值。
4、對於不需要改寫的方法,調用原有的方法。
5、對於需要改寫的方法,寫自己的代碼。

在這裏插入圖片描述
在這裏插入圖片描述

b、默認適配器:裝飾設計模式一個變體

(a實現了一個接口,實現接口所定義的方法,
然後b繼承a,只需要重寫我們需要的方法,)

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
代碼看起來更加簡潔

3、常用的數據源配置(日後都使用數據源,一定要配置一下)

3.1、DBCP

Properties類文件不支持中文
DBCP:Apache推出的Database Connection Pool
使用步驟:

  • 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
  • 添加屬性資源文件
  • 編寫數據源工具類

在這裏插入圖片描述
在這裏插入圖片描述

3.2、C3P0

使用步驟:
1、添加jar包
2、編寫配置文件
c3p0-config.xml,放在classpath中,或classes目錄中
在這裏插入圖片描述
3、編寫工具類:
在這裏插入圖片描述

九、完成全選/全不選

1、添加checkall的單擊事件
2、調用執行方法checkAll()
//得到ckall全選框
//得到所有ck的複選框
//根據ckall複選框的選中狀態給所有ck賦值

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章