package com.student.dao.impl; import com.student.bean.PageBean; import com.student.bean.User; import com.student.bean.UserQuery; import com.student.dao.UserDao; import com.student.util.DBUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; import java.util.List; public class UserDaoImpl implements UserDao { private static final String BASE_COLUMNS = "u.id, u.username, u.password, u.salt, u.student_no, u.real_name, u.gender, u.age, " + "u.email, u.phone, u.address, u.avatar, u.clazz_id, u.role, u.status, " + "u.fail_count, u.lock_until, u.create_time"; private static final String JOIN_CLAZZ = " FROM users u LEFT JOIN clazz c ON u.clazz_id = c.id " + "LEFT JOIN major m ON c.major_id = m.id " + "LEFT JOIN department d ON m.department_id = d.id "; @Override public User findByUsernameAndPassword(String username, String password) { String sql = "SELECT " + BASE_COLUMNS + JOIN_CLAZZ + " WHERE u.username = ? AND u.password = ?"; return queryOne(sql, ps -> { ps.setString(1, username); ps.setString(2, password); }); } @Override public User findByUsername(String username) { String sql = "SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " + JOIN_CLAZZ + " WHERE u.username = ?"; return queryOne(sql, ps -> ps.setString(1, username)); } @Override public User findById(int id) { String sql = "SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " + JOIN_CLAZZ + " WHERE u.id = ?"; return queryOne(sql, ps -> ps.setInt(1, id)); } @Override public User findByStudentNo(String studentNo) { String sql = "SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " + JOIN_CLAZZ + " WHERE u.student_no = ?"; return queryOne(sql, ps -> ps.setString(1, studentNo)); } @Override public boolean insert(User user) { String sql = "INSERT INTO users (username, password, salt, student_no, real_name, gender, age, " + "email, phone, address, avatar, clazz_id, role, status) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); fillInsertParams(ps, user); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("新增用户失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean update(User user) { String sql = "UPDATE users SET username=?, student_no=?, real_name=?, gender=?, age=?, email=?, " + "phone=?, address=?, avatar=?, clazz_id=?, role=?, status=? WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setString(1, user.getUsername()); setStringOrNull(ps, 2, user.getStudentNo()); ps.setString(3, user.getRealName()); ps.setString(4, user.getGender()); setIntOrNull(ps, 5, user.getAge()); ps.setString(6, user.getEmail()); ps.setString(7, user.getPhone()); ps.setString(8, user.getAddress()); setStringOrNull(ps, 9, user.getAvatar()); setIntOrNull(ps, 10, user.getClazzId()); ps.setInt(11, user.getRole() != null ? user.getRole() : User.ROLE_STUDENT); ps.setInt(12, user.getStatus() != null ? user.getStatus() : User.STATUS_ACTIVE); ps.setInt(13, user.getId()); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("更新用户失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean updateProfile(User user) { String sql = "UPDATE users SET real_name=?, gender=?, age=?, email=?, phone=?, address=? WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setString(1, user.getRealName()); ps.setString(2, user.getGender()); setIntOrNull(ps, 3, user.getAge()); ps.setString(4, user.getEmail()); ps.setString(5, user.getPhone()); ps.setString(6, user.getAddress()); ps.setInt(7, user.getId()); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("更新用户资料失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean updateAvatar(int userId, String avatar) { String sql = "UPDATE users SET avatar=? WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setString(1, avatar); ps.setInt(2, userId); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("更新头像失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean delete(int id) { String sql = "DELETE FROM users WHERE id = ? AND role = 0"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setInt(1, id); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("删除用户失败", e); } finally { DBUtil.close(conn, ps); } } @Override public int count(UserQuery query) { StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM users u WHERE 1=1"); List params = appendQueryConditions(sql, query); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql.toString()); setParams(ps, params); rs = ps.executeQuery(); if (rs.next()) { return rs.getInt(1); } } catch (SQLException e) { throw new RuntimeException("统计用户数量失败", e); } finally { DBUtil.close(conn, ps, rs); } return 0; } @Override public List findList(UserQuery query, int startIndex, int pageSize) { StringBuilder sql = new StringBuilder("SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " + JOIN_CLAZZ + " WHERE 1=1"); List params = appendQueryConditions(sql, query); sql.append(" ORDER BY u.id DESC LIMIT ?, ?"); params.add(startIndex); params.add(pageSize); List list = new ArrayList<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql.toString()); setParams(ps, params); rs = ps.executeQuery(); while (rs.next()) { list.add(mapRow(rs)); } } catch (SQLException e) { throw new RuntimeException("分页查询用户失败", e); } finally { DBUtil.close(conn, ps, rs); } return list; } @Override public PageBean findPage(UserQuery query) { PageBean page = new PageBean<>(query.getCurrentPage(), query.getPageSize()); page.setTotalCount(count(query)); page.setData(findList(query, page.getStartIndex(), page.getPageSize())); return page; } @Override public PageBean findPendingRegister(int currentPage, int pageSize) { UserQuery query = new UserQuery(); query.setStatus(User.STATUS_PENDING); query.setRole(User.ROLE_STUDENT); query.setCurrentPage(currentPage); query.setPageSize(pageSize); return findPage(query); } @Override public boolean updatePassword(int userId, String password, String salt) { String sql = "UPDATE users SET password=?, salt=?, fail_count=0, lock_until=NULL WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setString(1, password); ps.setString(2, salt); ps.setInt(3, userId); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("更新密码失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean updateFailCount(int userId, int failCount) { String sql = "UPDATE users SET fail_count=? WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setInt(1, failCount); ps.setInt(2, userId); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("更新失败次数失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean lockUser(int userId, java.util.Date lockUntil) { String sql = "UPDATE users SET lock_until=? WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); if (lockUntil != null) { ps.setTimestamp(1, new Timestamp(lockUntil.getTime())); } else { ps.setNull(1, Types.TIMESTAMP); } ps.setInt(2, userId); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("锁定用户失败", e); } finally { DBUtil.close(conn, ps); } } @Override public boolean updateStatus(int userId, int status) { String sql = "UPDATE users SET status=? WHERE id=?"; Connection conn = null; PreparedStatement ps = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setInt(1, status); ps.setInt(2, userId); return ps.executeUpdate() > 0; } catch (SQLException e) { throw new RuntimeException("更新用户状态失败", e); } finally { DBUtil.close(conn, ps); } } @Override public List findAllStudents() { UserQuery query = new UserQuery(); query.setRole(User.ROLE_STUDENT); query.setCurrentPage(1); query.setPageSize(Integer.MAX_VALUE); return findList(query, 0, Integer.MAX_VALUE); } @Override public List findAllTeachers() { UserQuery query = new UserQuery(); query.setRole(User.ROLE_TEACHER); query.setCurrentPage(1); query.setPageSize(Integer.MAX_VALUE); return findList(query, 0, Integer.MAX_VALUE); } private List appendQueryConditions(StringBuilder sql, UserQuery query) { List params = new ArrayList<>(); if (query.getRole() != null) { sql.append(" AND u.role = ?"); params.add(query.getRole()); } if (query.getStatus() != null) { sql.append(" AND u.status = ?"); params.add(query.getStatus()); } if (query.getClazzId() != null) { sql.append(" AND u.clazz_id = ?"); params.add(query.getClazzId()); } if (query.getGender() != null && !query.getGender().isEmpty()) { sql.append(" AND u.gender = ?"); params.add(query.getGender()); } if (query.getAgeMin() != null) { sql.append(" AND u.age >= ?"); params.add(query.getAgeMin()); } if (query.getAgeMax() != null) { sql.append(" AND u.age <= ?"); params.add(query.getAgeMax()); } if (query.getKeyword() != null && !query.getKeyword().isEmpty()) { sql.append(" AND (u.username LIKE ? OR u.real_name LIKE ? OR u.student_no LIKE ? " + "OR u.email LIKE ? OR u.phone LIKE ?)"); String pattern = "%" + query.getKeyword() + "%"; for (int i = 0; i < 5; i++) { params.add(pattern); } } return params; } private void fillInsertParams(PreparedStatement ps, User user) throws SQLException { ps.setString(1, user.getUsername()); ps.setString(2, user.getPassword()); ps.setString(3, user.getSalt()); setStringOrNull(ps, 4, user.getStudentNo()); ps.setString(5, user.getRealName()); ps.setString(6, user.getGender()); setIntOrNull(ps, 7, user.getAge()); ps.setString(8, user.getEmail()); ps.setString(9, user.getPhone()); ps.setString(10, user.getAddress()); setStringOrNull(ps, 11, user.getAvatar()); setIntOrNull(ps, 12, user.getClazzId()); ps.setInt(13, user.getRole() != null ? user.getRole() : User.ROLE_STUDENT); ps.setInt(14, user.getStatus() != null ? user.getStatus() : User.STATUS_ACTIVE); } private User mapRow(ResultSet rs) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setPassword(rs.getString("password")); user.setSalt(rs.getString("salt")); user.setStudentNo(rs.getString("student_no")); user.setRealName(rs.getString("real_name")); user.setGender(rs.getString("gender")); int age = rs.getInt("age"); user.setAge(rs.wasNull() ? null : age); user.setEmail(rs.getString("email")); user.setPhone(rs.getString("phone")); user.setAddress(rs.getString("address")); user.setAvatar(rs.getString("avatar")); int clazzId = rs.getInt("clazz_id"); user.setClazzId(rs.wasNull() ? null : clazzId); user.setRole(rs.getInt("role")); user.setStatus(rs.getInt("status")); int failCount = rs.getInt("fail_count"); user.setFailCount(rs.wasNull() ? 0 : failCount); Timestamp lockUntil = rs.getTimestamp("lock_until"); if (lockUntil != null) { user.setLockUntil(new java.util.Date(lockUntil.getTime())); } Timestamp createTime = rs.getTimestamp("create_time"); if (createTime != null) { user.setCreateTime(new java.util.Date(createTime.getTime())); } try { user.setClazzName(rs.getString("clazz_name")); user.setMajorName(rs.getString("major_name")); user.setDeptName(rs.getString("dept_name")); } catch (SQLException ignored) { } return user; } private void setIntOrNull(PreparedStatement ps, int index, Integer value) throws SQLException { if (value != null) { ps.setInt(index, value); } else { ps.setNull(index, Types.INTEGER); } } private void setStringOrNull(PreparedStatement ps, int index, String value) throws SQLException { if (value != null) { ps.setString(index, value); } else { ps.setNull(index, Types.VARCHAR); } } private void setParams(PreparedStatement ps, List params) throws SQLException { for (int i = 0; i < params.size(); i++) { Object param = params.get(i); if (param instanceof Integer) { ps.setInt(i + 1, (Integer) param); } else if (param instanceof String) { ps.setString(i + 1, (String) param); } } } @FunctionalInterface private interface ParamSetter { void set(PreparedStatement ps) throws SQLException; } private User queryOne(String sql, ParamSetter setter) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); setter.set(ps); rs = ps.executeQuery(); if (rs.next()) { return mapRow(rs); } } catch (SQLException e) { throw new RuntimeException("用户查询失败", e); } finally { DBUtil.close(conn, ps, rs); } return null; } }