狂神说Java【SMBMS】——SMBMS超市订单管理系统(六) ——用户管理功能实现
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());
}
}
测试完成!