1.導入分頁工具類
查看一下這個工具類的源碼
OOP的3大特性:封裝、繼承、多態,其中封裝 = 屬性私有+屬性的get/set() + 在set中限制一些不安全的賦值操作(這一步可以留到service層再做,但是在封裝的時候做更好,這樣減少了service層的代碼,且體現了封裝的特性)
2.用戶列表頁面導入
首先是HTML文件
分析:
- Dao層使用聚合函數COUNT(*)查詢用戶表一共多少條記錄
- service層用於統計總共有多少條數據
- servlet層用於向前端返回總共的數據條數
3.獲取用戶數量
1、UserDao接口
因為是獲取用戶的數量,所以和用戶表有關,那這個接口方法就放在前面已經創建好的UserDao中
方法定義的時候需要哪些參數?
查看前端素材:
可見,查詢界面我們需要實現按照用戶名查詢、按照角色名稱查詢和整表查詢
再去看看數據庫中的數據表
聯表查詢的基本SQL語句
SELECT COUNT(1)
FROM smbms_user u,smbms_role r
WHERE u.userRole = r.id;
這是MYSQL的方言版內連接查詢,內連接兩張表的地位平等,只要我們加了WHERE過濾笛卡爾積,那么輸出的結果就只包含有主外鍵關聯的字段
但是從前面的需求我們可以看出,前端素材提供了按照姓名查詢、按照職位查詢和整表查詢,所以我們需要在上面聯表查詢的基礎上再添加一些篩選條件,添加的手段就是使用"AND 條件"來實現
在Java中實現我們可以使用StringBuffer來實現sql語句的拼接
package com.thhh.dao.user;
import com.thhh.pojo.User;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface UserDao {
/**
* 1、得到要進行登陸的用戶
* @param conn:數據庫連接對象
* @param userCode:通過用戶的用戶名userCode查詢用戶數據
* @return
*/
public User getLoginUserInfo(Connection conn,String userCode);
/**
* 2、修改用戶密碼
* @param conn:數據庫連接對象
* @param id:修改密碼的用戶的ID
* @param newPwd:新密碼
* @return:影響行數
*/
public int updatePwd(Connection conn,String newPwd,int id);
/**
* 3、用於獲取數據庫中用戶總數
* @param conn:數據庫連接對象
* @param userName:用戶名,這個參數主要用於按照用戶名稱查詢用戶信息
* @param userRole:用戶角色,這個參數主要用於按照用戶角色查詢用戶信息
* @return :查詢到的行數
*/
public int getUserCount(Connection conn, String userName, int userRole) throws SQLException;
}
只看方法3
2、UserDaoImpl接口實現
//3、根據用戶名/角色名獲取用戶總數
@Override
public int getUserCount(Connection conn, String userName, int userRole) throws SQLException {
PreparedStatement pstmt = null;
ResultSet rs = null;
int count = 0;
if (conn!=null){
StringBuffer sql = new StringBuffer();//使用字符串緩沖區,這樣就可以動態的在sql后面追加AND條件了
sql.append("SELECT COUNT(1) COUNT FROM smbms_user u,smbms_role r WHERE u.userRole = r.id");//基本的聯表查詢SQL語句
List<Object> list = new ArrayList<Object>();//創建一個list來存儲我們要拼接的篩選條件,由於我們不能限制傳入的參數的數據類型,所以泛型指定為object
if (!StringUtils.isNullOrEmpty(userName)){//判斷傳入的用戶名是不是空,如果不是空表明前端指定了按照姓名查詢的參數
sql.append("AND userName like ?");
list.add("%"+userName+"%");
}
if (userRole>0){
sql.append("AND userRole = ?");
list.add(userRole);
}
Object[] params = list.toArray();//獲得BaseDao中為pstmt對象設置參數的參數列表
rs = BaseDao.executeQuery(sql.toString(), params, conn, pstmt, rs);//調用查詢定義好的查詢方法
if (rs.next()){//獲取查詢結果
count = rs.getInt("COUNT");//COUNT是在SQL語句中為查詢結果取的別名
}
BaseDao.close(null,pstmt,rs);//關閉資源
}
return count;
}
注意回顧知識點:
- StringBuffer類:一個專門用來彌補String內容不可修改的類,調用這個類對象的append()可以實現在字符串的末尾加上新字符串且不會產生新的字符串對象(String對象的拼接操作其實在底層就是產生了新的String對象)
- 使用List集合來存儲參數,這樣做的好處就在於我們可以動態的向集合中添加參數,而不是像前面使用數組那樣固定了數組長度;其實集合也是用來彌補數組長度不可修改的缺陷而出現的,使用集合存儲數據即使數據很多也不會產生新的集合對象,而數組不一樣,數組一經創建長度就固定了;而針對上面要實現的需求我們不知道到底前端要進行哪一種操作,所以我們不能定義一個定長的數組,即使按照最大需求量定義數組,雖然可以滿足要求,但是在不能充分使用的時候就是資源的浪費
- 上面使用的動態的拼接SQL語句的做法很明智:既使用了StringBuffer對象控制SQL語句在提交之前可變,又使用了List集合來存儲參數,在提交的時候才將其轉為數組
3、UserService接口
package com.thhh.service.user;
import com.thhh.pojo.User;
public interface UserService {
/**
* 1、獲取登陸用戶對象,對用戶登陸身份進行驗證
* @param userCode:用戶賬號
* @param userPassword:用戶密碼,注意,密碼判斷我們在service層進行;
* 在Dao層只是簡單的操作數據庫,沒有其他的邏輯代碼;在servlet層中只是接收和轉發請求以及控制視圖跳轉
* 而對於業務層(service)就是用來實現業務邏輯代碼的
* @return
*/
public User login(String userCode,String userPassword);
/**
* 2、根據用戶ID修改用戶密碼
* @param newPwd:新密碼
* @param id:用戶ID
* @return
*/
public boolean updatePwd(String newPwd, int id);
/**
* 3、獲取用戶總數
* @param userName:按照用戶姓名查,查到的用戶總數
* @param userRole:按照用戶角色查,查到的用戶總數
* @return:返滬對應查詢條件查到的用戶總數
*/
public int getUserCount(String userName, int userRole) ;
}
只看方法3
4、UserServiceImpl接口實現
/**
* 3、按照條件查詢符合條件的用戶總數
* @param userName:按照用戶姓名查,查到的用戶總數
* @param userRole:按照用戶角色查,查到的用戶總數
* @return
*/
@Override
public int getUserCount(String userName, int userRole) {
Connection conn = null;
int rs = 0;
try {
conn = BaseDao.getConnection();//獲取數據庫連接對象
rs = userDao.getUserCount(conn,userName,userRole);//業務層調用Dao層獲取業務結果
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
BaseDao.close(conn,null,null);//關閉資源
}
return rs;//業務層將業務結果返回給servlet
}
5、測試
bug1:
4.獲取用戶列表
1、UserDao接口
/**
* 4、用戶獲取用戶列表
* @param conn:數據庫連接對象
* ===========后面兩個參數用於條件查詢用戶數據
* @param userName:按照用戶名查找
* @param userRole:按照角色名稱查找
* ===========后面兩個參數用於對按照上面條件查詢出來的結果進行分頁處理
* @param currentPageNo:翻到第多少頁
* @param pageSize:每一頁多少條數據
* @return:返回滿足條件的user對象集合
*/
public List<User> getUserList(Connection conn, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException;
2、UserDaoImpl接口實現
//4、獲取滿足條件的用戶對象集合
@Override
public List<User> getUserList(Connection conn, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<User> userList = null;
if (conn!=null){
userList = new ArrayList<User>();
StringBuffer sql = new StringBuffer();
sql.append("SELECT u.*,r.roleName as userRoleName FROM smbms_user u,smbms_role r WHERE u.userRole = r.id");
List<Object> temp = new ArrayList<Object>();
if (userName!=null){
sql.append(" AND u.userName LIKE ?");
temp.add("%"+userName+"%");
}
if (userRole>0){
sql.append(" AND u.userRole = ?");
temp.add(userRole);
}
sql.append(" ORDER BY u.creationDate DESC LIMIT ?,?");//在sql最后追加一個排序和分頁
//5
//1 5
//2 10
//3 15
currentPageNo = (currentPageNo-1)*pageSize;//減一的原因就是MYSQL分頁的index從0開始
temp.add(currentPageNo);//從哪一個下標開始
temp.add(pageSize);//從currentPageNo連續取幾個
Object[] params = temp.toArray();
rs = BaseDao.executeQuery(sql.toString(),params,conn,pstmt,rs);
while (rs.next()){
User _user = new User();
_user.setId(rs.getInt("id"));
_user.setUserCode(rs.getString("userCode"));
_user.setUserName(rs.getString("userName"));
_user.setGender(rs.getInt("gender"));
_user.setBirthday(rs.getDate("birthday"));
_user.setPhone(rs.getString("phone"));
_user.setUserRole(rs.getInt("userRole"));
_user.setUserRoleName(rs.getString("userRoleName"));//這個屬性是在POJO中新加入的,數據表中沒有
userList.add(_user);//將查到的這個對象分裝為對象並存入List集合中
}
BaseDao.close(null,pstmt,rs);
}
return userList;
}
3、UserService接口
/**
* 4、根據用戶名/用戶角色名稱來查詢數據,返回一個User對象集合,而currentPageNo+pageSize用於前端做分頁操作
* @param userName
* @param userRole
* @param currentPageNo
* @param pageSize
* @return:滿足條件+limit的User對象集合
*/
public List<User> getUserList(String userName, int userRole, int currentPageNo, int pageSize);
4、Userservice接口實現
/**
* 4、根據用戶名/用戶角色名稱來查詢數據,返回一個User對象集合,而currentPageNo+pageSize用於前端做分頁操作
* @param userName
* @param userRole
* @param currentPageNo
* @param pageSize
* @return:滿足條件+limit的User對象集合
*/
@Override
public List<User> getUserList(String userName, int userRole, int currentPageNo, int pageSize) {
Connection conn = null;
List<User> userList = null;
try {
conn = BaseDao.getConnection();//獲取連接
userList = userDao.getUserList(conn,userName,userRole,currentPageNo,pageSize);//業務層調用Dao層獲取業務結果
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
BaseDao.close(conn,null, null);//關閉資源
}
return userList;//業務層將業務結果返回給servlet
}
5、測試
@Test
public void test(){
List userList = new UserServiceImpl().getUserList(null,0,2,5);
//(3-1)*5 = 10,所以展示的是10~14條數據,但是一共只有12條,注意:MYSQL中結果index從0開始
for (Object o : userList) {
System.out.println(((User)o).getUserName());
}
}
測試完成!