数据库会话管理器
| 92 | |
| 93 | |
| 94 | class DatabaseSessionManager: |
| 95 | """数据库会话管理器""" |
| 96 | |
| 97 | def __init__(self, database_url: str = None): |
| 98 | if database_url is None: |
| 99 | env_url = os.environ.get("APP_DATABASE_URL") or os.environ.get("DATABASE_URL") |
| 100 | if env_url: |
| 101 | database_url = env_url |
| 102 | else: |
| 103 | # 优先使用 APP_DATA_DIR 环境变量(PyInstaller 打包后由 webui.py 设置) |
| 104 | data_dir = os.environ.get('APP_DATA_DIR') or os.path.join( |
| 105 | os.path.dirname(os.path.dirname(os.path.dirname(__file__))), |
| 106 | 'data' |
| 107 | ) |
| 108 | db_path = os.path.join(data_dir, 'database.db') |
| 109 | # 确保目录存在 |
| 110 | os.makedirs(data_dir, exist_ok=True) |
| 111 | database_url = f"sqlite:///{db_path}" |
| 112 | |
| 113 | self.database_url = _build_sqlalchemy_url(database_url) |
| 114 | self.engine = create_engine( |
| 115 | self.database_url, |
| 116 | **_build_engine_options(self.database_url), |
| 117 | ) |
| 118 | self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self.engine) |
| 119 | |
| 120 | def get_db(self) -> Generator[Session, None, None]: |
| 121 | """ |
| 122 | 获取数据库会话的上下文管理器 |
| 123 | 使用示例: |
| 124 | with get_db() as db: |
| 125 | # 使用 db 进行数据库操作 |
| 126 | pass |
| 127 | """ |
| 128 | db = self.SessionLocal() |
| 129 | try: |
| 130 | yield db |
| 131 | finally: |
| 132 | db.close() |
| 133 | |
| 134 | @contextmanager |
| 135 | def session_scope(self) -> Generator[Session, None, None]: |
| 136 | """ |
| 137 | 事务作用域上下文管理器 |
| 138 | 使用示例: |
| 139 | with session_scope() as session: |
| 140 | # 数据库操作 |
| 141 | pass |
| 142 | """ |
| 143 | session = self.SessionLocal() |
| 144 | try: |
| 145 | yield session |
| 146 | session.commit() |
| 147 | except Exception as e: |
| 148 | session.rollback() |
| 149 | raise e |
| 150 | finally: |
| 151 | session.close() |
no outgoing calls