使用装饰器封装类内函数:数据库类重复会话操作优化问询
这问题我之前做数据库封装的时候也碰到过!用装饰器抽离重复的会话管理逻辑绝对是最干净的解决方案,既符合DRY原则,又能让业务方法只专注于核心逻辑。我给你写个具体的实现方案:
第一步:实现会话管理装饰器
这个装饰器会帮你完成会话创建、事务提交/回滚、会话关闭这整套重复操作,还会处理异常情况:
from functools import wraps from sqlalchemy.orm import sessionmaker def session_managed(func): @wraps(func) # 保留原函数的元信息(比如函数名、文档字符串) def wrapper(self, *args, **kwargs): # 创建会话实例 Session = sessionmaker(bind=self.engine) session = Session() try: # 把会话传递给原方法,让业务逻辑直接使用这个会话 result = func(self, session, *args, **kwargs) # 操作成功则提交事务 session.commit() return result except Exception as e: # 出现异常就回滚事务,避免脏数据 session.rollback() raise e # 把异常抛出去,让调用者可以捕获处理 finally: # 不管成功失败,最后都关闭会话 session.close() return wrapper
第二步:改造你的数据库管理类
把原来每个方法里的会话创建/提交/关闭代码删掉,用装饰器标记需要会话管理的方法,并且让方法接收装饰器传入的session参数:
from sqlalchemy import create_engine # 假设你已经定义了User映射类 from your_models import User class UserDatabaseManager(object): DEFAULT_DB_PATH = 'test.db' def __init__(self, dbpath=DEFAULT_DB_PATH): dbpath = 'sqlite:///' + dbpath self.engine = create_engine(dbpath, echo=True) @session_managed def add_user(self, session, username, password): # 只专注于业务逻辑:创建用户并添加到会话 new_user = User(username=username, password=password) session.add(new_user) @session_managed def get_user(self, session, username): # 同样只写查询逻辑 return session.query(User).filter_by(username=username).first() @session_managed def delete_user(self, session, username): user = session.query(User).filter_by(username=username).first() if user: session.delete(user)
额外说明
- 为什么要加
@wraps(func)?这样可以保留原方法的名称、文档字符串等元信息,方便调试和使用help()函数。 - 异常处理很关键:
try-except-finally确保了不管操作成功还是失败,会话都会被正确关闭,异常时还会回滚事务,避免数据库出现不一致的状态。 - 如果不想修改方法参数,也可以通过临时属性注入会话(比如
self._temp_session = session),但直接传参数的方式更清晰,也更符合函数式编程的风格。
内容的提问来源于stack exchange,提问作者Katie
相关产品推荐
相关产品推荐

