一、預(yù)編譯sql處理(防止sql注入)
--創(chuàng)建數(shù)據(jù)庫(kù)
CREATEDATABASE jdbc_demo DEFAULT CHARACTER SET utf8;i
--創(chuàng)建表
USEjdbc_demo;
CREATETABLE admin(
id INT PRIMARY KEY AUTO_INCREMENT,
userName VARCHAR(20),
pwd VARCHAR(20)
)
|--Statement 執(zhí)行SQL命令
|-- CallableStatement, 執(zhí)行存儲(chǔ)過程
|--PreparedStatement 預(yù)編譯SQL語句執(zhí)行
使用預(yù)編譯SQL語句的命令對(duì)象,好處:
1. 避免了頻繁sql拼接 (可以使用占位符)
2. 可以防止sql注入
登陸模塊,
輸入用戶名,密碼!
注意,
要避免用戶輸入的惡意密碼!
package com.xp.jdbc.pstmt;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;public class PstmtLogin { // 連接參數(shù) // private String url = "jdbc:MySQL://localhost:3306/jdbc_demo"; private String url = "jdbc:mysql:///jdbc_demo"; private String user = "root"; private String passWord = "root"; private Connection con; private Statement stmt; private PreparedStatement pstmt; private ResultSet rs; // 1. 沒有使用防止sql注入的案例 @Test public void testLogin() { // 1.0 模擬登陸的用戶名,密碼 String userName = "tom"; // String pwd = "8881"; String pwd = " ' or 1=1 -- "; // SQL語句 String sql = "select * from admin where userName='" + userName + "' and pwd='" + pwd + "' "; System.out.println(sql); try { // 1.1 加載驅(qū)動(dòng),創(chuàng)建連接 Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection(url, user, password); // 1.2 創(chuàng)建stmt對(duì)象 stmt = con.createStatement(); // 1.3 執(zhí)行查詢 rs = stmt.executeQuery(sql); // 業(yè)務(wù)判斷 if (rs.next()) { System.out.println("登陸成功, 編號(hào):" + rs.getInt("id")); } } catch (Exception e) { e.printStackTrace(); } finally { // 1.4 關(guān)閉 try { rs.close(); stmt.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } } // 2. 使用PreparedStatement, 防止sql注入 @Test public void testLogin2() { // 1.0 模擬登陸的用戶名,密碼 String userName = "tom"; // String pwd = "8881"; String pwd = " ' or 1=1 -- "; // SQL語句 String sql = "select * from admin where userName=? and pwd=? "; try { // 1.1 加載驅(qū)動(dòng),創(chuàng)建連接 Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection(url, user, password); // 1.2 創(chuàng)建pstmt對(duì)象 pstmt = con.prepareStatement(sql); // 對(duì)sql語句預(yù)編譯 // 設(shè)置占位符值 pstmt.setString(1, userName); pstmt.setString(2, pwd); // 1.3 執(zhí)行 rs = pstmt.executeQuery(); if (rs.next()) { System.out.println("登陸成功," + rs.getInt("id")); } } catch (Exception e) { e.printStackTrace(); } finally { // 1.4 關(guān)閉 try { rs.close(); pstmt.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } }}二、 存儲(chǔ)過程調(diào)用-- 存儲(chǔ)過程DELIMITER $$CREATE PROCEDURE proc_login()BEGIN SELECT * FROM admin;END $$-- 調(diào)用CALL proc_login;package com.xp.jdbc.utils;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcUtil { // 連接參數(shù) // private String url = "jdbc:mysql://localhost:3306/jdbc_demo"; private static String url = "jdbc:mysql:///jdbc_demo"; private static String user = "root"; private static String password = "xiongpan"; /** * 返回連接對(duì)象 */ public static Connection getConnection() { try { Class.forName("com.mysql.jdbc.Driver"); return DriverManager.getConnection(url, user, password); } catch (Exception e) { throw new RuntimeException(e); } } /** * 關(guān)閉 */ public static void closeAll(Connection con, Statement stmt, ResultSet rs) { try { if (rs != null) { rs.close(); // 快速異常捕獲 Alt + shift + z rs = null; // 建議垃圾回收期回收資源 } if (stmt != null) { stmt.close(); stmt = null; } if (con != null && !con.isClosed()) { con.close(); con = null; } } catch (SQLException e) { throw new RuntimeException(e); } } }package com.xp.jdbc.pstmt;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;import com.xp.jdbc.utils.JdbcUtil;public class PstmtLogin_call { // 全局參數(shù) private Connection con; private Statement stmt; private PreparedStatement pstmt; private CallableStatement cstmt; // 存儲(chǔ)過程 private ResultSet rs; // 程序中調(diào)用存儲(chǔ)過程 @Test public void testCall() throws Exception { try { // 1 . 創(chuàng)建連接 con = JdbcUtil.getConnection(); // 2. 創(chuàng)建執(zhí)行存儲(chǔ)過程的stmt對(duì)象 CallableStatement cstmt = con.prepareCall("CALL proc_login"); // 3. 執(zhí)行(存儲(chǔ)過程) rs = cstmt.executeQuery(); // 遍歷結(jié)果,測(cè)試 if (rs.next()) { String name = rs.getString("userName"); String pwd = rs.getString("pwd"); // 測(cè)試 System.out.println(name + pwd); } } catch (Exception e) { e.printStackTrace(); } }}一、 批處理
很多時(shí)候,需要批量執(zhí)行sql語句!
需求:批量保存信息!
設(shè)計(jì):
AdminDao
Public void save(List<Admin list){ // 目前用這種方式
// 循環(huán)
// 保存 (批量保存)
}
Public void save(Admin admin ){
// 循環(huán)
// 保存
}
技術(shù):
|-- Statement
批處理相關(guān)方法
voidaddBatch(String sql) 添加批處理
voidclearBatch() 清空批處理
int[] executeBatch() 執(zhí)行批處理
實(shí)現(xiàn):
Admin.java 實(shí)體類封裝數(shù)據(jù)
AdminDao.java 封裝所有的與數(shù)據(jù)庫(kù)的操作
App.java 測(cè)試
package com.xp.batch;public class Admin { private String userName; private String pwd; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }package com.xp.batch;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.List;import com.xp.jdbc.utils.JdbcUtil;public class AdminDao { // 全局參數(shù) private Connection con; private PreparedStatement pstmt; private ResultSet rs; // 批量保存管理員 public void save(List<Admin> list) { // SQL String sql = "INSERT INTO admin(userName,pwd) values(?,?)"; try { // 獲取連接 con = JdbcUtil.getConnection(); // 創(chuàng)建stmt pstmt = con.prepareStatement(sql); // 【預(yù)編譯SQL語句】 for (int i = 0; i < list.size(); i++) { Admin admin = list.get(i); // 設(shè)置參數(shù) pstmt.setString(1, admin.getUserName()); pstmt.setString(2, admin.getPwd()); // 添加批處理 pstmt.addBatch(); // 【不需要傳入SQL】 // 測(cè)試:每5條執(zhí)行一次批處理 if (i % 5 == 0) { // 批量執(zhí)行 pstmt.executeBatch(); // 清空批處理 pstmt.clearBatch(); } } // 批量執(zhí)行 pstmt.executeBatch(); // 清空批處理 pstmt.clearBatch(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, rs); } }}package com.xp.batch;import java.util.ArrayList;import java.util.List;import org.junit.Test;public class App { // 測(cè)試批處理操作 @Test public void testBatch() throws Exception { // 模擬數(shù)據(jù) List<Admin> list = new ArrayList<Admin>(); for (int i = 1; i < 21; i++) { Admin admin = new Admin(); admin.setUserName("Jack" + i); admin.setPwd("888" + i); list.add(admin); } // 保存 AdminDao dao = new AdminDao(); dao.save(list); }}四、 插入數(shù)據(jù),獲取自增長(zhǎng)值 需求: 李俊杰 18張相 19如何設(shè)計(jì)數(shù)據(jù)庫(kù)?編號(hào) 員工姓名 年齡 部門01 李俊杰 18 開發(fā)部02 張三 19 開發(fā)部’思考:如何減少數(shù)據(jù)冗余? 設(shè)置外鍵約束所以,編號(hào) 員工姓名 年齡 部門01 李俊杰 18 102 張三 19 1部門編號(hào) 部門名稱 1 開發(fā)部 部門與員工,一對(duì)多的關(guān)系 設(shè)計(jì)數(shù)據(jù)庫(kù):?jiǎn)T工表 (外鍵表) 【員工表有一個(gè)外鍵字段,引用了部門表的主鍵】部門表(主鍵表) 編碼總體思路:保存員工及其對(duì)應(yīng)的部門!步驟:1. 先保存部門2. 再得到部門主鍵,再保存員工開發(fā)具體步驟:1. 設(shè)計(jì)javabean2. 設(shè)計(jì)dao3. 測(cè)試-- 部門CREATE TABLE dept( deptId INT PRIMARY KEY AUTO_INCREMENT, deptName VARCHAR(20));-- 員工CREATE TABLE employee( empId INT PRIMARY KEY AUTO_INCREMENT, empName VARCHAR(20), dept_id INT -- 外鍵字段 );-- 給員工表添加外鍵約束ALTER TABLE employee ADD CONSTRAINT FK_employee_dept_deptId FOREIGN KEY(dept_id) REFERENCES dept(deptId) ;package com.xp.auto;public class Employee { private int empId; private String empName; // 關(guān)聯(lián)的部門 private Dept dept; public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public int getEmpId() { return empId; } public void setEmpId(int empId) { this.empId = empId; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; }}package com.xp.auto;public class Dept { private int id; private String deptName; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } }package com.xp.auto;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;import com.xp.jdbc.utils.JdbcUtil;public class EmpDao { private Connection con; private PreparedStatement pstmt; private ResultSet rs; // 保存員工,同時(shí)保存關(guān)聯(lián)的部門 public void save(Employee emp){ // 保存部門 String sql_dept = "insert into dept(deptName) values(?)"; // 保存員工 String sql_emp = "INSERT INTO employee (empName,dept_id) VALUES (?,?)"; // 部門id int deptId = 0; try { // 連接 con = JdbcUtil.getConnection(); /*****保存部門,獲取自增長(zhǎng)*******/ // 【一、需要指定返回自增長(zhǎng)標(biāo)記】 pstmt = con.prepareStatement(sql_dept,Statement.RETURN_GENERATED_KEYS); // 設(shè)置參數(shù) pstmt.setString(1, emp.getDept().getDeptName()); // 執(zhí)行 pstmt.executeUpdate(); // 【二、獲取上面保存的部門子增長(zhǎng)的主鍵】 rs = pstmt.getGeneratedKeys(); // 得到返回的自增長(zhǎng)字段 if (rs.next()) { deptId = rs.getInt(1); } /*****保存員工*********/ pstmt = con.prepareStatement(sql_emp); // 設(shè)置參數(shù) pstmt.setString(1, emp.getEmpName()); pstmt.setInt(2, deptId); pstmt.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, rs); } }}package com.xp.auto;import org.junit.Test;public class App { // 保存員工 @Test public void testSave() throws Exception { // 模擬數(shù)據(jù) Dept d = new Dept(); d.setDeptName("應(yīng)用開發(fā)部"); Employee emp = new Employee(); emp.setEmpName("李俊杰"); emp.setDept(d); // 關(guān)聯(lián) // 調(diào)用dao保存 EmpDao empDao = new EmpDao(); empDao.save(emp); }}五、事務(wù)
事務(wù)使指一組最小邏輯操作單元,里面有多個(gè)操作組成。組成事務(wù)的每一部分必須要同時(shí)提交成功,如果有一個(gè)操作失敗,整個(gè)操作就回滾。
事務(wù)ACID特性
原子性(Atomicity)
原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
一致性(Consistency)
事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變換到另外一個(gè)一致性狀態(tài)。
隔離性(Isolation)
事務(wù)的隔離性是多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫(kù)時(shí),數(shù)據(jù)庫(kù)為每一個(gè)用戶開啟的事務(wù),不能被其他事務(wù)的操作數(shù)據(jù)所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。
持久性(Durability)
持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響
事務(wù)的特性:
原子性,是一個(gè)最小邏輯操作單元 !
一致性,事務(wù)過程中,數(shù)據(jù)處于一致狀態(tài)。
持久性, 事務(wù)一旦提交成功,對(duì)數(shù)據(jù)的更改會(huì)反映到數(shù)據(jù)庫(kù)中。
隔離性, 事務(wù)與事務(wù)之間是隔離的。
案例:
需求: 張三給李四轉(zhuǎn)賬
設(shè)計(jì): 賬戶表
技術(shù):
|--Connection
voidsetAutoCommit(boolean autoCommit) ; 設(shè)置事務(wù)是否自動(dòng)提交如果設(shè)置為false,表示手動(dòng)提交事務(wù)。
voidcommit() (); 手動(dòng)提交事務(wù)
voidrollback() ; 回滾(出現(xiàn)異常時(shí)候,所有已經(jīng)執(zhí)行成功的代碼需要回退到事務(wù)開始前的狀態(tài)。)
SavepointsetSavepoint(String name)
-- 賬戶表CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, accountName VARCHAR(20), money DOUBLE);-- 轉(zhuǎn)賬UPDATE account SET money=money-1000 WHERE accountName='張三';UPDATE account SET money=money+1000 WHERE accountName='李四';package com.xp.account;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import java.sql.Savepoint;import com.xp.jdbc.utils.JdbcUtil;public class AccountDao { // 全局參數(shù) private Connection con; private PreparedStatement pstmt; // 1. 轉(zhuǎn)賬,沒有使用事務(wù) public void trans1() { String sql_zs = "UPDATE account SET money=money-1000 WHERE accountName='張三';"; String sql_ls = "UPDATE account SET money=money+1000 WHERE accountName='李四';"; try { con = JdbcUtil.getConnection(); // 默認(rèn)開啟的隱士事務(wù) con.setAutoCommit(true); /*** 第一次執(zhí)行SQL ***/ pstmt = con.prepareStatement(sql_zs); pstmt.executeUpdate(); /*** 第二次執(zhí)行SQL ***/ pstmt = con.prepareStatement(sql_ls); pstmt.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, null); } } // 2. 轉(zhuǎn)賬,使用事務(wù) public void trans2() { String sql_zs = "UPDATE account SET money=money-1000 WHERE accountName='張三';"; String sql_ls = "UPDATE1 account SET money=money+1000 WHERE accountName='李四';"; try { con = JdbcUtil.getConnection(); // 默認(rèn)開啟的隱士事務(wù) // 一、設(shè)置事務(wù)為手動(dòng)提交 con.setAutoCommit(false); /*** 第一次執(zhí)行SQL ***/ pstmt = con.prepareStatement(sql_zs); pstmt.executeUpdate(); /*** 第二次執(zhí)行SQL ***/ pstmt = con.prepareStatement(sql_ls); pstmt.executeUpdate(); } catch (Exception e) { try { // 二、 出現(xiàn)異常,需要回滾事務(wù) con.rollback(); } catch (SQLException e1) { } e.printStackTrace(); } finally { try { // 三、所有的操作執(zhí)行成功, 提交事務(wù) con.commit(); JdbcUtil.closeAll(con, pstmt, null); } catch (SQLException e) { } } } // 3. 轉(zhuǎn)賬,使用事務(wù), 回滾到指定的代碼段 public void trans() { // 定義個(gè)標(biāo)記 Savepoint sp = null; // 第一次轉(zhuǎn)賬 String sql_zs1 = "UPDATE account SET money=money-1000 WHERE accountName='張三';"; String sql_ls1 = "UPDATE account SET money=money+1000 WHERE accountName='李四';"; // 第二次轉(zhuǎn)賬 String sql_zs2 = "UPDATE account SET money=money-500 WHERE accountName='張三';"; String sql_ls2 = "UPDATE1 account SET money=money+500 WHERE accountName='李四';"; try { con = JdbcUtil.getConnection(); // 默認(rèn)開啟的隱士事務(wù) con.setAutoCommit(false); // 設(shè)置事務(wù)手動(dòng)提交 /*** 第一次轉(zhuǎn)賬 ***/ pstmt = con.prepareStatement(sql_zs1); pstmt.executeUpdate(); pstmt = con.prepareStatement(sql_ls1); pstmt.executeUpdate(); // 回滾到這個(gè)位置? sp = con.setSavepoint(); /*** 第二次轉(zhuǎn)賬 ***/ pstmt = con.prepareStatement(sql_zs2); pstmt.executeUpdate(); pstmt = con.prepareStatement(sql_ls2); pstmt.executeUpdate(); } catch (Exception e) { try { // 回滾 (回滾到指定的代碼段) con.rollback(sp); } catch (SQLException e1) { } e.printStackTrace(); } finally { try { // 提交 con.commit(); } catch (SQLException e) { } JdbcUtil.closeAll(con, pstmt, null); } }}package com.xp.account;import org.junit.Test;public class App { @Test public void testname() throws Exception { // 轉(zhuǎn)賬 AccountDao accountDao = new AccountDao(); accountDao.trans(); }}六、Jdbc中大文本類型的處理Oracle中大文本數(shù)據(jù)類型,Clob 長(zhǎng)文本類型 (MySQL中不支持,使用的是text)Blob 二進(jìn)制類型MySQL數(shù)據(jù)庫(kù),Text 長(zhǎng)文本類型Blob 二進(jìn)制類型需求: jdbc中操作長(zhǎng)文本數(shù)據(jù)。設(shè)計(jì): 測(cè)試表編碼:保存大文本數(shù)據(jù)類型讀取大文本數(shù)據(jù)類型保存二進(jìn)制數(shù)據(jù)讀取二進(jìn)制數(shù)據(jù)-- 測(cè)試大數(shù)據(jù)類型CREATE TABLE test( id INT PRIMARY KEY AUTO_INCREMENT, content LONGTEXT, img LONGBLOB);package com.xp.longtext;import java.io.File;import java.io.FileReader;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;import com.xp.jdbc.utils.JdbcUtil;public class App_text { // 全局參數(shù) private Connection con; private Statement stmt; private PreparedStatement pstmt; private ResultSet rs; @Test // 1. 保存大文本數(shù)據(jù)類型 ( 寫longtext) public void testSaveText() { String sql = "insert into test(content) values(?)"; try { // 連接 con = JdbcUtil.getConnection(); // pstmt 對(duì)象 pstmt = con.prepareStatement(sql); // 設(shè)置參數(shù) // 先獲取文件路徑 String path = App_text.class.getResource("tips.txt").getPath(); FileReader reader = new FileReader(new File(path)); pstmt.setCharacterStream(1, reader); // 執(zhí)行sql pstmt.executeUpdate(); // 關(guān)閉 reader.close(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, null); } } @Test // 2. 讀取大文本數(shù)據(jù)類型 ( 讀longtext) public void testGetAsText() { String sql = "select * from test;"; try { // 連接 con = JdbcUtil.getConnection(); // pstmt 對(duì)象 pstmt = con.prepareStatement(sql); // 讀取 rs = pstmt.executeQuery(); if (rs.next()) { // 獲取長(zhǎng)文本數(shù)據(jù), 方式1: // Reader r = rs.getCharacterStream("content"); // 獲取長(zhǎng)文本數(shù)據(jù), 方式2: System.out.print(rs.getString("content")); } } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, null); } }}package com.xp.longtext;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;import com.xp.jdbc.utils.JdbcUtil;public class App_blob { // 全局參數(shù) private Connection con; private Statement stmt; private PreparedStatement pstmt; private ResultSet rs; @Test // 1. 二進(jìn)制數(shù)據(jù)類型 ( 寫longblob) public void testSaveText() { String sql = "insert into test(img) values(?)"; try { // 連接 con = JdbcUtil.getConnection(); // pstmt 對(duì)象 pstmt = con.prepareStatement(sql); // 獲取圖片流 InputStream in = App_text.class.getResourceAsStream("7.jpg"); pstmt.setBinaryStream(1, in); // 執(zhí)行保存圖片 pstmt.execute(); // 關(guān)閉 in.close(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, null); } } @Test // 2. 讀取大文本數(shù)據(jù)類型 ( 讀longblob) public void testGetAsText() { String sql = "select img from test where id=2;"; try { // 連接 con = JdbcUtil.getConnection(); // pstmt 對(duì)象 pstmt = con.prepareStatement(sql); // 讀取 rs = pstmt.executeQuery(); if (rs.next()) { // 獲取圖片流 InputStream in = rs.getBinaryStream("img"); // 圖片輸出流 FileOutputStream out = new FileOutputStream(new File( "c://1.jpg")); int len = -1; byte b[] = new byte[1024]; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } // 關(guān)閉 out.close(); in.close(); } } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.closeAll(con, pstmt, null); } }}五、綜合案例
需求分析:
登陸、注冊(cè)、注銷;
登陸成功,
顯示所有的員工
設(shè)計(jì)
數(shù)據(jù)庫(kù)設(shè)計(jì):
Admin, 存放所有的登陸用戶
Employee, 存放所有的員工信息
系統(tǒng)設(shè)計(jì)
a. 系統(tǒng)結(jié)構(gòu)
分層: 基于mvc模式的分層
b. 項(xiàng)目用到的公用組件、類 (了解)

CREATE TABLE admin( id INT PRIMARY KEY AUTO_INCREMENT, userName VARCHAR(20), pwd VARCHAR(20))-- 員工CREATE TABLE employee( empId INT PRIMARY KEY AUTO_INCREMENT, empName VARCHAR(20), dept_id INT -- 外鍵字段 );package com.xp.entity;public class Admin { private int id; private String userName; private String pwd; public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } 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; }}package com.xp.dao;import com.xp.entity.Admin;public interface IAdminDao { /** * 保存 * @param admin */ void save(Admin admin); /** * 根據(jù)用戶名密碼查詢 */ Admin findByNameAndPwd(Admin admin); /** * 檢查用戶名是否存在 * @param name 要檢查的用戶名 * @return true表示用戶名已經(jīng)存在; 否則用戶名不存在 */ boolean userExists(String name);}package com.xp.dao.impl;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import com.xp.dao.IAdminDao;import com.xp.entity.Admin;import com.xp.utils.JdbcUtil;/** * 2. 數(shù)據(jù)訪問層接口的實(shí)現(xiàn)類*/public class AdminDao implements IAdminDao { private Connection con; private PreparedStatement pstmt; private ResultSet rs; @Override public Admin findByNameAndPwd(Admin admin) { String sql = "select * from admin where userName=? and pwd=?"; Admin ad = null; try { con = JdbcUtil.getConnection(); pstmt = con.prepareStatement(sql); pstmt.setString(1, admin.getUserName()); pstmt.setString(2, admin.getPwd()); // 執(zhí)行 rs = pstmt.executeQuery(); // 遍歷 if (rs.next()) { ad = new Admin(); ad.setId(rs.getInt("id")); ad.setUserName(rs.getString("userName")); ad.setPwd(rs.getString("pwd")); } return ad; } catch (Exception e) { throw new RuntimeException(e); } finally { JdbcUtil.closeAll(con, pstmt, null); } } @Override public void save(Admin admin) { String sql = "INSERT INTO admin(userName,pwd) VALUES(?,?);"; try { con = JdbcUtil.getConnection(); pstmt = con.prepareStatement(sql); // 設(shè)置參數(shù) pstmt.setString(1, admin.getUserName()); pstmt.setString(2, admin.getPwd()); // 執(zhí)行更新 pstmt.executeUpdate(); } catch (Exception e) { throw new RuntimeException(e); } finally { JdbcUtil.closeAll(con, pstmt, null); } } @Override public boolean userExists(String name) { String sql = "select id from admin where userName=?"; try { con = JdbcUtil.getConnection(); pstmt = con.prepareStatement(sql); // 設(shè)置參數(shù) pstmt.setString(1, name); // 執(zhí)行查詢 rs = pstmt.executeQuery(); // 判斷 if (rs.next()) { int id = rs.getInt("id"); if (id > 0) { // 用戶名已經(jīng)存在 return true; } } return false; } catch (SQLException e) { throw new RuntimeException(e); } finally { JdbcUtil.closeAll(con, pstmt, rs); } }}package com.xp.service;import com.xp.entity.Admin;import com.xp.exception.UserExistsException;public interface IAdminService { /** * 注冊(cè) */ void register(Admin admin) throws UserExistsException; /** * 登陸 */ Admin login(Admin admin);}package com.xp.exception;public class UserExistsException extends Exception { public UserExistsException() { } public UserExistsException(String message) { super(message); } public UserExistsException(Throwable cause) { super(cause); } public UserExistsException(String message, Throwable cause) { super(message, cause); }}package com.xp.service.impl;import com.xp.dao.IAdminDao;import com.xp.dao.impl.AdminDao;import com.xp.entity.Admin;import com.xp.exception.UserExistsException;import com.xp.service.IAdminService;/** * 3. 業(yè)務(wù)邏輯層實(shí)現(xiàn) * * @author Jie.Yuan * */public class AdminService implements IAdminService { // 調(diào)用的dao private IAdminDao adminDao = new AdminDao(); @Override public Admin login(Admin admin) { try { return adminDao.findByNameAndPwd(admin); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void register(Admin admin) throws UserExistsException { try { // 1. 先根據(jù)用戶名查詢用戶是否存在 boolean flag = adminDao.userExists(admin.getUserName()); // 2. 如果用戶存在,不允許注冊(cè) if (flag) { // 不允許注冊(cè), 給調(diào)用者提示 throw new UserExistsException("用戶名已經(jīng)存在,注冊(cè)失敗!"); } // 3. 用戶不存在,才可以注冊(cè) adminDao.save(admin); } catch (UserExistsException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } }}package com.xp.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.xp.entity.Admin;import com.xp.exception.UserExistsException;import com.xp.service.IAdminService;import com.xp.service.impl.AdminService;public class AdminServlet extends HttpServlet { // 調(diào)用的service private IAdminService adminService = new AdminService(); public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 獲取操作類型 String method = request.getParameter("method"); if ("register".equals(method)) { register(request, response); } } /** * 注冊(cè)處理方法 * * @param request * @param response * @throws IOException * @throws ServletException */ private void register(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 1. 獲取請(qǐng)求參數(shù) String userName = request.getParameter("userName"); String pwd = request.getParameter("pwd"); // 封裝 Admin admin = new Admin(); admin.setUserName(userName); admin.setPwd(pwd); // 2. 調(diào)用Service處理注冊(cè)的業(yè)務(wù)邏輯 try { adminService.register(admin); // 注冊(cè)成功,跳轉(zhuǎn)到首頁 request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (UserExistsException e) { // 用戶名存在,注冊(cè)失敗(跳轉(zhuǎn)到注冊(cè)頁面) request.setAttribute("message", "用戶名已經(jīng)存在"); // 轉(zhuǎn)發(fā) request.getRequestDispatcher("/register.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); // 測(cè)試時(shí)候用 // 其他錯(cuò)誤, 跳轉(zhuǎn)到錯(cuò)誤頁面 response.sendRedirect(request.getContextPath() + "/error/error.jsp"); } }}<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>注冊(cè)</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <form name="frm1" action="${pageContext.request.contextPath }/admin?method=register" method="post" > <table> <tr> <td>用戶名</td> <td> <input type="text" name="userName"/> ${requestScope.message } <!-- 如果用戶名存在注冊(cè)失敗,給用戶提示 --> </td> </tr> <tr> <td>密碼</td> <td><input type="password" name="pwd"/></td> </tr> <tr> <td colspan="2"> <input type="submit" value="親,點(diǎn)我注冊(cè)!"> </td> </tr> </table> </form> </body></html>
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注