用spring+mybaities架构制作一个人事/工资/考勤管理系统

在用javaweb三层架构,(传递多个字段)新增一个数据库数据时,在service层实体类对dao层接口方法调用时,先创建一个对象,然后用set方法给对象实体类的值赋值,然后再把对象赋值给接口函数

可以传年月日时分秒

employeeHistory.setChangeDate(java.sql.Timestamp.valueOf("2022-12-12 00:00:00"));

只能传年月日

employeeHistory.setChangeDate(Date.valueOf("2022-12-12"))

 

注意数据库的序列,这个东西好像规定你过来数据库主键的自增,在前端调用的时候如果传递了这个主键的字段会报错500来着,但是测试类传这个主键不会报错,因为测试类是直接调用controller层的方法,绕过了springMVC的检测

 

我的大概流程

先搞定数据库,把表建好序列搞好触发器弄好(保留整个sql语句)

然后确定系统界面的前后端框架(我是javaweb+mybatis的三层架构框架)(把框架和sql语句给ai然后生成 可以省力一点反正后面写测试类还得自己修改然后熟悉然后测试)

然后连接数据库

然后按照功能把三层架构一个一个方法到一个一个类建好

然后写测试类把所有方法测试一遍(在这个过程补充需要的方法和修改ai给的方法)

然后再根据测试类看方法需要用的数据写jsp文件(可以直接把controller层的代码和测试类的代码给ai然后直接生成jsp文件)

然后在jsp文件按照方法一个一个测试是否能用并且是否合理然后修改

最后再统一样式或者结束。

 

 

这是数据库部分

-- 1. 序列创建
-- 部门序列
CREATE SEQUENCE seq_department_id START WITH 100 INCREMENT BY 10;

-- 职位序列
CREATE SEQUENCE seq_position_id START WITH 10 INCREMENT BY 1;

-- 员工序列
CREATE SEQUENCE seq_employee_id START WITH 1000 INCREMENT BY 1;

-- 考勤序列
CREATE SEQUENCE seq_attendance_id START WITH 1 INCREMENT BY 1;

-- 工资序列
CREATE SEQUENCE seq_salary_id START WITH 1 INCREMENT BY 1;

-- 员工历史记录序列
CREATE SEQUENCE seq_employee_history START WITH 1 INCREMENT BY 1;

-- 2. 核心表结构设计
-- 部门表
CREATE TABLE department (
  dept_id NUMBER PRIMARY KEY,
  dept_name VARCHAR2(50) NOT NULL
);

-- 职位表
CREATE TABLE position (
  pos_id NUMBER PRIMARY KEY,
  pos_name VARCHAR2(20) NOT NULL,
  base_salary NUMBER(10,2) NOT NULL,
  pos_level NUMBER(1) NOT NULL CHECK (pos_level BETWEEN 1 AND 5) -- 1试用2正式3组长4经理5总经理
);

-- 员工表
CREATE TABLE employee (
  emp_id NUMBER PRIMARY KEY,
  emp_name VARCHAR2(20) NOT NULL,
  dept_id NUMBER REFERENCES department(dept_id),
  pos_id NUMBER REFERENCES position(pos_id),
  hire_date DATE NOT NULL,
  status NUMBER(1) DEFAULT 1 -- 0离职1在职
);

-- 考勤表
CREATE TABLE attendance (
  att_id NUMBER PRIMARY KEY,
  emp_id NUMBER REFERENCES employee(emp_id),
  att_date DATE DEFAULT SYSDATE NOT NULL,
  check_in TIMESTAMP,
  check_out TIMESTAMP,
  att_type VARCHAR2(10) DEFAULT '正常'
);

-- 工资表
CREATE TABLE salary (
  sal_id NUMBER PRIMARY KEY,
  emp_id NUMBER REFERENCES employee(emp_id),
  year NUMBER(4) NOT NULL,
  month NUMBER(2) NOT NULL,
  base_salary NUMBER(10,2) NOT NULL,
  bonus NUMBER(10,2) DEFAULT 0,
  deduction NUMBER(10,2) DEFAULT 0,
  total NUMBER(10,2) GENERATED ALWAYS AS (base_salary + bonus - deduction) VIRTUAL,
  CONSTRAINT uk_salary UNIQUE (emp_id, year, month)
);

-- 员工历史表
CREATE TABLE employee_history (
  history_id NUMBER PRIMARY KEY,
  emp_id NUMBER REFERENCES employee(emp_id),
  change_type VARCHAR2(10), -- 调动/离职
  change_date DATE DEFAULT SYSDATE
);

-- 登录用的
CREATE TABLE users (
  user_id NUMBER PRIMARY KEY,
  username VARCHAR2(50) UNIQUE NOT NULL,
  password VARCHAR2(50) NOT NULL
);
CREATE SEQUENCE seq_user_id START WITH 1 INCREMENT BY 1;
INSERT INTO USERS (USER_ID, USERNAME, PASSWORD) VALUES (1, 'admin', '123456');

-- 3. 关键触发器
-- 触发器1:自动处理迟到/缺勤

CREATE OR REPLACE TRIGGER trg_attendance_check
BEFORE INSERT OR UPDATE ON attendance
FOR EACH ROW
DECLARE
v_base_time TIMESTAMP;
BEGIN
v_base_time := TO_TIMESTAMP(TO_CHAR(:NEW.att_date, 'YYYY-MM-DD'), 'YYYY-MM-DD');
IF :NEW.check_in > v_base_time + INTERVAL '9' HOUR THEN
IF :NEW.check_in >= v_base_time + INTERVAL '10' HOUR THEN
:NEW.att_type := '缺勤';
ELSE
:NEW.att_type := '迟到';
END IF;
ELSE
:NEW.att_type := '正常'; -- 建议加上确保数据一致性
END IF;
END;
/



-- 触发器2:自动记录员工变动历史
CREATE OR REPLACE TRIGGER trg_employee_history
AFTER UPDATE OF dept_id, pos_id, status ON employee
FOR EACH ROW
BEGIN
  IF :OLD.dept_id != :NEW.dept_id OR :OLD.pos_id != :NEW.pos_id OR :OLD.status != :NEW.status THEN
    INSERT INTO employee_history VALUES(
      seq_employee_history.NEXTVAL,
      :NEW.emp_id,
      CASE WHEN :NEW.status = 0 THEN '离职' ELSE '调动' END,
      SYSDATE
   
);
  END IF;
END;
/

-- 触发器3:自动计算工资扣款

CREATE OR REPLACE TRIGGER trg_salary_deduction
BEFORE INSERT OR UPDATE ON salary
FOR EACH ROW
DECLARE
v_absent_days NUMBER;
BEGIN
SELECT COUNT(*) INTO v_absent_days
FROM attendance
WHERE emp_id = :NEW.emp_id
AND att_date >= TO_DATE(:NEW.year || '-' || :NEW.month || '-01', 'YYYY-MM-DD')
AND att_date < ADD_MONTHS(TO_DATE(:NEW.year || '-' || :NEW.month || '-01', 'YYYY-MM-DD'), 1)
AND att_type = '缺勤';

:NEW.deduction := ROUND(v_absent_days * (:NEW.base_salary/22), 2);
END;
/



-- 4. 统计视图
-- 视图1:部门考勤统计
CREATE OR REPLACE VIEW v_dept_attendance AS
SELECT
  d.dept_name,
  TO_CHAR(a.att_date, 'YYYY-MM') AS month,
  COUNT(DISTINCT a.emp_id) AS employee_count,
  SUM(CASE WHEN a.att_type = '正常' THEN 1 ELSE 0 END) AS normal_days,
  SUM(CASE WHEN a.att_type = '迟到' THEN 1 ELSE 0 END) AS late_days,
  SUM(CASE WHEN a.att_type = '缺勤' THEN 1 ELSE 0 END) AS absent_days
FROM attendance a
JOIN employee e ON a.emp_id = e.emp_id
JOIN department d ON e.dept_id = d.dept_id
GROUP BY d.dept_name, TO_CHAR(a.att_date, 'YYYY-MM');

-- 视图2:员工工资明细
CREATE OR REPLACE VIEW v_employee_salary AS
SELECT
  e.emp_name,
  d.dept_name,
  p.pos_name,
  s.year,
  s.month,
  s.base_salary,
  s.bonus,
  s.deduction,
  s.total
FROM salary s
JOIN employee e ON s.emp_id = e.emp_id
JOIN department d ON e.dept_id = d.dept_id
JOIN position p ON e.pos_id = p.pos_id;


-- 部门数据插入
-- 插入部门数据
INSERT INTO department (dept_id, dept_name) VALUES (seq_department_id.NEXTVAL, '人力资源部');
INSERT INTO department (dept_id, dept_name) VALUES (seq_department_id.NEXTVAL, '财务部');
INSERT INTO department (dept_id, dept_name) VALUES (seq_department_id.NEXTVAL, '技术开发部');
INSERT INTO department (dept_id, dept_name) VALUES (seq_department_id.NEXTVAL, '市场营销部');
INSERT INTO department (dept_id, dept_name) VALUES (seq_department_id.NEXTVAL, '客户服务部');

-- 职位数据插入
-- 插入职位数据
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '试用员工', 4000, 1);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '正式员工', 6000, 2);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '开发组长', 10000, 3);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '部门经理', 15000, 4);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '总经理', 25000, 5);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '会计', 8000, 2);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '市场专员', 7000, 2);
INSERT INTO position (pos_id, pos_name, base_salary, pos_level) VALUES (seq_position_id.NEXTVAL, '客服主管', 9000, 3);

-- 员工数据插入
-- 插入员工数据
INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '张三', 100, 10, TO_DATE('2020-01-15', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '李四', 100, 13, TO_DATE('2019-05-20', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '王五', 110, 11, TO_DATE('2021-03-10', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '赵六', 110, 15, TO_DATE('2020-11-01', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '钱七', 120, 12, TO_DATE('2022-02-18', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '孙八', 120, 14, TO_DATE('2018-07-22', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '周九', 130, 16, TO_DATE('2021-09-05', 'YYYY-MM-DD'), 1);

INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '吴十', 140, 17, TO_DATE('2022-01-10', 'YYYY-MM-DD'), 1);

-- 插入一个已离职员工
INSERT INTO employee (emp_id, emp_name, dept_id, pos_id, hire_date, status)
VALUES (seq_employee_id.NEXTVAL, '郑十一', 130, 11, TO_DATE('2020-06-15', 'YYYY-MM-DD'), 0);

-- 考勤数据插入
-- 插入考勤数据 (当前月份)
INSERT INTO attendance (att_id, emp_id, att_date, check_in, check_out, att_type)
VALUES (seq_attendance_id.NEXTVAL, 1000, TRUNC(SYSDATE),
        TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE), 'YYYY-MM-DD') || ' 08:45:00', 'YYYY-MM-DD HH24:MI:SS'),
        TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE), 'YYYY-MM-DD') || ' 17:30:00', 'YYYY-MM-DD HH24:MI:SS'),
        '正常');

INSERT INTO attendance (att_id, emp_id, att_date, check_in, check_out, att_type)
VALUES (seq_attendance_id.NEXTVAL, 1001, TRUNC(SYSDATE),
        TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE), 'YYYY-MM-DD') || ' 09:15:00', 'YYYY-MM-DD HH24:MI:SS'),
        TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE), 'YYYY-MM-DD') || ' 18:00:00', 'YYYY-MM-DD HH24:MI:SS'),
        '迟到');

INSERT INTO attendance (att_id, emp_id, att_date, check_in, check_out, att_type)
VALUES (seq_attendance_id.NEXTVAL, 1002, TRUNC(SYSDATE)-1,
        TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE)-1, 'YYYY-MM-DD') || ' 10:30:00', 'YYYY-MM-DD HH24:MI:SS'),
        TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE)-1, 'YYYY-MM-DD') || ' 17:45:00', 'YYYY-MM-DD HH24:MI:SS'),
        '缺勤');

-- 上个月的数据
INSERT INTO attendance (att_id, emp_id, att_date, check_in, check_out, att_type)
VALUES (seq_attendance_id.NEXTVAL, 1000, ADD_MONTHS(TRUNC(SYSDATE), -1),
        TO_TIMESTAMP(TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -1), 'YYYY-MM-DD') || ' 08:50:00', 'YYYY-MM-DD HH24:MI:SS'),
        TO_TIMESTAMP(TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -1), 'YYYY-MM-DD') || ' 17:20:00', 'YYYY-MM-DD HH24:MI:SS'),
        '正常');

INSERT INTO attendance (att_id, emp_id, att_date, check_in, check_out, att_type)
VALUES (seq_attendance_id.NEXTVAL, 1003, ADD_MONTHS(TRUNC(SYSDATE), -1)+1,
        TO_TIMESTAMP(TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -1)+1, 'YYYY-MM-DD') || ' 08:55:00', 'YYYY-MM-DD HH24:MI:SS'),
        TO_TIMESTAMP(TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -1)+1, 'YYYY-MM-DD') || ' 17:40:00', 'YYYY-MM-DD HH24:MI:SS'),
        '正常');

-- 工资数据插入
-- 插入工资数据 (当前月份和上个月)
-- 当前月份
INSERT INTO salary (sal_id, emp_id, year, month, base_salary, bonus, deduction)
VALUES (seq_salary_id.NEXTVAL, 1000, EXTRACT(YEAR FROM SYSDATE), EXTRACT(MONTH FROM SYSDATE), 6000, 500, 0);

INSERT INTO salary (sal_id, emp_id, year, month, base_salary, bonus, deduction)
VALUES (seq_salary_id.NEXTVAL, 1001, EXTRACT(YEAR FROM SYSDATE), EXTRACT(MONTH FROM SYSDATE), 15000, 1000, 0);

INSERT INTO salary (sal_id, emp_id, year, month, base_salary, bonus, deduction)
VALUES (seq_salary_id.NEXTVAL, 1002, EXTRACT(YEAR FROM SYSDATE), EXTRACT(MONTH FROM SYSDATE), 8000, 300, 363.64); -- 8000/22 ≈ 363.64

-- 上个月
INSERT INTO salary (sal_id, emp_id, year, month, base_salary, bonus, deduction)
VALUES (seq_salary_id.NEXTVAL, 1000, EXTRACT(YEAR FROM ADD_MONTHS(SYSDATE, -1)), EXTRACT(MONTH FROM ADD_MONTHS(SYSDATE, -1)), 6000, 300, 0);

INSERT INTO salary (sal_id, emp_id, year, month, base_salary, bonus, deduction)
VALUES (seq_salary_id.NEXTVAL, 1003, EXTRACT(YEAR FROM ADD_MONTHS(SYSDATE, -1)), EXTRACT(MONTH FROM ADD_MONTHS(SYSDATE, -1)), 10000, 500, 0);

 

以下是代码结构

 

一些配置文件

 

 

实体类

  

  

 

 

下面就是部分几层架构的代码了,其他没放上来的全是普通的增删改查,我觉得这些代码还能更简单,但是我懒得改了直接放上来备份。

 

 

 

 

 

  

 

 

posted @ 2025-05-14 17:22  BKYNEKO  阅读(16)  评论(0)    收藏  举报