# 导入 SQLAlchemy 的 Session 类,用于类型提示 from sqlalchemy.orm import Session # 导入学生信息模型和性别枚举 from model.student_info_region_model import Student_info, GenderEnum # 导入完整性错误异常,用于捕获外键/唯一约束等数据库错误 from sqlalchemy.exc import IntegrityError # ==================== 条件查询学生信息 ==================== def get_part_student_info(session: Session, student_id: str, student_name: str, gender: str): """ 根据学号、姓名、性别查询学生信息(均为可选条件)。 :param session: 数据库会话 :param student_id: 学号,精确匹配 :param student_name: 姓名,精确匹配 :param gender: 性别,前端传“男/女”,内部转为“1/0” :return: 学生对象列表 """ # 前端传来的性别为 男/女,与数据库的枚举值('0'/'1')不符,需要转换 # 注意:若 gender 为 None(不筛选),此处会被错误地转为 '0',导致只查女生。 # 建议调用方在不需要筛选性别时不要传该参数,或修改此段逻辑。 if gender == '男': gender = '1' else: gender = '0' try: # 创建基础查询 query = session.query(Student_info) # 过滤逻辑删除:只查询未删除的记录(is_deleted = '0') query = query.filter(Student_info.is_deleted == '0') # 如果传入学号,则按学号精确过滤 if student_id is not None: query = query.filter(Student_info.student_id == student_id) # 如果传入姓名,则按姓名精确过滤 # 若需模糊查询,可将 == 改为 like(f"%{student_name}%") if student_name is not None: query = query.filter(Student_info.student_name == student_name) # 如果传入性别,则按性别过滤(已转为 '0'/'1',再转为枚举) if gender is not None: # 把字符串转成枚举,SQLAlchemy 才能正确比较 query = query.filter(Student_info.gender == GenderEnum(gender)) # 返回所有匹配记录 return query.all() except Exception as e: # 出现异常直接向上抛出,由 API 层统一处理 raise e # ==================== 添加学生信息 ==================== def add_student_info(session: Session, data: dict): """ 新增一条学生记录。 :param session: 数据库会话 :param data: 学生信息字典,键需与模型字段对应 :return: 成功时返回字符串 '添加成功' """ try: # 先检查学号是否已存在 rows = session.query(Student_info).filter( Student_info.student_id == data['student_id'] ).first() # 如果已存在,返回 ValueError 类(注意:这里返回的是类,不是实例,也不是抛出异常) # 调用方如果做 `if not res` 判断,ValueError 类是真值,可能导致逻辑错误。 # 建议改为 `raise ValueError("学号已存在")` if rows is not None: return ValueError # 根据字典创建 ORM 对象 obj = Student_info(**data) session.add(obj) # 加入会话 session.commit() # 提交事务,写入数据库 return '添加成功' except Exception as e: # 出现异常时回滚事务,避免脏数据 session.rollback() raise e # ==================== 修改学生信息 ==================== def update_student_info(session: Session, data: dict): """ 根据学号更新学生信息(全量更新)。 :param session: 数据库会话 :param data: 包含 student_id 及待更新字段的字典 :return: 成功返回 '修改成功';未找到记录返回 None """ try: # 使用 query.update() 批量更新,返回受影响行数 rows = session.query(Student_info).filter( Student_info.student_id == data['student_id'] ).update(data) # 如果受影响行数为 0,说明学号不存在,无记录可更新 if rows == 0: return None session.commit() return '修改成功' except IntegrityError as e: # 捕获数据库完整性错误(外键、唯一约束等),回滚并翻译为友好提示 session.rollback() err_msg = str(e.orig) # 获取底层 MySQL 错误信息 if 'fk_student_region' in err_msg: # 外键 fk_student_region 失败:region_id 在地区表中不存在 raise ValueError( f"region_id '{data.get('region_id')}' 在地区表中不存在,请先维护 region_dimension" ) elif 'id_card' in err_msg: # 身份证号唯一约束冲突 raise ValueError(f"身份证号 '{data.get('id_card')}' 已被其他学生占用") else: # 其他完整性错误 raise ValueError(f"数据完整性错误: {err_msg}") except Exception as e: # 其他异常同样回滚并抛出 session.rollback() raise e # ==================== 删除学生信息(逻辑删除) ==================== def delete_student_info(session: Session, student_id: str): """ 根据学号进行逻辑删除(将 is_deleted 置为 '1')。 :param session: 数据库会话 :param student_id: 学号 :return: 成功返回 '修改成功';未找到记录返回 None """ try: # 使用 update 将 is_deleted 改为 '1',实现逻辑删除 rows = session.query(Student_info).filter( Student_info.student_id == student_id ).update({'is_deleted': '1'}) # 没有匹配记录,返回 None if rows == 0: return None session.commit() return '修改成功' except Exception as e: # 异常时回滚 session.rollback() raise e