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,400 @@
1
+ """
2
+ Spring与MyBatis集成模块
3
+ 提供@MapperScan、@Mapper等注解,实现Mapper自动注册到Spring容器
4
+ """
5
+ from typing import Optional, List, Dict, Any, Type
6
+ import os
7
+ import sys
8
+ import inspect
9
+ import logging
10
+ from contextlib import contextmanager
11
+ from contextvars import ContextVar
12
+ from spring.annotations.core import SpringAnnotation
13
+ from spring.context.bean_factory import BeanFactory
14
+ from spring.context.bean_definition import BeanDefinition
15
+ from spring.config.config_loader import ConfigLoader
16
+ from spring.orm.pymybatis import build_session_factory, SqlSessionFactory, SqlSession
17
+
18
+ logger = logging.getLogger("Spring.MyBatis")
19
+ _transaction_session: ContextVar[Optional[SqlSession]] = ContextVar(
20
+ 'spring_mybatis_transaction_session', default=None
21
+ )
22
+
23
+
24
+ def get_transaction_session() -> Optional[SqlSession]:
25
+ return _transaction_session.get()
26
+
27
+
28
+ @contextmanager
29
+ def mybatis_transaction(session_factory: SqlSessionFactory, propagation: str = 'REQUIRED'):
30
+ """Bind one ``SqlSession`` to the current execution context.
31
+
32
+ The propagation names intentionally follow Spring's transaction contract.
33
+ ``REQUIRES_NEW`` gets a separate session/connection while the outer
34
+ context is suspended. ``NOT_SUPPORTED`` runs without a bound session so
35
+ mapper calls use their normal short-lived, auto-commit session.
36
+ """
37
+ normalized = str(propagation or 'REQUIRED').upper()
38
+ supported = {
39
+ 'REQUIRED', 'REQUIRES_NEW', 'NESTED', 'SUPPORTS',
40
+ 'MANDATORY', 'NOT_SUPPORTED', 'NEVER',
41
+ }
42
+ if normalized not in supported:
43
+ raise ValueError(
44
+ f"不支持的事务传播级别: {propagation}; 可选: {', '.join(sorted(supported))}"
45
+ )
46
+
47
+ existing_session = get_transaction_session()
48
+ if normalized == 'NEVER':
49
+ if existing_session is not None and existing_session.in_transaction:
50
+ raise RuntimeError("事务传播 NEVER 要求当前不存在活动事务")
51
+ yield None
52
+ return
53
+
54
+ if normalized == 'MANDATORY' and (
55
+ existing_session is None or not existing_session.in_transaction
56
+ ):
57
+ raise RuntimeError("事务传播 MANDATORY 要求当前已存在活动事务")
58
+
59
+ if normalized in {'SUPPORTS', 'NOT_SUPPORTED'}:
60
+ if normalized == 'SUPPORTS' and existing_session is not None:
61
+ yield existing_session
62
+ return
63
+ # Suspend the outer connection while mapper calls create their normal
64
+ # short-lived auto-commit sessions. This avoids accidentally running
65
+ # NOT_SUPPORTED work on the outer transaction.
66
+ if existing_session is not None and normalized == 'NOT_SUPPORTED':
67
+ with existing_session._suspended_transaction():
68
+ token = _transaction_session.set(None)
69
+ try:
70
+ yield None
71
+ finally:
72
+ _transaction_session.reset(token)
73
+ return
74
+ yield None
75
+ return
76
+
77
+ if normalized == 'REQUIRED' and existing_session is not None:
78
+ with existing_session.transaction(propagation='REQUIRED'):
79
+ yield existing_session
80
+ return
81
+
82
+ if normalized == 'NESTED' and existing_session is not None:
83
+ with existing_session.transaction(propagation='NESTED'):
84
+ yield existing_session
85
+ return
86
+
87
+ # REQUIRES_NEW always creates a new physical session. The outer session
88
+ # remains open and is restored after the inner boundary completes.
89
+ if normalized == 'REQUIRES_NEW':
90
+ with session_factory.open_session() as session:
91
+ token = _transaction_session.set(session)
92
+ try:
93
+ with session.transaction(propagation='REQUIRED'):
94
+ yield session
95
+ finally:
96
+ _transaction_session.reset(token)
97
+ return
98
+
99
+ # REQUIRED with no existing session starts the physical transaction.
100
+ if existing_session is not None:
101
+ raise RuntimeError(f"无法建立事务传播上下文: {normalized}")
102
+
103
+ with session_factory.open_session() as session:
104
+ token = _transaction_session.set(session)
105
+ try:
106
+ with session.transaction(propagation='REQUIRED'):
107
+ yield session
108
+ finally:
109
+ _transaction_session.reset(token)
110
+
111
+
112
+ class ManagedMapperProxy:
113
+ """为每次Mapper调用创建并关闭Session,避免跨请求共享会话状态。"""
114
+
115
+ def __init__(self, session_factory: SqlSessionFactory, mapper_class: Type):
116
+ self._session_factory = session_factory
117
+ self._mapper_class = mapper_class
118
+
119
+ def __getattr__(self, name: str):
120
+ mapper_method = getattr(self._mapper_class, name, None)
121
+ if mapper_method is None or not callable(mapper_method):
122
+ raise AttributeError(f"Mapper {self._mapper_class.__name__} 没有方法: {name}")
123
+
124
+ def invoke(*args, **kwargs):
125
+ transaction_session = get_transaction_session()
126
+ if transaction_session is not None:
127
+ mapper = transaction_session.get_mapper(self._mapper_class)
128
+ return getattr(mapper, name)(*args, **kwargs)
129
+ with self._session_factory.open_session() as session:
130
+ mapper = session.get_mapper(self._mapper_class)
131
+ return getattr(mapper, name)(*args, **kwargs)
132
+
133
+ return invoke
134
+
135
+
136
+ class Mapper(SpringAnnotation):
137
+ """
138
+ Mapper接口注解
139
+ 标识一个类为MyBatis Mapper接口
140
+
141
+ 使用示例:
142
+ @Mapper
143
+ class UserMapper:
144
+ @Select("SELECT * FROM users WHERE id = #{id}")
145
+ def find_by_id(self, id):
146
+ pass
147
+ """
148
+ _annotation_type = "mapper"
149
+
150
+ def __init__(self, value: str = ""):
151
+ super().__init__(value=value)
152
+
153
+
154
+ class MapperScan(SpringAnnotation):
155
+ """
156
+ Mapper扫描注解
157
+ 指定要扫描的Mapper包路径
158
+
159
+ 使用示例:
160
+ @SpringBootApplication
161
+ @MapperScan(base_packages=["example.mappers"])
162
+ class Application:
163
+ pass
164
+ """
165
+ _annotation_type = "mapper_scan"
166
+
167
+ def __init__(self, base_packages: Optional[List[str]] = None):
168
+ super().__init__(base_packages=base_packages or [])
169
+
170
+
171
+ class MyBatisConfigurer:
172
+ """
173
+ MyBatis配置器
174
+ 负责初始化SqlSessionFactory和注册Mapper Bean
175
+ """
176
+
177
+ def __init__(self, config_loader: ConfigLoader):
178
+ self.config_loader = config_loader
179
+ self.sql_session_factory: Optional[SqlSessionFactory] = None
180
+ self._mapper_registry: Dict[str, Type] = {}
181
+
182
+ def init(self, application_context) -> None:
183
+ """
184
+ 初始化MyBatis
185
+ """
186
+ # 1. 获取数据库配置
187
+ db_config = self.config_loader.get_config().get('database', {})
188
+ orm_mode = str(db_config.get('orm', 'mybatis')).lower()
189
+ if not db_config.get('enabled', False) or orm_mode not in {'mybatis', 'both'}:
190
+ return
191
+
192
+ # 2. 构建配置字典,传递给build_session_factory
193
+ datasource_config = {
194
+ 'driver': db_config.get('driver', 'sqlite'),
195
+ 'host': db_config.get('host', 'localhost'),
196
+ 'port': db_config.get('port', 3306),
197
+ 'database': db_config.get('database', 'test'),
198
+ 'username': db_config.get('username', ''),
199
+ 'password': db_config.get('password', ''),
200
+ }
201
+
202
+ # 设置安全配置
203
+ security_config = dict(db_config.get('security', {}))
204
+ if 'ddl_block_enabled' in security_config and 'block_ddl' not in security_config:
205
+ security_config['block_ddl'] = security_config.pop('ddl_block_enabled')
206
+
207
+ # 设置缓存配置
208
+ cache_config = db_config.get('cache', {})
209
+
210
+ # 3. 构建SqlSessionFactory(内部会调用Configuration.load_config)
211
+ pool_config = {
212
+ 'min_size': db_config.get('min_size', 5),
213
+ 'max_size': db_config.get('max_size', 20),
214
+ 'max_idle': db_config.get('max_idle', 3600),
215
+ 'wait_timeout': db_config.get('wait_timeout', 30),
216
+ 'validation_interval': db_config.get('validation_interval', 300),
217
+ 'leak_detection_enabled': db_config.get('leak_detection_enabled', True),
218
+ 'leak_timeout': db_config.get('leak_timeout', 300),
219
+ 'circuit_breaker': db_config.get('circuit_breaker', {}),
220
+ }
221
+
222
+ mybatis_config = {
223
+ 'datasource': datasource_config,
224
+ 'pool': pool_config,
225
+ 'security': security_config,
226
+ 'cache': cache_config,
227
+ 'transaction': db_config.get('transaction', {}),
228
+ 'batch': db_config.get('batch', {}),
229
+ }
230
+ mapper_locations = db_config.get('mapper_locations') or db_config.get('mapper_paths')
231
+ if mapper_locations:
232
+ mybatis_config['mapper_locations'] = mapper_locations
233
+
234
+ self.sql_session_factory = build_session_factory(mybatis_config)
235
+
236
+ # 4. 初始化DDL自动建表(JPA hibernate.ddl-auto风格)
237
+ self._init_ddl_auto(db_config)
238
+
239
+ # 5. 扫描并注册Mapper
240
+ self._scan_mappers(application_context)
241
+
242
+ # 6. 注册SqlSessionFactory和SqlSession为Bean
243
+ self._register_beans(application_context.bean_factory)
244
+
245
+ def _init_ddl_auto(self, db_config: dict) -> None:
246
+ """初始化DDL自动建表"""
247
+ try:
248
+ from spring.orm.ddl_auto import init_ddl_auto
249
+ # 获取连接池
250
+ pool = None
251
+ if hasattr(self.sql_session_factory, 'configuration'):
252
+ pool = getattr(self.sql_session_factory.configuration, 'pool', None)
253
+ if pool is None and hasattr(self.sql_session_factory, '_pool'):
254
+ pool = self.sql_session_factory._pool
255
+ if pool is not None:
256
+ init_ddl_auto(pool, db_config)
257
+ except Exception as e:
258
+ logger.warning(f"DDL auto initialization skipped: {e}")
259
+
260
+ def _scan_mappers(self, application_context) -> None:
261
+ """
262
+ 扫描Mapper类
263
+ """
264
+ # 获取MapperScan注解配置
265
+ main_class = application_context.main_class
266
+ annotations = getattr(main_class, '__spring_annotations__', [])
267
+
268
+ base_packages = []
269
+ for annotation in annotations:
270
+ if isinstance(annotation, MapperScan):
271
+ base_packages.extend(annotation.base_packages)
272
+
273
+ if not base_packages:
274
+ # 默认扫描主类所在包下的mappers目录
275
+ base_packages.append(self._get_default_mapper_package(main_class))
276
+
277
+ # 扫描每个包
278
+ for package in base_packages:
279
+ self._scan_package(package)
280
+
281
+ def _get_default_mapper_package(self, main_class) -> str:
282
+ """
283
+ 获取默认的Mapper包路径
284
+ """
285
+ module_name = main_class.__module__
286
+ if module_name == '__main__':
287
+ return 'mappers'
288
+ return f"{module_name.split('.')[0]}.mappers"
289
+
290
+ def _scan_package(self, package_name: str) -> None:
291
+ """
292
+ 扫描指定包下的Mapper类
293
+ """
294
+ try:
295
+ # 将包名转换为路径
296
+ package_path = package_name.replace('.', os.sep)
297
+
298
+ # 查找包路径
299
+ for path in sys.path:
300
+ full_path = os.path.join(path, package_path)
301
+ if os.path.exists(full_path) and os.path.isdir(full_path):
302
+ # 遍历包下所有文件
303
+ for filename in os.listdir(full_path):
304
+ if filename.endswith('.py') and not filename.startswith('_'):
305
+ module_name = f"{package_name}.{filename[:-3]}"
306
+ self._import_module(module_name)
307
+ break
308
+ except Exception as e:
309
+ logger.warning(f"Failed to scan package {package_name}: {e}")
310
+
311
+ def _import_module(self, module_name: str) -> None:
312
+ """
313
+ 导入模块并查找Mapper类
314
+ """
315
+ try:
316
+ module = __import__(module_name, fromlist=['*'])
317
+ for name in dir(module):
318
+ obj = getattr(module, name)
319
+ if inspect.isclass(obj) and hasattr(obj, '__spring_annotations__'):
320
+ for annotation in obj.__spring_annotations__:
321
+ if isinstance(annotation, Mapper):
322
+ self._mapper_registry[name] = obj
323
+ break
324
+ except Exception as exc:
325
+ logger.warning("Failed to import mapper module %s: %s", module_name, exc)
326
+
327
+ def _generate_bean_name(self, cls_name: str) -> str:
328
+ """
329
+ 生成Bean名称,与Spring的命名规则保持一致
330
+ 将驼峰式转换为下划线式,如 UserMapper -> user_mapper
331
+ """
332
+ base_name = cls_name[:-6] if cls_name.endswith('Mapper') else cls_name
333
+
334
+ # 将驼峰式转换为下划线式
335
+ result = []
336
+ for i, char in enumerate(base_name):
337
+ if i > 0 and char.isupper():
338
+ result.append('_')
339
+ result.append(char.lower())
340
+
341
+ suffix = '_mapper' if cls_name.endswith('Mapper') else ''
342
+
343
+ return ''.join(result) + suffix
344
+
345
+ def _register_beans(self, bean_factory: BeanFactory) -> None:
346
+ """
347
+ 注册MyBatis相关Bean到Spring容器
348
+ """
349
+ # 注册SqlSessionFactory
350
+ bean_factory.register_bean_definition(
351
+ 'sqlSessionFactory',
352
+ BeanDefinition(
353
+ bean_class=SqlSessionFactory,
354
+ bean_name='sqlSessionFactory',
355
+ scope='singleton',
356
+ )
357
+ )
358
+ bean_factory.register_instance('sqlSessionFactory', self.sql_session_factory)
359
+
360
+ # 注册SqlSession(每次获取都创建新实例)
361
+ def create_sql_session():
362
+ return self.sql_session_factory.open_session()
363
+
364
+ bean_factory.register_bean_definition(
365
+ 'sqlSession',
366
+ BeanDefinition(
367
+ bean_class=SqlSession,
368
+ bean_name='sqlSession',
369
+ scope='prototype',
370
+ factory_method=create_sql_session,
371
+ )
372
+ )
373
+
374
+ # 注册所有Mapper(使用与Spring一致的命名规则)
375
+ for mapper_name, mapper_class in self._mapper_registry.items():
376
+ # 生成符合Spring命名规则的bean名称
377
+ bean_name = self._generate_bean_name(mapper_name)
378
+
379
+ # 创建Mapper代理工厂方法
380
+ def create_mapper_proxy(mapper_cls=mapper_class):
381
+ return ManagedMapperProxy(self.sql_session_factory, mapper_cls)
382
+
383
+ bean_factory.register_bean_definition(
384
+ bean_name,
385
+ BeanDefinition(
386
+ bean_class=mapper_class,
387
+ bean_name=bean_name,
388
+ scope='prototype',
389
+ factory_method=create_mapper_proxy,
390
+ )
391
+ )
392
+
393
+
394
+ def init_mybatis(application_context) -> None:
395
+ """
396
+ 初始化MyBatis集成
397
+ 在Spring应用启动时调用
398
+ """
399
+ configurer = MyBatisConfigurer(application_context.config_loader)
400
+ configurer.init(application_context)
@@ -0,0 +1,86 @@
1
+ """
2
+ PyMyBatis - Python版MyBatis ORM框架
3
+
4
+ 对标Java MyBatis,实现SQL与代码分离,支持XML映射文件、注解两种SQL编写方式。
5
+
6
+ 核心特性:
7
+ - SQL注入防御(参数化查询 + AST验证)
8
+ - 敏感数据脱敏
9
+ - 连接池管理(带熔断降级机制)
10
+ - 多数据源支持
11
+ - 动态SQL(if/where/foreach标签)
12
+ - 事务管理
13
+ - 自定义类型处理器
14
+ - 拦截器插件
15
+ - 查询缓存(支持Redis分布式缓存)
16
+ - 监控指标(Prometheus兼容)
17
+
18
+ 支持数据库:MySQL、PostgreSQL、SQLite、Oracle
19
+ """
20
+
21
+ from .core import SqlSession, SqlSessionFactory
22
+ from .configuration import Configuration
23
+ from .mapper import Mapper
24
+ from .annotations import (
25
+ CacheNamespace, DataSource, Delete, Insert, Options, Param, Result,
26
+ ResultMap, Select, Transactional, Update,
27
+ SelectProvider, InsertProvider, UpdateProvider, DeleteProvider,
28
+ )
29
+ from .transaction import Transaction, TransactionIsolationLevel
30
+ from .pool import ConnectionPool
31
+ from .cache import SqlCache, LRUCache, GLOBAL_SECOND_LEVEL_CACHE
32
+ from .dialect import Dialect, MySQLDialect, PostgreSQLDialect, SQLiteDialect, OracleDialect
33
+ from .security import SensitiveDataMasker, SQLInjectionDetector
34
+ from .interceptor import Interceptor
35
+ from .type_handler import TypeHandler
36
+
37
+ __version__ = "1.4.0"
38
+ __author__ = "PyMyBatis Team"
39
+
40
+ # 基础导出列表
41
+ __all__ = [
42
+ 'SqlSession', 'SqlSessionFactory', 'Configuration', 'Mapper',
43
+ 'Select', 'Insert', 'Update', 'Delete',
44
+ 'SelectProvider', 'InsertProvider', 'UpdateProvider', 'DeleteProvider',
45
+ 'ResultMap', 'Result',
46
+ 'Options', 'Param', 'CacheNamespace', 'DataSource', 'Transactional',
47
+ 'Transaction', 'TransactionIsolationLevel', 'ConnectionPool',
48
+ 'SqlCache', 'LRUCache', 'GLOBAL_SECOND_LEVEL_CACHE', 'Dialect',
49
+ 'MySQLDialect', 'PostgreSQLDialect', 'SQLiteDialect', 'OracleDialect',
50
+ 'SensitiveDataMasker', 'SQLInjectionDetector', 'Interceptor', 'TypeHandler',
51
+ 'build_session_factory',
52
+ ]
53
+
54
+ # 可选模块(按需导入)
55
+ try:
56
+ from .circuit_breaker import CircuitBreaker, DatabaseCircuitBreaker, CircuitBreakerState, CircuitBreakerError
57
+ __all__.extend(['CircuitBreaker', 'DatabaseCircuitBreaker', 'CircuitBreakerState', 'CircuitBreakerError'])
58
+ except ImportError:
59
+ pass
60
+
61
+ try:
62
+ from .cache.redis_cache import RedisSecondLevelCache, create_redis_cache
63
+ __all__.extend(['RedisSecondLevelCache', 'create_redis_cache'])
64
+ except ImportError:
65
+ pass
66
+
67
+ try:
68
+ from .metrics import MetricsCollector, Counter, Gauge, Histogram, Timer, get_default_collector
69
+ __all__.extend(['MetricsCollector', 'Counter', 'Gauge', 'Histogram', 'Timer', 'get_default_collector'])
70
+ except ImportError:
71
+ pass
72
+
73
+
74
+ def build_session_factory(config: dict) -> SqlSessionFactory:
75
+ """
76
+ 快速构建SqlSessionFactory
77
+
78
+ Args:
79
+ config: 配置字典,包含数据源、映射文件等配置
80
+
81
+ Returns:
82
+ SqlSessionFactory实例
83
+ """
84
+ configuration = Configuration()
85
+ configuration.load_config(config)
86
+ return SqlSessionFactory(configuration)
@@ -0,0 +1,30 @@
1
+ """
2
+ PyMyBatis注解模块
3
+
4
+ 提供SQL注解定义:@Select、@Insert、@Update、@Delete、@ResultMap、@Result
5
+ """
6
+
7
+ from .annotations import (
8
+ CacheNamespace,
9
+ DataSource,
10
+ Delete,
11
+ DeleteProvider,
12
+ Insert,
13
+ InsertProvider,
14
+ Options,
15
+ Param,
16
+ Result,
17
+ ResultMap,
18
+ Select,
19
+ SelectProvider,
20
+ Transactional,
21
+ Update,
22
+ UpdateProvider,
23
+ )
24
+
25
+ __all__ = [
26
+ 'Select', 'Insert', 'Update', 'Delete',
27
+ 'SelectProvider', 'InsertProvider', 'UpdateProvider', 'DeleteProvider',
28
+ 'ResultMap', 'Result',
29
+ 'Options', 'Param', 'CacheNamespace', 'DataSource', 'Transactional',
30
+ ]