JDBC(二)
在開發過程中資料庫訪問程式碼應和業務程式碼徹底分離
將資料層抽離出來,將資料訪問的程式碼以物件的方式進行封裝,便於業務層進行復用
資料訪問物件稱為DAO(DAO Data Access Object 資料訪問物件)
DAO應根據資料表為單位進行獨立的封裝,如現在有Users表以及Dep表,在設計DAO時應封裝UserDao和DepDao兩個資料訪問物件;UserDao中僅封裝和Users表有關的資料訪問方法,DepDao封裝和dep有關的資料訪問方法
DAO層屬於專案結構中相對底層的呼叫,因此在業務層訪問資料層時應確保DAO編寫的準確性,每個DAO都應進行測試
測試分為白盒測試和黑盒測試
白盒測試:測試的過程是能看得到的
黑盒:只看結果執行是否通過,不看過程
匯入單元測試的jar包:File——ProjectStructure——Libraries——點選加號——匯入“C3P0”包
使用資料池(連線池)技術解決應用程式與資料庫通訊連線消耗資源過大的問題
常用的連線池:
c3p0、DBCP、Duird
匯入連線池jar包:
<c3p0-config> <default-config> <!--配置連線池初始的連線數--> <property name="initialPoolSize">10</property> <!--配置最大的連線數--> <property name="maxPoolSize">25</property> <!--配置最小的連線數--> <property name="minPoolSize">5</property> <!--配置驅動--> <property name="driverClass">com.mysql.jdbc.Driver</property> <!--配置URL--> <property name="jdbcUrl">jdbc:mysql:\\localhost:3306/bbs_db</property> <!--配置連線資料庫的使用者名稱--> <property name="user">root</property> <!--配置密碼--> <property name="password">tjhilu</property> </default-config> </c3p0-config>
建立和資料的連線有兩種方法:
1.使用靜態塊載入驅動
Class.forName("com.mysql.jdbc.Driver"),
在獲取連線的方法中通過
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/geekhome", "root", "root")
獲取連線物件
2.使用資料池進行載入資料
/** * 連線池的使用 */ public class Demo8 { public static voidmain(String[] args) { try { //建立連線池物件 DataSource dataSource = new ComboPooledDataSource(); //從連線池中獲取連線物件 Connection con = dataSource.getConnection(); System.out.println(con); } catch (SQLException e) { e.printStackTrace(); } } }
將資料層和業務層分離出來,需要建立一個Dao包將資料類都封裝起來
資料庫連線的類:
/** * 封裝了資料庫連線和關閉的工具類 */ public class DaoUtil { //使用靜態塊載入驅動 // static{ // try { // Class.forName("com.mysql.jdbc.Driver"); // } catch (ClassNotFoundException e) { // e.printStackTrace(); // } // } //資料池 private static DataSource dataSource; static{ //初始化連線池 dataSource = new ComboPooledDataSource(); } /** * 獲得連線 * @return */ public static Connection openConnection(){ Connection con = null; // try { // con = DriverManager.getConnection("jdbc:mysql://localhost:3306/geekhome", "root", "root"); // } catch (Exception e) { // e.printStackTrace(); // } //通過連線池獲取連線物件 if(dataSource != null){ try { con = dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } } return con; } /** * 關閉資料庫物件:判斷只要不為null就要關閉 * @param con * @param pstmt * @param rs */ public static void close(Connection con, PreparedStatement pstmt, ResultSet rs){ try { if(rs != null){ rs.close(); } if(pstmt != null){ pstmt.close(); } if(con != null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
使用者類的Dao包:
將業務中需要對資料進行的操作方法寫在資料類中,業務層中直接呼叫方法得到返回值即可
package com.igeek.dao; import com.igeek.pojo.User; import java.sql.*; import java.util.ArrayList; /** * 封裝users表相關的資料訪問操作 */ public class UserDao { /** * 刪除使用者 * @param userId */ public void delete(int userId){ //開啟資料庫連線 Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; if(con != null){ try { //建立處理器 pstmt = con.prepareStatement("delete from users where userid=?"); //注入引數 pstmt.setInt(1, userId); //執行刪除 pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally{ //關閉資料庫物件 DaoUtil.close(con, pstmt, null); } } } /** * 新增使用者資料 * @param user */ public void addUser(User user){ //開啟資料庫連線 Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; if(con != null){ try { pstmt = con.prepareStatement("insert into users values(null,?,?,null,null,null,null,?)"); //注入引數 pstmt.setString(1, user.getUserName()); //pstmt.setTimestamp(2, new Timestamp(user.getBirthday().getTime())); pstmt.setTimestamp(2, null); pstmt.setString(3, user.getPassword()); //執行新增 pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { DaoUtil.close(con, pstmt, null); } } } /** * 修改使用者 * 根據使用者的編號進行修改,修改使用者的密碼和生日 * @param user */ public void update(User user){ Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; if(con != null){ try { pstmt = con.prepareStatement("update users set password=?,birthday=? where userid=?"); //注入引數 pstmt.setString(1, user.getPassword()); pstmt.setDate(2, new Date(user.getBirthday().getTime())); pstmt.setInt(3, user.getUserId()); pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { DaoUtil.close(con, pstmt, null); } } } /** * 根據使用者編號查詢 * @param userId * @return */ public User findById(int userId){ User user = null; Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; ResultSet rs = null; if(con != null){ try { pstmt = con.prepareStatement("select userid,username,birthday,password from users where " + "userid=? "); pstmt.setInt(1, userId); //執行查詢 rs = pstmt.executeQuery(); while(rs.next()){ user = new User(); user.setUserId(rs.getInt(1)); user.setUserName(rs.getString(2)); user.setBirthday(rs.getTimestamp(3)); user.setPassword(rs.getString(4)); } } catch (SQLException e) { e.printStackTrace(); } finally { DaoUtil.close(con, pstmt, rs); } } return user; } /** * 查詢users表的所有資料:返回一個user集合 */ public ArrayList<User> findAll(){ ArrayList<User> list = new ArrayList<>(); Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; ResultSet rs = null; if(con != null){ try { pstmt = con.prepareStatement("select userid,username,password,birthday from users"); rs = pstmt.executeQuery(); while(rs.next()){ //建立User物件 User user = new User(); //封裝列值至user物件 user.setUserId(rs.getInt(1)); user.setUserName(rs.getString(2)); user.setPassword(rs.getString(3)); user.setBirthday(rs.getDate(4)); //將user物件新增至集合儲存 list.add(user); } } catch (SQLException e) { e.printStackTrace(); } finally { DaoUtil.close(con, pstmt, rs); } } return list; }
/**
* 查詢users表中的所有使用者:返回一個user集合
* 按照頁面進行查詢
*pstmt = con.prepareStatement("select userid,username,password,birthday " +
"from users limit ?,3");//第一個引數表示從什麼位置開始,第二個引數表示每頁顯示多少條內容
*pstmt.setInt(1, (page-1)*3); //注入佔位符處的引數
*/
public ArrayList<User> findByPage(int page){
//要先例項化,不然要是找到以後在例項化,那麼每次都會重新new ArrayList<User> list = new ArrayList<>(); Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; ResultSet rs = null; if(con != null){ try { pstmt = con.prepareStatement("select userid,username,password,birthday " + "from users limit ?,3"); pstmt.setInt(1, (page-1)*3); rs = pstmt.executeQuery(); while(rs.next()){ //建立User物件 User user = new User(); //封裝列值至user物件 user.setUserId(rs.getInt(1)); user.setUserName(rs.getString(2)); user.setPassword(rs.getString(3)); user.setBirthday(rs.getDate(4)); //將user物件新增至集合儲存 list.add(user); } } catch (SQLException e) { e.printStackTrace(); } finally { DaoUtil.close(con, pstmt, rs); } } return list; } /** * 根據使用者名稱查詢 * @param userName * @return */ public User findByName(String userName){ User user = null; Connection con = DaoUtil.openConnection(); PreparedStatement pstmt = null; ResultSet rs = null; if(con != null){ try { pstmt = con.prepareStatement("select 1userid,username,birthday,password from users where " + "userName=? "); pstmt.setString(1, userName); //執行查詢 rs = pstmt.executeQuery(); while(rs.next()){ user = new User(); user.setUserId(rs.getInt(1)); user.setUserName(rs.getString(2)); user.setBirthday(rs.getTimestamp(3)); user.setPassword(rs.getString(4)); } } catch (SQLException e) { e.printStackTrace(); } finally { DaoUtil.close(con, pstmt, rs); } } return user; } }
user類:
package com.igeek.pojo; import java.util.Date; /** * users表的對映類,用於封裝users表的資料行 */ public class User { private int userId; private String userName; private String password; private Date birthday; public User() { } public User(String userName, String password, Date birthday) { this.userName = userName; this.password = password; this.birthday = birthday; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } 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 Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
業務類:
package com.igeek; import com.igeek.dao.UserDao; import com.igeek.pojo.User; import java.util.Scanner; /** * 在業務中使用DAO實現資料訪問 */ public class Demo7 { private UserDao userDao; private Scanner sc; public Demo7() { userDao = new UserDao(); sc = new Scanner(System.in); } public void start(){ System.out.println("1. 登入"); System.out.println("2. 註冊"); System.out.println("請選擇:"); int chooice = sc.nextInt(); switch(chooice){ case 1: login(); break; case 2: regist(); break; } } /** * 登入 */ public void login(){ System.out.println("請輸入使用者名稱:"); String userName = sc.next(); System.out.println("請輸入密碼:"); String password = sc.next(); //根據使用者名稱查詢 User user = userDao.findByName(userName); //判斷使用者是否找到 if(user != null){ //判斷密碼 if(password.equals(user.getPassword())){ System.out.println("登入成功!"); } else{ System.out.println("密碼錯誤!"); login(); } } else{ System.out.println("使用者名稱不存在!"); login(); } } /** * 註冊 */ public void regist(){ System.out.println("請輸入使用者名稱:"); String userName = sc.next(); System.out.println("請輸入密碼:"); String password = sc.next(); //查詢使用者名稱是否被註冊 User user = userDao.findByName(userName); if(user == null){ //建立要註冊的使用者物件 User registUser = new User(); registUser.setUserName(userName); registUser.setPassword(password); userDao.addUser(registUser); System.out.println("註冊成功!"); start(); } else{ System.out.println("使用者名稱已被註冊!"); regist(); } } public static void main(String[] args) { Demo7 demo = new Demo7(); demo.start(); } }