springbootAI 1.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. spring/__init__.py +66 -0
  2. spring/ai/__init__.py +78 -0
  3. spring/ai/advisors.py +139 -0
  4. spring/ai/annotations.py +74 -0
  5. spring/ai/autoconfig.py +481 -0
  6. spring/ai/core.py +391 -0
  7. spring/ai/etl.py +188 -0
  8. spring/ai/memory.py +109 -0
  9. spring/ai/observability.py +129 -0
  10. spring/ai/providers.py +789 -0
  11. spring/ai/resilience.py +258 -0
  12. spring/ai/tools.py +106 -0
  13. spring/ai/vectorstore.py +303 -0
  14. spring/annotations/__init__.py +188 -0
  15. spring/annotations/cache.py +126 -0
  16. spring/annotations/cloud.py +207 -0
  17. spring/annotations/conditional.py +272 -0
  18. spring/annotations/core.py +864 -0
  19. spring/annotations/messaging.py +107 -0
  20. spring/aop/__init__.py +4 -0
  21. spring/aop/cloud_aop.py +404 -0
  22. spring/aop/comprehensive_aop.py +1015 -0
  23. spring/aop/method_interceptor.py +19 -0
  24. spring/aop/proxy_factory.py +55 -0
  25. spring/cloud/__init__.py +76 -0
  26. spring/cloud/discovery.py +364 -0
  27. spring/cloud/feign.py +469 -0
  28. spring/cloud/gateway.py +452 -0
  29. spring/cloud/load_balancer.py +149 -0
  30. spring/cloud/seata.py +557 -0
  31. spring/cloud/sentinel.py +525 -0
  32. spring/cloud/tracer.py +337 -0
  33. spring/config/__init__.py +21 -0
  34. spring/config/binding.py +206 -0
  35. spring/config/config_loader.py +405 -0
  36. spring/context/__init__.py +13 -0
  37. spring/context/application_context.py +589 -0
  38. spring/context/bean_definition.py +70 -0
  39. spring/context/bean_factory.py +1052 -0
  40. spring/context/registry.py +58 -0
  41. spring/context/scanner.py +106 -0
  42. spring/core/__init__.py +3 -0
  43. spring/core/graceful_shutdown.py +196 -0
  44. spring/core/typing_utils.py +50 -0
  45. spring/csv/__init__.py +52 -0
  46. spring/csv/annotations.py +402 -0
  47. spring/csv/converters.py +69 -0
  48. spring/csv/easy_csv.py +95 -0
  49. spring/csv/exceptions.py +27 -0
  50. spring/csv/reader.py +195 -0
  51. spring/csv/writer.py +155 -0
  52. spring/data/__init__.py +54 -0
  53. spring/data/page.py +181 -0
  54. spring/data/repository.py +274 -0
  55. spring/data/specification.py +228 -0
  56. spring/datasource/__init__.py +66 -0
  57. spring/datasource/annotations.py +133 -0
  58. spring/datasource/context.py +69 -0
  59. spring/datasource/dynamic.py +148 -0
  60. spring/event/__init__.py +7 -0
  61. spring/event/publisher.py +69 -0
  62. spring/excel/__init__.py +51 -0
  63. spring/excel/annotations.py +405 -0
  64. spring/excel/converters.py +231 -0
  65. spring/excel/easy_excel.py +94 -0
  66. spring/excel/exceptions.py +31 -0
  67. spring/excel/reader.py +254 -0
  68. spring/excel/style.py +95 -0
  69. spring/excel/writer.py +197 -0
  70. spring/i18n/__init__.py +97 -0
  71. spring/i18n/accessor.py +94 -0
  72. spring/i18n/auto_config.py +177 -0
  73. spring/i18n/holder.py +106 -0
  74. spring/i18n/locale.py +152 -0
  75. spring/i18n/locale_resolver.py +367 -0
  76. spring/i18n/message_source.py +250 -0
  77. spring/i18n/middleware.py +79 -0
  78. spring/i18n/properties.py +168 -0
  79. spring/i18n/sources.py +255 -0
  80. spring/logging/__init__.py +1 -0
  81. spring/logging/loguru_logger.py +228 -0
  82. spring/main.py +378 -0
  83. spring/messaging/__init__.py +1 -0
  84. spring/messaging/rabbitmq.py +302 -0
  85. spring/monitoring/__init__.py +1 -0
  86. spring/monitoring/prometheus.py +199 -0
  87. spring/orm/__init__.py +258 -0
  88. spring/orm/database.py +222 -0
  89. spring/orm/ddl_auto.py +1217 -0
  90. spring/orm/migration.py +419 -0
  91. spring/orm/mybatis_integration.py +400 -0
  92. spring/orm/pymybatis/__init__.py +86 -0
  93. spring/orm/pymybatis/annotations/__init__.py +30 -0
  94. spring/orm/pymybatis/annotations/annotations.py +332 -0
  95. spring/orm/pymybatis/cache/__init__.py +47 -0
  96. spring/orm/pymybatis/cache/cache.py +371 -0
  97. spring/orm/pymybatis/cache/redis_cache.py +434 -0
  98. spring/orm/pymybatis/circuit_breaker/__init__.py +21 -0
  99. spring/orm/pymybatis/circuit_breaker/circuit_breaker.py +424 -0
  100. spring/orm/pymybatis/configuration.py +525 -0
  101. spring/orm/pymybatis/core/__init__.py +10 -0
  102. spring/orm/pymybatis/core/sql_session.py +1382 -0
  103. spring/orm/pymybatis/core/sql_session_factory.py +76 -0
  104. spring/orm/pymybatis/dialect/__init__.py +9 -0
  105. spring/orm/pymybatis/dialect/dialect.py +445 -0
  106. spring/orm/pymybatis/dynamic_sql/__init__.py +9 -0
  107. spring/orm/pymybatis/dynamic_sql/dynamic_sql.py +900 -0
  108. spring/orm/pymybatis/interceptor/__init__.py +31 -0
  109. spring/orm/pymybatis/interceptor/interceptor.py +427 -0
  110. spring/orm/pymybatis/mapper/__init__.py +9 -0
  111. spring/orm/pymybatis/mapper/mapper.py +540 -0
  112. spring/orm/pymybatis/metrics/__init__.py +41 -0
  113. spring/orm/pymybatis/metrics/metrics.py +595 -0
  114. spring/orm/pymybatis/pool/__init__.py +9 -0
  115. spring/orm/pymybatis/pool/connection_pool.py +711 -0
  116. spring/orm/pymybatis/security/__init__.py +19 -0
  117. spring/orm/pymybatis/security/access_control.py +415 -0
  118. spring/orm/pymybatis/security/password_encoder.py +293 -0
  119. spring/orm/pymybatis/security/sensitive_data_masker.py +326 -0
  120. spring/orm/pymybatis/security/sql_injection_detector.py +675 -0
  121. spring/orm/pymybatis/transaction/__init__.py +9 -0
  122. spring/orm/pymybatis/transaction/transaction.py +288 -0
  123. spring/orm/pymybatis/type_handler/__init__.py +37 -0
  124. spring/orm/pymybatis/type_handler/type_handler.py +473 -0
  125. spring/orm/pymybatis/version.py +9 -0
  126. spring/orm/pymybatis/xml_parser/__init__.py +9 -0
  127. spring/orm/pymybatis/xml_parser/xml_parser.py +761 -0
  128. spring/retry/__init__.py +12 -0
  129. spring/retry/retry_annotations.py +71 -0
  130. spring/retry/retry_decorator.py +155 -0
  131. spring/scheduling/__init__.py +3 -0
  132. spring/scheduling/scheduler.py +389 -0
  133. spring/security/__init__.py +39 -0
  134. spring/security/jwt_utils.py +281 -0
  135. spring/security/replay_protection.py +206 -0
  136. spring/security/secret_manager.py +226 -0
  137. spring/security/security_aop.py +248 -0
  138. spring/security/security_context.py +172 -0
  139. spring/test/__init__.py +45 -0
  140. spring/test/slicing.py +341 -0
  141. spring/tracing/__init__.py +11 -0
  142. spring/tracing/skywalking.py +229 -0
  143. spring/tx/__init__.py +52 -0
  144. spring/tx/events.py +172 -0
  145. spring/tx/synchronization.py +143 -0
  146. spring/utils/__init__.py +5 -0
  147. spring/utils/banner.py +32 -0
  148. spring/utils/logger.py +73 -0
  149. spring/utils/redis_client.py +526 -0
  150. spring/validation/__init__.py +55 -0
  151. spring/validation/aop.py +141 -0
  152. spring/validation/constraints.py +357 -0
  153. spring/validation/exceptions.py +55 -0
  154. spring/validation/validator.py +139 -0
  155. spring/web/__init__.py +12 -0
  156. spring/web/actuator.py +319 -0
  157. spring/web/exception_handler.py +61 -0
  158. spring/web/health.py +399 -0
  159. spring/web/interceptor.py +91 -0
  160. spring/web/result.py +44 -0
  161. spring/web/swagger.py +601 -0
  162. spring/web/web_context.py +755 -0
  163. spring/websocket/__init__.py +86 -0
  164. spring/websocket/annotations.py +169 -0
  165. spring/websocket/broker.py +238 -0
  166. spring/websocket/exceptions.py +26 -0
  167. spring/websocket/handler.py +243 -0
  168. spring/websocket/router.py +526 -0
  169. spring/websocket/session.py +216 -0
  170. springbootai-1.8.0.dist-info/METADATA +2796 -0
  171. springbootai-1.8.0.dist-info/RECORD +175 -0
  172. springbootai-1.8.0.dist-info/WHEEL +5 -0
  173. springbootai-1.8.0.dist-info/entry_points.txt +2 -0
  174. springbootai-1.8.0.dist-info/licenses/LICENSE +7 -0
  175. springbootai-1.8.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,199 @@
1
+ """
2
+ Prometheus监控模块
3
+ 提供指标暴露和采集功能
4
+ """
5
+ from prometheus_client import (
6
+ CollectorRegistry,
7
+ Counter,
8
+ Gauge,
9
+ Histogram,
10
+ Summary,
11
+ generate_latest,
12
+ CONTENT_TYPE_LATEST,
13
+ )
14
+ from prometheus_client.exposition import start_http_server
15
+ import logging
16
+ import os
17
+ import time
18
+
19
+ logger = logging.getLogger("Spring.Monitoring.Prometheus")
20
+
21
+
22
+ class PrometheusMetrics:
23
+ """Prometheus指标管理器"""
24
+
25
+ _instance = None
26
+ _lock = __import__('threading').Lock()
27
+
28
+ def __new__(cls, *args, **kwargs):
29
+ if cls._instance is None:
30
+ with cls._lock:
31
+ if cls._instance is None:
32
+ cls._instance = super().__new__(cls)
33
+ return cls._instance
34
+
35
+ def __init__(self, namespace: str = "spring", subsystem: str = "python"):
36
+ if hasattr(self, '_initialized'):
37
+ return
38
+ self.namespace = namespace
39
+ self.subsystem = subsystem
40
+ self._registry = CollectorRegistry()
41
+ self._metric_registry = self._registry
42
+ if os.getenv('PROMETHEUS_MULTIPROC_DIR'):
43
+ from prometheus_client import multiprocess
44
+ multiprocess.MultiProcessCollector(self._registry)
45
+ # Metrics write their values to multiprocess files and must not also
46
+ # register live collectors in the exposition registry.
47
+ self._metric_registry = None
48
+ self._metrics: dict = {}
49
+ self._initialized = True
50
+
51
+ def configure(self, namespace: str, subsystem: str) -> None:
52
+ if self._metrics and (namespace != self.namespace or subsystem != self.subsystem):
53
+ raise RuntimeError("Prometheus namespace/subsystem cannot change after metrics are created")
54
+ self.namespace = namespace
55
+ self.subsystem = subsystem
56
+
57
+ def create_counter(self, name: str, documentation: str, labelnames: list = None) -> Counter:
58
+ """
59
+ 创建计数器指标
60
+
61
+ Args:
62
+ name: 指标名称
63
+ documentation: 指标描述
64
+ labelnames: 标签名称列表
65
+
66
+ Returns:
67
+ Counter对象
68
+ """
69
+ key = f"{self.namespace}_{self.subsystem}_{name}"
70
+ if key not in self._metrics:
71
+ self._metrics[key] = Counter(
72
+ name=name,
73
+ documentation=documentation,
74
+ labelnames=labelnames or [],
75
+ namespace=self.namespace,
76
+ subsystem=self.subsystem,
77
+ registry=self._metric_registry,
78
+ )
79
+ return self._metrics[key]
80
+
81
+ def create_gauge(self, name: str, documentation: str, labelnames: list = None) -> Gauge:
82
+ """
83
+ 创建仪表盘指标
84
+
85
+ Args:
86
+ name: 指标名称
87
+ documentation: 指标描述
88
+ labelnames: 标签名称列表
89
+
90
+ Returns:
91
+ Gauge对象
92
+ """
93
+ key = f"{self.namespace}_{self.subsystem}_{name}"
94
+ if key not in self._metrics:
95
+ self._metrics[key] = Gauge(
96
+ name=name,
97
+ documentation=documentation,
98
+ labelnames=labelnames or [],
99
+ namespace=self.namespace,
100
+ subsystem=self.subsystem,
101
+ registry=self._metric_registry,
102
+ )
103
+ return self._metrics[key]
104
+
105
+ def create_histogram(self, name: str, documentation: str, labelnames: list = None,
106
+ buckets: list = None) -> Histogram:
107
+ """
108
+ 创建直方图指标
109
+
110
+ Args:
111
+ name: 指标名称
112
+ documentation: 指标描述
113
+ labelnames: 标签名称列表
114
+ buckets: 桶边界列表
115
+
116
+ Returns:
117
+ Histogram对象
118
+ """
119
+ key = f"{self.namespace}_{self.subsystem}_{name}"
120
+ if key not in self._metrics:
121
+ self._metrics[key] = Histogram(
122
+ name=name,
123
+ documentation=documentation,
124
+ labelnames=labelnames or [],
125
+ buckets=buckets or Histogram.DEFAULT_BUCKETS,
126
+ namespace=self.namespace,
127
+ subsystem=self.subsystem,
128
+ registry=self._metric_registry,
129
+ )
130
+ return self._metrics[key]
131
+
132
+ def create_summary(self, name: str, documentation: str, labelnames: list = None,
133
+ objectives: dict = None) -> Summary:
134
+ """
135
+ 创建摘要指标
136
+
137
+ Args:
138
+ name: 指标名称
139
+ documentation: 指标描述
140
+ labelnames: 标签名称列表
141
+ objectives: 分位数目标
142
+
143
+ Returns:
144
+ Summary对象
145
+ """
146
+ key = f"{self.namespace}_{self.subsystem}_{name}"
147
+ if key not in self._metrics:
148
+ self._metrics[key] = Summary(
149
+ name=name,
150
+ documentation=documentation,
151
+ labelnames=labelnames or [],
152
+ objectives=objectives or Summary.DEFAULT_OBJECTIVES,
153
+ namespace=self.namespace,
154
+ subsystem=self.subsystem,
155
+ registry=self._metric_registry,
156
+ )
157
+ return self._metrics[key]
158
+
159
+ def get_metrics(self) -> dict:
160
+ """获取所有指标"""
161
+ return self._metrics
162
+
163
+ def get_registry(self) -> CollectorRegistry:
164
+ """获取指标注册表"""
165
+ return self._registry
166
+
167
+ def generate_metrics_data(self) -> bytes:
168
+ """生成Prometheus格式的指标数据"""
169
+ return generate_latest(self._registry)
170
+
171
+ def start_server(self, port: int = 8000):
172
+ """
173
+ 启动Prometheus指标暴露HTTP服务器
174
+
175
+ Args:
176
+ port: 监听端口
177
+ """
178
+ start_http_server(port, registry=self._registry)
179
+ logger.info(f"Prometheus metrics server started on port {port}")
180
+
181
+
182
+ # 创建全局Prometheus指标管理器实例
183
+ prometheus_metrics = PrometheusMetrics()
184
+
185
+
186
+ def init_prometheus(config: dict) -> None:
187
+ """
188
+ 初始化Prometheus配置
189
+
190
+ Args:
191
+ config: 配置字典,包含namespace, subsystem, port等
192
+ """
193
+ prometheus_metrics.configure(
194
+ namespace=config.get('namespace', 'spring'),
195
+ subsystem=config.get('subsystem', 'python'),
196
+ )
197
+ # 默认通过主应用 /actuator/prometheus 暴露,避免多 worker 争抢端口。
198
+ if config.get('standalone_server', False):
199
+ prometheus_metrics.start_server(config.get('port', 8000))
spring/orm/__init__.py ADDED
@@ -0,0 +1,258 @@
1
+ """
2
+ Spring ORM模块
3
+ 集成PyMyBatis作为核心ORM框架
4
+ 提供SQL与代码分离、事务管理、连接池等企业级数据库能力
5
+
6
+ 支持两种数据访问模式:
7
+ 1. Mapper模式(推荐):使用@Mapper注解和SQL注解定义数据访问接口
8
+ 2. Repository模式:使用SQLAlchemy的ORM方式进行数据访问
9
+ """
10
+
11
+ # 导入SQLAlchemy数据库管理器(可选)
12
+ try:
13
+ from spring.orm.database import (
14
+ DatabaseManager,
15
+ Base,
16
+ BaseEntity,
17
+ User,
18
+ AuditLog,
19
+ init_database,
20
+ )
21
+ except ImportError:
22
+ # SQLAlchemy未安装,这些类不可用
23
+ DatabaseManager = None
24
+ Base = None
25
+ BaseEntity = None
26
+ User = None
27
+ AuditLog = None
28
+ init_database = None
29
+
30
+ # 从pymybatis导入核心类
31
+ from spring.orm.pymybatis import (
32
+ Configuration,
33
+ build_session_factory,
34
+ SqlSessionFactory,
35
+ SqlSession,
36
+ )
37
+
38
+ # 导入Spring与MyBatis集成注解和工具
39
+ from spring.orm.mybatis_integration import (
40
+ Mapper,
41
+ MapperScan,
42
+ MyBatisConfigurer,
43
+ init_mybatis,
44
+ )
45
+
46
+ # 导入注解
47
+ from spring.orm.pymybatis.annotations import (
48
+ Select,
49
+ Insert,
50
+ Update,
51
+ Delete,
52
+ SelectProvider,
53
+ InsertProvider,
54
+ UpdateProvider,
55
+ DeleteProvider,
56
+ ResultMap,
57
+ Result,
58
+ Options,
59
+ Param,
60
+ CacheNamespace,
61
+ DataSource,
62
+ Transactional as MapperTransactional,
63
+ )
64
+
65
+ # 导入安全模块
66
+ from spring.orm.pymybatis.security import (
67
+ SensitiveDataMasker,
68
+ PasswordEncoder,
69
+ SQLInjectionDetector,
70
+ RoleBasedAccessControl,
71
+ RowLevelAccessControl,
72
+ )
73
+
74
+ # 导入缓存模块
75
+ from spring.orm.pymybatis.cache import (
76
+ LRUCache,
77
+ SecondLevelCache,
78
+ )
79
+
80
+ # 导入事务模块
81
+ from spring.orm.pymybatis.transaction import (
82
+ TransactionIsolationLevel,
83
+ )
84
+
85
+ # 导入拦截器模块
86
+ from spring.orm.pymybatis.interceptor import (
87
+ Interceptor,
88
+ LogInterceptor,
89
+ PerformanceInterceptor,
90
+ SecurityInterceptor,
91
+ )
92
+
93
+ # 导入类型处理器
94
+ from spring.orm.pymybatis.type_handler import (
95
+ TypeHandler,
96
+ )
97
+
98
+ # 导入数据库方言
99
+ from spring.orm.pymybatis.dialect import (
100
+ Dialect,
101
+ get_dialect,
102
+ )
103
+
104
+ # 导入连接池
105
+ from spring.orm.pymybatis.pool import (
106
+ create_connection_pool,
107
+ )
108
+
109
+ # 导入动态SQL处理器
110
+ from spring.orm.pymybatis.dynamic_sql import (
111
+ DynamicSQLProcessor,
112
+ )
113
+
114
+ # 导入XML解析器
115
+ from spring.orm.pymybatis.xml_parser import (
116
+ XmlParser,
117
+ )
118
+
119
+ # 导入熔断器
120
+ from spring.orm.pymybatis.circuit_breaker import (
121
+ CircuitBreaker,
122
+ )
123
+
124
+ # 导入指标监控
125
+ from spring.orm.pymybatis.metrics import (
126
+ MetricsCollector,
127
+ )
128
+
129
+ # 导入数据库迁移(Flyway风格)
130
+ from spring.orm.migration import (
131
+ MigrationManager,
132
+ MigrationError,
133
+ MigrationState,
134
+ )
135
+
136
+ # 导入DDL自动建表(JPA hibernate.ddl-auto风格)
137
+ from spring.orm.ddl_auto import (
138
+ DdlAutoManager,
139
+ DdlAutoMode,
140
+ EntityTable,
141
+ Table,
142
+ Column,
143
+ Id,
144
+ Version,
145
+ Transient,
146
+ Index,
147
+ entity,
148
+ table as table_decorator,
149
+ column as column_decorator,
150
+ id_column as id_column_decorator,
151
+ version_column,
152
+ version_column as version_column_decorator,
153
+ transient_field,
154
+ transient_field as transient_field_decorator,
155
+ init_ddl_auto,
156
+ get_ddl_manager,
157
+ OptimisticLockExecutor,
158
+ OptimisticLockError,
159
+ )
160
+
161
+ # 版本信息
162
+ from spring.orm.pymybatis.version import __version__
163
+
164
+ __all__ = [
165
+ # SQLAlchemy数据库管理器
166
+ 'DatabaseManager',
167
+ 'Base',
168
+ 'BaseEntity',
169
+ 'User',
170
+ 'AuditLog',
171
+ 'init_database',
172
+ # PyMyBatis核心类
173
+ 'Configuration',
174
+ 'build_session_factory',
175
+ 'SqlSessionFactory',
176
+ 'SqlSession',
177
+ # Spring集成注解
178
+ 'Mapper',
179
+ 'MapperScan',
180
+ 'MyBatisConfigurer',
181
+ 'init_mybatis',
182
+ # 注解
183
+ 'Select',
184
+ 'Insert',
185
+ 'Update',
186
+ 'Delete',
187
+ 'SelectProvider',
188
+ 'InsertProvider',
189
+ 'UpdateProvider',
190
+ 'DeleteProvider',
191
+ 'ResultMap',
192
+ 'Result',
193
+ 'Options',
194
+ 'Param',
195
+ 'CacheNamespace',
196
+ 'DataSource',
197
+ 'MapperTransactional',
198
+ # 安全模块
199
+ 'SensitiveDataMasker',
200
+ 'PasswordEncoder',
201
+ 'SQLInjectionDetector',
202
+ 'RoleBasedAccessControl',
203
+ 'RowLevelAccessControl',
204
+ # 缓存模块
205
+ 'LRUCache',
206
+ 'SecondLevelCache',
207
+ # 事务模块
208
+ 'TransactionIsolationLevel',
209
+ # 拦截器模块
210
+ 'Interceptor',
211
+ 'LogInterceptor',
212
+ 'PerformanceInterceptor',
213
+ 'SecurityInterceptor',
214
+ # 类型处理器
215
+ 'TypeHandler',
216
+ # 数据库方言
217
+ 'Dialect',
218
+ 'get_dialect',
219
+ # 连接池
220
+ 'create_connection_pool',
221
+ # 动态SQL
222
+ 'DynamicSQLProcessor',
223
+ # XML解析器
224
+ 'XmlParser',
225
+ # 熔断器
226
+ 'CircuitBreaker',
227
+ # 指标监控
228
+ 'MetricsCollector',
229
+ # 数据库迁移
230
+ 'MigrationManager',
231
+ 'MigrationError',
232
+ 'MigrationState',
233
+ # DDL自动建表
234
+ 'DdlAutoManager',
235
+ 'DdlAutoMode',
236
+ 'EntityTable',
237
+ 'Table',
238
+ 'Column',
239
+ 'Id',
240
+ 'Version',
241
+ 'Transient',
242
+ 'Index',
243
+ 'entity',
244
+ 'table_decorator',
245
+ 'column_decorator',
246
+ 'id_column_decorator',
247
+ 'version_column',
248
+ 'version_column_decorator',
249
+ 'transient_field',
250
+ 'transient_field_decorator',
251
+ 'init_ddl_auto',
252
+ 'get_ddl_manager',
253
+ # JPA @Version 乐观锁执行器
254
+ 'OptimisticLockExecutor',
255
+ 'OptimisticLockError',
256
+ # 版本
257
+ '__version__',
258
+ ]
spring/orm/database.py ADDED
@@ -0,0 +1,222 @@
1
+ """
2
+ 数据库ORM模块
3
+ 集成SQLAlchemy实现企业级数据库操作
4
+ """
5
+ from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime, Boolean, Text, ForeignKey
6
+ from sqlalchemy.orm import declarative_base, sessionmaker, Session, relationship, scoped_session
7
+ from sqlalchemy.exc import SQLAlchemyError
8
+ from datetime import datetime
9
+ import logging
10
+
11
+ logger = logging.getLogger("Spring.ORM")
12
+
13
+ # 创建Base类
14
+ Base = declarative_base()
15
+
16
+
17
+ class DatabaseManager:
18
+ """数据库管理器"""
19
+
20
+ _instance = None
21
+ _lock = __import__('threading').Lock()
22
+
23
+ def __new__(cls, *args, **kwargs):
24
+ if cls._instance is None:
25
+ with cls._lock:
26
+ if cls._instance is None:
27
+ cls._instance = super().__new__(cls)
28
+ return cls._instance
29
+
30
+ def __init__(self, db_url: str = "sqlite:///./test.db", echo: bool = False):
31
+ if hasattr(self, '_initialized'):
32
+ return
33
+ self.db_url = db_url
34
+ self.echo = echo
35
+ self._engine = None
36
+ self._session_factory = None
37
+ self._scoped_session = None
38
+ self._initialized = True
39
+
40
+ def connect(self) -> None:
41
+ """连接数据库"""
42
+ try:
43
+ self._engine = create_engine(self.db_url, echo=self.echo)
44
+
45
+ # 创建Session工厂
46
+ self._session_factory = sessionmaker(
47
+ bind=self._engine,
48
+ autocommit=False,
49
+ autoflush=False,
50
+ )
51
+
52
+ # 创建线程安全的Scoped Session
53
+ self._scoped_session = scoped_session(self._session_factory)
54
+
55
+ logger.info(f"Connected to database: {self.db_url}")
56
+ except Exception as e:
57
+ logger.error(f"Failed to connect to database: {e}")
58
+ raise
59
+
60
+ def get_engine(self):
61
+ """获取数据库引擎"""
62
+ if self._engine is None:
63
+ self.connect()
64
+ return self._engine
65
+
66
+ def get_session(self) -> Session:
67
+ """获取数据库会话"""
68
+ if self._scoped_session is None:
69
+ self.connect()
70
+ return self._scoped_session()
71
+
72
+ def create_all(self):
73
+ """创建所有表"""
74
+ engine = self.get_engine()
75
+ Base.metadata.create_all(engine)
76
+ logger.info("All tables created")
77
+
78
+ def drop_all(self):
79
+ """删除所有表"""
80
+ engine = self.get_engine()
81
+ Base.metadata.drop_all(engine)
82
+ logger.info("All tables dropped")
83
+
84
+ def execute(self, statement, *args, **kwargs):
85
+ """执行SQL语句"""
86
+ session = self.get_session()
87
+ try:
88
+ result = session.execute(statement, *args, **kwargs)
89
+ session.commit()
90
+ return result
91
+ except SQLAlchemyError as e:
92
+ session.rollback()
93
+ logger.error(f"SQL execution failed: {e}")
94
+ raise
95
+ finally:
96
+ session.close()
97
+
98
+ def insert(self, model):
99
+ """插入数据"""
100
+ session = self.get_session()
101
+ try:
102
+ session.add(model)
103
+ session.commit()
104
+ session.refresh(model)
105
+ return model
106
+ except SQLAlchemyError as e:
107
+ session.rollback()
108
+ logger.error(f"Insert failed: {e}")
109
+ raise
110
+ finally:
111
+ session.close()
112
+
113
+ def update(self, model):
114
+ """更新数据"""
115
+ session = self.get_session()
116
+ try:
117
+ # 使用merge处理脱管对象
118
+ merged_model = session.merge(model)
119
+ session.commit()
120
+ session.refresh(merged_model)
121
+ # 更新原始对象的属性
122
+ for attr in ['id', 'created_at', 'updated_at'] + [c.name for c in model.__table__.columns]:
123
+ if hasattr(merged_model, attr):
124
+ setattr(model, attr, getattr(merged_model, attr))
125
+ return model
126
+ except SQLAlchemyError as e:
127
+ session.rollback()
128
+ logger.error(f"Update failed: {e}")
129
+ raise
130
+ finally:
131
+ session.close()
132
+
133
+ def delete(self, model):
134
+ """删除数据"""
135
+ session = self.get_session()
136
+ try:
137
+ session.delete(model)
138
+ session.commit()
139
+ except SQLAlchemyError as e:
140
+ session.rollback()
141
+ logger.error(f"Delete failed: {e}")
142
+ raise
143
+ finally:
144
+ session.close()
145
+
146
+ def query(self, model):
147
+ """创建查询对象"""
148
+ session = self.get_session()
149
+ return session.query(model)
150
+
151
+ def flush(self):
152
+ """刷新会话"""
153
+ session = self.get_session()
154
+ session.flush()
155
+
156
+ def commit(self):
157
+ """提交事务"""
158
+ session = self.get_session()
159
+ session.commit()
160
+
161
+ def rollback(self):
162
+ """回滚事务"""
163
+ session = self.get_session()
164
+ session.rollback()
165
+
166
+
167
+ # 创建全局数据库管理器实例
168
+ db_manager = DatabaseManager()
169
+
170
+
171
+ def init_database(config: dict) -> None:
172
+ """
173
+ 初始化数据库配置
174
+
175
+ Args:
176
+ config: 配置字典,包含url, echo等
177
+ """
178
+ global db_manager
179
+ db_manager = DatabaseManager(
180
+ db_url=config.get('url', 'sqlite:///./test.db'),
181
+ echo=config.get('echo', False)
182
+ )
183
+ db_manager.connect()
184
+
185
+ # 创建所有表
186
+ db_manager.create_all()
187
+
188
+
189
+ # ==================== 基础实体类 ====================
190
+
191
+ class BaseEntity(Base):
192
+ """基础实体类"""
193
+ __abstract__ = True
194
+
195
+ id = Column(Integer, primary_key=True, autoincrement=True)
196
+ created_at = Column(DateTime, default=datetime.now, nullable=False)
197
+ updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now, nullable=False)
198
+ deleted = Column(Boolean, default=False, nullable=False)
199
+
200
+
201
+ class User(BaseEntity):
202
+ """用户实体"""
203
+ __tablename__ = 'users'
204
+
205
+ username = Column(String(50), unique=True, nullable=False)
206
+ password = Column(String(255), nullable=False)
207
+ email = Column(String(100), unique=True, nullable=False)
208
+ phone = Column(String(20))
209
+ role = Column(String(50), default='USER')
210
+ status = Column(Integer, default=1)
211
+
212
+
213
+ class AuditLog(BaseEntity):
214
+ """审计日志实体"""
215
+ __tablename__ = 'audit_logs'
216
+
217
+ action = Column(String(100), nullable=False)
218
+ target = Column(String(200))
219
+ detail = Column(Text)
220
+ operator = Column(String(100))
221
+ status = Column(String(20), default='SUCCESS')
222
+ duration = Column(Float)