1. 程式人生 > >javaweb:JDBC連線MYSQL資料庫詳解,使用JDBC對資料庫進行CRUD操作以及DAO模式的介紹

javaweb:JDBC連線MYSQL資料庫詳解,使用JDBC對資料庫進行CRUD操作以及DAO模式的介紹

 

JDBC簡介:

JDBC全稱為:Java DataBase Connectivity(java資料庫連線)。

SUN公司為了簡化、統一對資料庫的操作,定義了一套Java操作資料庫的規範,稱之為JDBC。

組成JDBC的2個包:

連結:https://pan.baidu.com/s/1ePw4wDxcsZu9x-3MZHu8FQ 
提取碼:0g1z 

java.sql

javax.sql

開發JDBC應用需要以上2個包的支援外

還需要匯入相應JDBC的資料庫實現(即資料庫驅動

第一個JDBC程式:

程式設計從user表中讀取資料,並列印在命令列視窗中。

  一、搭建實驗環境 :

  1、在mysql中建立一個庫,並建立user表和插入表的資料。

  2、新建一個Java工程,並匯入資料驅動。

二、編寫程式,在程式中載入資料庫驅動

  DriverManager. registerDriver(Driver driver)

三、建立連線(Connection)

  Connection conn = DriverManager.getConnection(url,user,pass);

四、建立用於向資料庫傳送SQL的Statement物件,併發送sql

  Statement st = conn.createStatement();

  ResultSet rs = st.executeQuery(sql);

五、從代表結果集的ResultSet中取出資料,列印到命令列視窗

六、斷開與資料庫的連線,並釋放相關資源

package cn.itcast.jdbctest;

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

import org.junit.Test;

/**
 * JDBC的快速入門
 * @author Administrator
 *
 */
public class JdbcDemo1 {
	
	@Test
	public void run2(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			// 現在這麼做
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
			// 編寫SQL語句了
			String sql = "select * from t_user";
			// 建立能執行SQL語句的Statement物件
			stmt = conn.createStatement();
			// 執行SQL語句
			rs = stmt.executeQuery(sql);
			// 迴圈變數rs
			while(rs.next()){
				// 拿出來
				int id = rs.getInt("id");
				String username = rs.getString("username");
				String password = rs.getString("password");
				System.out.println(id+" "+username+" "+password);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				rs = null;
			}
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
		
	}
	
	
	@Test
	public void run1() throws SQLException, ClassNotFoundException{
		/**
		 * 1.完成驅動的註冊
		 * 2.獲取連結
		 * 3.執行SQL語句
		 * 4.釋放資源
		 */
		// 註冊驅動
		// DriverManager.registerDriver(new Driver());
		
		// 現在這麼做
		Class.forName("com.mysql.jdbc.Driver");
		
		// 獲取連結
		// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day17", "root", "root");
		
		Connection conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
		
		// 編寫SQL語句了
		String sql = "select * from t_user";
		// 建立能執行SQL語句的Statement物件
		Statement stmt = conn.createStatement();
		// 執行SQL語句
		ResultSet rs = stmt.executeQuery(sql);
		// 迴圈變數rs
		while(rs.next()){
			// 拿出來
			int id = rs.getInt("id");
			String username = rs.getString("username");
			String password = rs.getString("password");
			System.out.println(id+" "+username+" "+password);
		}
		rs.close();
		stmt.close();
		conn.close();
	}
}


JDBC程式設計步驟:

裝載驅動程式

建立連線

操作資料

釋放資源

程式詳解—DriverManager:

DriverManager類的是管理一組 JDBC 驅動程式的基本服務。作用有兩個,如下:

註冊驅動

static void registerDriver(Driver driver)方法進行註冊驅動

但是這種方式不是很好,原因如下:

讓應用程式依賴具體的驅動包,如果是切換資料庫還需要修改原始碼才能完成。

呼叫該方法導致驅動被註冊兩次,通過檢視驅動的原始碼能發現次問題。

所以在實際開發中不會這麼做?具體做法如下:

Class.forName("com.mysql.jdbc.Driver");

獲取連結物件

資料庫URL:

URL用於標識資料庫的位置,程式設計師通過URL地址告訴JDBC程式連線哪個資料庫,URL的寫法為:

   jdbc:    mysql: //       localhost:3306/test ?     key=value

 

l常用資料庫URL地址的寫法:

Oracle寫法:jdbc:oracle:thin:@localhost:1521:sid

MySql—jdbc:mysql://localhost:3306/sid

Mysql的url地址的簡寫形式: jdbc:mysql:///sid

常用屬性:useUnicode=true&characterEncoding=UTF-8

程式詳解—Connection:

Jdbc程式中的Connection,它用於代表資料庫的連結,Collection是資料庫程式設計中最重要的一個物件,客戶端與資料庫所有互動都是通過connection物件完成的,

有兩個作用:

建立執行SQL語句的物件

createStatement():建立向資料庫傳送sql的statement物件

prepareStatement(sql) :建立向資料庫傳送預編譯sql的PreparedSatement物件

prepareCall(sql):建立執行儲存過程的CallableStatement物件。

管理事物

setAutoCommit(boolean autoCommit):設定事務是否自動提交。

commit() :在連結上提交事務。 ---與事務相關!!

rollback() :在此連結上回滾事務。

程式詳解—Statement  -- 一次操作:

Jdbc程式中的Statement物件用於向資料庫傳送SQL語句, Statement物件常用方法:

執行SQL語句

executeQuery(String sql) :用於向資料傳送查詢語句。

executeUpdate(String sql):用於向資料庫傳送insert、update或delete語句

execute(String sql):用於向資料庫傳送任意sql語句

執行批處理

addBatch(String sql) :把多條sql語句放到一個批處理中。

executeBatch():向資料庫傳送一批sql語句執行。

程式詳解—ResultSet:

Jdbc程式中的ResultSet用於代表Sql語句的執行結果。Resultset封裝執行結果時,採用的類似於表格的方式。ResultSet 物件維護了一個指向表格資料行的遊標cursor,初始的時候,遊標在第一行之前,呼叫ResultSet.next() 方法,可以使遊標指向具體的資料行,進而呼叫方法獲取該行的資料。

ResultSet既然用於封裝執行結果的,所以該物件提供的大部分方法都是用於獲取資料的get方法:

獲取任意型別的資料

getObject(int index)

getObject(string columnName)

獲取指定型別的資料,例如:

getString(int index)

getString(String columnName)

常用資料型別轉換表:

遍歷查詢結果:

 程式詳解—釋放資源:
Jdbc程式執行完後,切記要釋放程式在執行過程中,建立的那些與資料庫進行互動的物件,這些物件通常是ResultSet, Statement和Connection物件。

特別是Connection物件,它是非常稀有的資源,用完後必須馬上釋放,如果Connection不能及時、正確的關閉,極易導致系統宕機。Connection的使用原則是儘量晚建立,儘量早的釋放。

為確保資源釋放程式碼能執行,資源釋放程式碼也一定要放在finally語句中。

使用JDBC對資料庫進行CRUD:

Jdbc中的statement物件用於向資料庫傳送SQL語句,想完成對資料庫的增刪改查,只需要通過這個物件向資料庫傳送增刪改查語句即可。

 

Statement物件的executeUpdate方法,用於向資料庫傳送增、刪、改的sql語句,executeUpdate執行完後,將會返回一個整數(即增刪改語句導致了資料庫幾行資料發生了變化)。

 

Statement.executeQuery方法用於向資料庫傳送查詢語句,executeQuery方法返回代表查詢結果的ResultSet物件。

CRUD操作-create:

使用executeUpdate(String sql)方法完成資料新增操作,示例操作:

Statement st = conn.createStatement();

	String sql = "insert into user(….) values(…..) "; 

	int num = st.executeUpdate(sql);

	if(num>0){
		System.out.println("插入成功!!!");
	}

 CRUD操作-updata:

使用executeUpdate(String sql)方法完成資料修改操作,示例操作:

Statement st = conn.createStatement();

	String sql = “update user set name=‘’ where name=‘’"; 

	int num = st.executeUpdate(sql);

	if(num>0){
		System.out.println(“修改成功!!!");
	}

 CRUD操作-delete:

使用executeUpdate(String sql)方法完成資料刪除操作,示例操作:

Statement st = conn.createStatement();

	String sql = “delete from user where id=1; 

	int num = st.executeUpdate(sql);

	if(num>0){
		System.out.println(“刪除成功!!!");
	}

 CRUD操作-Retrieve/Read:
使用executeQuery(String sql)方法完成資料查詢操作,示例操作:

Statement st = conn.createStatement();

	String sql = “select * from user where id=1; 

	ResultSet rs = st.executeQuery(sql);

	while(rs.next()){
		//根據獲取列的資料型別,分別呼叫rs的相應方法
		//對映到java物件中
	}

增刪改查例項: 

package cn.itcast.jdbctest;

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

import org.junit.Test;

import cn.itcast.utils.MyJdbcUtil;

/**
 * 完成t_user表的增刪改查
 * @author Administrator
 *
 */
public class JdbcDemo3 {
	
	@Test
	public void testSelect(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			// 載入驅動,現在不用了,直接獲取連結物件
            // MyJdbcUtil封裝工具類,下文有詳細解析,在裡面封裝了固定的模組,簡化程式碼
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user";
			// 建立執行
			stmt = conn.createStatement();
			// 執行
			rs = stmt.executeQuery(sql);
			// 迴圈遍歷
			while(rs.next()){
				System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
	}
	
	/**
	 * 測試新增的功能
	 */
	@Test
	public void testInsert(){
		Connection conn = null;
		Statement stmt = null;
		try {
			// 註冊驅動
			Class.forName("com.mysql.jdbc.Driver");
			// 獲取連結
			conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
			// 編寫SQL語句
			String sql = "insert into t_user values (null,'小鳳','111')";
			// 能執行該SQL語句的物件
			stmt = conn.createStatement();
			// 執行
			int index = stmt.executeUpdate(sql);
			if(index > 0){
				System.out.println("新增資料成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
	
	
	/**
	 * 測試修改的功能
	 */
	@Test
	public void testUpdate(){
		Connection conn = null;
		Statement stmt = null;
		try {
			// 註冊驅動
			Class.forName("com.mysql.jdbc.Driver");
			// 獲取連結
			conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
			// 編寫SQL語句
			String sql = "update t_user set username = '如花',password='555' where id = 5 ";
			// 能執行該SQL語句的物件
			stmt = conn.createStatement();
			// 執行
			int index = stmt.executeUpdate(sql);
			if(index > 0){
				System.out.println("修改資料成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
	
	
	/**
	 * 測試刪除的功能
	 */
	@Test
	public void testDelete(){
		Connection conn = null;
		Statement stmt = null;
		try {
			// 註冊驅動
			Class.forName("com.mysql.jdbc.Driver");
			// 獲取連結
			conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
			// 編寫SQL語句
			String sql = "delete from t_user where id = 5";
			// 能執行該SQL語句的物件
			stmt = conn.createStatement();
			// 執行
			int index = stmt.executeUpdate(sql);
			if(index > 0){
				System.out.println("刪除資料成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}

}

 

 JDBC工具類的封裝和CURD:

使用JDBC完成資料的CURD操作具有很多重複性的程式碼,像驅動載入、獲取連結、釋放資源等,所以可以封裝成工具類方便使用。

封裝工具類:

package cn.itcast.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 操作JDBC
 * @author Administrator
 */
public class MyJdbcUtil {
	
	public static final String DRIVERCLASS;
	public static final String URL;
	public static final String USERNAME;
	public static final String PASSWORD;
	
	// 想給常量賦值
	static{
		// 解析db.properties檔案
		// Properties工具類,載入檔案
		Properties pro = new Properties();
		// 獲取輸入流
		InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
		try {
			pro.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 通過Properties獲取內容
		DRIVERCLASS = pro.getProperty("driverClass");
		URL = pro.getProperty("url");
		USERNAME = pro.getProperty("username");
		PASSWORD = pro.getProperty("password");
	}
	
	/**
	 * 載入驅動
	 */
	public static void loadDriver(){
		try {
			Class.forName(DRIVERCLASS);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 獲取連結
	 * @return
	 */
	public static Connection getConnection(){
		// 載入驅動
		loadDriver();
		// 獲取連結物件
		try {
			return DriverManager.getConnection(URL, USERNAME, PASSWORD);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 釋放資源
	 * @param rs
	 * @param stmt
	 * @param conn
	 */
	public static void release(ResultSet rs,Statement stmt,Connection conn){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
	
	/**
	 * 釋放資源的方法
	 * @param stmt
	 * @param conn
	 */
	public static void release(Statement stmt,Connection conn){
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
	
}

db.properties配置資料庫檔案(這個檔案是在src的根目錄下建立的):

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day17
username=root
password=root

 

JavaEE模式-DAO 模式:

SUN公司在早期的JAVAEE體系分成了三層經典結構:WEB層 (Servlet/JSP業務層(JavaBean持久層(JDBC

早期採用Servlet+JSP+JavaBean+JDBC架構完成開發

現在採用框架來完成開發(ssh框架)Struts2 + Spring + Hibernate

DAO模式就是持久層的一種解決方案,封裝對於資料來源及其資料的單個操作,需要提供一組介面,供業務層訪問,業務呼叫DAO的程式碼時候需要傳遞一個物件。

資料來源可能是檔案、資料庫等任意儲存方式

負責管理與資料來源的連線

負責資料的存取(CRUD)

DAO模式的類圖:

DAO 模式中的物件:

Business Object

代表資料的使用者

DataAccessObject

抽象並封裝了對底層資料來源的操作

DataSource

資料來源

TransferObject

表示資料的Java Bean

例項(java三層架構模式)—使用者登陸:

原始碼已上傳到github:https://github.com/LazyTraveller/standard-login

1.搭建環境

2.匯入jar包(MySQL驅動包,JSTL包)

架構:

LoginServlet.java:

package cn.itcast.action;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import cn.itcast.service.UserService;
import cn.itcast.vo.User;

public class LoginServlet extends HttpServlet {

	private static final long serialVersionUID = -5933952794357976456L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		/**
		 * 接收資料
		 * 封裝資料
		 * 處理資料
		 * 顯示結果
		 */
		// 設定編碼
		request.setCharacterEncoding("UTF-8");
		// 接收資料
		Map<String, String []> map = request.getParameterMap();
		User user = new User();
		try {
			// 封裝資料
			BeanUtils.populate(user, map);
			// 呼叫業務層的程式碼
			UserService us = new UserService();
			// 判斷是否登陸
			User existUser = us.loginUser(user);
			// 判斷是否為null
			if(existUser == null){
				// 說明失敗
				// 向域中存值
				request.setAttribute("msg", "使用者名稱或者密碼錯誤");
				// 使用轉發
				request.getRequestDispatcher("/pages/login.jsp").forward(request, response);
			}else{
				// 把使用者的資訊儲存到session中
				request.getSession().setAttribute("existUser", existUser);
				// 重定向到頁面
				response.sendRedirect(request.getContextPath()+"/pages/success.jsp");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

 

UserDao.java:   這是一個介面

package cn.itcast.dao;

import java.util.List;

import cn.itcast.vo.User;

public interface UserDao {
	
	public User findUser(User user);
	
	public User findUserByPrepared(User user);
	
	// 新增資料
	public void insert(User user);
	// 修改資料
	public void update(User user);
	// 刪除資料
	public void delete(User user);
	// 通過主鍵來查詢單個使用者
	public User findUserById(int id);
	// 查詢所有使用者
	public List<User> findUsers();
	
}

防止SQL注入漏洞:

1.前臺校驗

2.後臺校驗(prepareStatement)

UserDaolmple.java:  這是UserDao的實現類

package cn.itcast.dao;

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

import org.junit.Test;

import cn.itcast.utils.MyJdbcUtil;
import cn.itcast.vo.User;

public class UserDaoImple implements UserDao {
	
	/**
	 * 防止SQL注入
	 */
	public User findUserByPrepared(User user) {
		// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			// 先獲取連結物件
			conn = MyJdbcUtil.getConnection();
			// 編寫的SQL語句不同
			String sql = "select * from t_user where username = ? and password = ? ";
			// 預編譯(已經把SQL傳送給伺服器進行預編譯,格式就固定了)
			stmt = conn.prepareStatement(sql);
			// 設定引數的值
			stmt.setString(1, user.getUsername());  // bbb ' or ' 1 = 1不認識or關鍵字
			stmt.setString(2, user.getPassword());
			// 執行SQL(不帶SQL語句的)
			rs = stmt.executeQuery();
			// 如果有
			if(rs.next()){
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
		
	}
	

	/**
	 * 完成登陸的操作
	 */
	public User findUser(User user) {
		// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			// 先獲取連結物件
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user where username = '"+user.getUsername()+"' and password= '"+user.getPassword()+"' ";
			// 執行SQL
			stmt = conn.createStatement();
			// 執行SQL語句,如果有會查詢出一條記錄
			rs = stmt.executeQuery(sql);
			// 如果有
			if(rs.next()){
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
	}
	
	
	/**
	 * 完成新增的功能
	 */
	public void insert(User user) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "insert into t_user values (null,?,?)";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setString(1, user.getUsername());
			stmt.setString(2, user.getPassword());
			// 執行SQL
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(stmt, conn);
		}
	}

	/**
	 * 修改使用者的資料
	 */
	public void update(User user) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "update t_user set username = ? , password = ? where id = ?";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setString(1, user.getUsername());
			stmt.setString(2, user.getPassword());
			stmt.setInt(3, user.getId());
			// 執行SQL
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(stmt, conn);
		}
	}


	/**
	 * 刪除使用者的記錄
	 */
	public void delete(User user) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "delete from t_user where id = ?";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setInt(1, user.getId());
			// 執行SQL
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(stmt, conn);
		}
	}

	/**
	 * 通過使用者的主鍵來獲取使用者的詳細資訊
	 */
	public User findUserById(int id) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user where id = ?";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setInt(1, id);
			// 執行SQL
			rs = stmt.executeQuery();
			// 一條記錄
			if(rs.next()){
				User u = new User();
				u.setId(id);
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
	}

	/**
	 * 獲取所有的使用者資訊
	 */
	public List<User> findUsers() {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		List<User> list = new ArrayList<User>();
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 執行SQL
			rs = stmt.executeQuery();
			// 一條記錄
			while(rs.next()){
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				list.add(u);
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
	}
	
	
	@Test
	public void run(){
		User u = new User(6,"eee","333");
		// insert(u);
		// update(u);
		// delete(u);
		//User u2 = findUserById(2);
		//System.out.println(u2);
		List<User> list = findUsers();
		for (User user : list) {
			System.out.println(user);
		}
	}

}













package cn.itcast.dao;

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

import org.junit.Test;

import cn.itcast.utils.MyJdbcUtil;
import cn.itcast.vo.User;

public class UserDaoImple implements UserDao {
	
	/**
	 * 防止SQL注入
	 */
	public User findUserByPrepared(User user) {
		// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			// 先獲取連結物件
			conn = MyJdbcUtil.getConnection();
			// 編寫的SQL語句不同
			String sql = "select * from t_user where username = ? and password = ? ";
			// 預編譯(已經把SQL傳送給伺服器進行預編譯,格式就固定了)
			stmt = conn.prepareStatement(sql);
			// 設定引數的值
			stmt.setString(1, user.getUsername());  // bbb ' or ' 1 = 1不認識or關鍵字
			stmt.setString(2, user.getPassword());
			// 執行SQL(不帶SQL語句的)
			rs = stmt.executeQuery();
			// 如果有
			if(rs.next()){
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
		
	}
	

	/**
	 * 完成登陸的操作
	 */
	public User findUser(User user) {
		// 完成登陸的功能(通過使用者名稱和密碼查詢資料庫)
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			// 先獲取連結物件
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user where username = '"+user.getUsername()+"' and password= '"+user.getPassword()+"' ";
			// 執行SQL
			stmt = conn.createStatement();
			// 執行SQL語句,如果有會查詢出一條記錄
			rs = stmt.executeQuery(sql);
			// 如果有
			if(rs.next()){
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
	}
	
	
	/**
	 * 完成新增的功能
	 */
	public void insert(User user) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "insert into t_user values (null,?,?)";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setString(1, user.getUsername());
			stmt.setString(2, user.getPassword());
			// 執行SQL
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(stmt, conn);
		}
	}

	/**
	 * 修改使用者的資料
	 */
	public void update(User user) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "update t_user set username = ? , password = ? where id = ?";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setString(1, user.getUsername());
			stmt.setString(2, user.getPassword());
			stmt.setInt(3, user.getId());
			// 執行SQL
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(stmt, conn);
		}
	}


	/**
	 * 刪除使用者的記錄
	 */
	public void delete(User user) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "delete from t_user where id = ?";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setInt(1, user.getId());
			// 執行SQL
			stmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(stmt, conn);
		}
	}

	/**
	 * 通過使用者的主鍵來獲取使用者的詳細資訊
	 */
	public User findUserById(int id) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user where id = ?";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 設定引數
			stmt.setInt(1, id);
			// 執行SQL
			rs = stmt.executeQuery();
			// 一條記錄
			if(rs.next()){
				User u = new User();
				u.setId(id);
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
	}

	/**
	 * 獲取所有的使用者資訊
	 */
	public List<User> findUsers() {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		List<User> list = new ArrayList<User>();
		try {
			// 獲取連結
			conn = MyJdbcUtil.getConnection();
			// 編寫SQL語句
			String sql = "select * from t_user";
			// 預編譯SQL
			stmt = conn.prepareStatement(sql);
			// 執行SQL
			rs = stmt.executeQuery();
			// 一條記錄
			while(rs.next()){
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setUsername(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				list.add(u);
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 釋放資源
			MyJdbcUtil.release(rs, stmt, conn);
		}
		return null;
	}
	
	
	@Test
	public void run(){
		User u = new User(6,"eee","333");
		// insert(u);
		// update(u);
		// delete(u);
		//User u2 = findUserById(2);
		//System.out.println(u2);
		List<User> list = findUsers();
		for (User user : list) {
			System.out.println(user);
		}
	}

}

 

UserService.java:

package cn.itcast.service;

import cn.itcast.dao.UserDao;
import cn.itcast.dao.UserDaoImple;
import cn.itcast.vo.User;

/**
 * 使用者相關的業務類
 * @author Administrator
 *
 */
public class UserService {

	/**
	 * 使用者是否可以登陸
	 * @param user
	 * @return
	 */
	public User loginUser(User user){
		UserDao dao = new UserDaoImple();
		// 防止SQL注入
		return dao.findUserByPrepared(user);
	}
	
}

MyjdbcUtil.java:

package cn.itcast.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 操作JDBC
 * @author Administrator
 */
public class MyJdbcUtil {
	
	public static final String DRIVERCLASS;
	public static final String URL;
	public static final String USERNAME;
	public static final String PASSWORD;
	
	// 想給常量賦值
	static{
		// 解析db.properties檔案
		// Properties工具類,載入檔案
		Properties pro = new Properties();
		// 獲取輸入流
		InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
		try {
			pro.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 通過Properties獲取內容
		DRIVERCLASS = pro.getProperty("driverClass");
		URL = pro.getProperty("url");
		USERNAME = pro.getProperty("username");
		PASSWORD = pro.getProperty("password");
	}
	
	/**
	 * 載入驅動
	 */
	public static void loadDriver(){
		try {
			Class.forName(DRIVERCLASS);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 獲取連結
	 * @return
	 */
	public static Connection getConnection(){
		// 載入驅動
		loadDriver();
		// 獲取連結物件
		try {
			return DriverManager.getConnection(URL, USERNAME, PASSWORD);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 釋放資源
	 * @param rs
	 * @param stmt
	 * @param conn
	 */
	public static void release(ResultSet rs,Statement stmt,Connection conn){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
	
	/**
	 * 釋放資源的方法
	 * @param stmt
	 * @param conn
	 */
	public static void release(Statement stmt,Connection conn){
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
	
}


User.java:

package cn.itcast.vo;

public class User {
	
	private int id;
	private String username;
	private String password;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public User(int id, String username, String password) {
		super();
		this.id = id;
		this.username = username;
		this.password = password;
	}
	
	public User(String username, String password) {
		this.username = username;
		this.password = password;
	}
	
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password="
				+ password + "]";
	}
	
}

login.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<h3>使用者登陸</h3>
<font color="red">${ msg }</font>
<form action="${ pageContext.request.contextPath }/login" method="post">
	使用者名稱:<input type="text" name="username" /><br/>
	密碼:<input type="password" name="password" /><br/>
	<input type="submit" value="登陸">
</form>

</body>
</html>

success.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>歡迎頁面</h3>
<c:if test="${ empty existUser }">
	<h3>親,您還沒有登陸,請您<a href="${ pageContext.request.contextPath }/pages/login.jsp">登陸</a></h3>
</c:if>

<c:if test="${ not empty existUser }">
	<h3>親,歡迎您:${ existUser.username }</h3>
</c:if>


</body>
</html>

 

使用JDBC處理大資料:

在實際開發中,程式需要把大文字 Text 或二進位制資料 Blob儲存到資料庫。

Text是mysql叫法,Oracle中叫Clob

基本概念:大資料也稱之為LOB(Large Objects),LOB又分為:

clob和blob

clob用於儲存大文字。Text

blob用於儲存二進位制資料,例如影象、聲音、二進位制文等。

對MySQL而言只有blob,而沒有clob,mysql儲存大文字採用的是Text,Text和blob分別又分為:

TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)

TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

使用JDBC處理大文字:

l對於MySQL中的Text型別,可呼叫如下方法設定:

PreparedStatement.setCharacterStream(index, reader, length);

//注意length長度須設定,並且設定為int型

//當包過大時修改配置:[mysqld] max_allowed_packet=64M

l對MySQL中的Text型別,可呼叫如下方法獲取:

reader = resultSet. getCharacterStream(i);

等價於

reader = resultSet.getClob(i).getCharacterStream();

使用JDBC處理二進位制資料:

對於MySQL中的BLOB型別,可呼叫如下方法設定:

PreparedStatement. setBinaryStream(i, inputStream, length);

對MySQL中的BLOB型別,可呼叫如下方法獲取:

InputStream in  = resultSet.getBinaryStream(i);

InputStream in  = resultSet.getBlob(i).getBinaryStream();

使用JDBC進行批處理:

業務場景:當需要向資料庫傳送一批SQL語句執行時,應避免向資料庫一條條的傳送執行,而應採用JDBC的批處理機制,以提升執行效率。

實現批處理有兩種方式,第一種方式:

Statement.addBatch(sql)

執行批處理SQL語句

executeBatch()方法:執行批處理命令

clearBatch()方法:清除批處理命令

使用JDBC進行批處理:

Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
String sql1 = "insert into person(name,password,email,birthday) 
	values('kkk','123','[email protected]','1978-08-08')";
String sql2 = "update user set password='123456' where id=3";
st = conn.createStatement();
st.addBatch(sql1);  //把SQL語句加入到批命令中
st.addBatch(sql2);  //把SQL語句加入到批命令中
st.executeBatch();
} finally{
	JdbcUtil.free(conn, st, rs);
}
採用Statement.addBatch(sql)方式實現批處理:
優點:可以向資料庫傳送多條不同的SQL語句。
缺點:
SQL語句沒有預編譯。
當向資料庫傳送多條語句相同,但僅引數不同的SQL語句時,需重複寫上很多條SQL語句。例如:
		Insert into user(name,password) values(‘aa’,’111’);
		Insert into user(name,password) values(‘bb’,’222’);
		Insert into user(name,password) values(‘cc’,’333’);
		Insert into user(name,password) values(‘dd’,’444’);

實現批處理的第二種方式:

PreparedStatement.addBatch()

conn = JdbcUtil.getConnection();
String sql = "insert into person(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql);
for(int i=0;i<50000;i++){
st.setString(1, "aaa" + i);
st.setString(2, "123" + i);
st.setString(3, "aaa" + i + "@sina.com");
st.setDate(4,new Date(1980, 10, 10));

st.addBatch(); 
if(i%1000==0){
st.executeBatch();
st.clearBatch();
}
}
st.executeBatch();

採用PreparedStatement.addBatch()實現批處理

優點:傳送的是預編譯後的SQL語句,執行效率高。

缺點:只能應用在SQL語句相同,但引數不同的批處理中。因此此種形式的批處理經常用於在同一個表中批量插入資料,或批量更新表的資料。