fix: 修复复审2个建议 (models注释 + N+1查询 + 事务边界)
- models.py: 注释中旧模式名对齐 EditingMode 枚举 - list_by_user: 批量加载 segments 避免 N+1 查询 - create(): flush 替代 commit,create_segments 统一提交事务
This commit is contained in:
@@ -287,7 +287,7 @@ class TemplateModel(Base):
|
||||
id = Column(String(36), primary_key=True)
|
||||
user_id = Column(String(36), nullable=False, index=True)
|
||||
name = Column(String(200), nullable=False)
|
||||
mode = Column(String(30), nullable=False, index=True) # pip / person_narration / one_take / voice_over_mix
|
||||
mode = Column(String(30), nullable=False, index=True) # EditingMode 枚举值: pip / voice_pip / one_take / voice_over
|
||||
category = Column(String(100), nullable=False, default="")
|
||||
tags = Column(JSON, nullable=False, default=list)
|
||||
title_config = Column(JSON, nullable=False, default=dict)
|
||||
@@ -307,7 +307,7 @@ class TemplateSegmentModel(Base):
|
||||
segment_order = Column(Integer, nullable=False)
|
||||
duration_min = Column(Float, nullable=False)
|
||||
duration_max = Column(Float, nullable=False)
|
||||
material_type = Column(String(20), nullable=True) # 仅 voice_over_mix: 人物/场景
|
||||
material_type = Column(String(20), nullable=True) # 仅 voice_over 模式: 人物/场景
|
||||
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
updated_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
|
||||
|
||||
@@ -40,8 +40,23 @@ class SQLAlchemyTemplateRepository:
|
||||
.all()
|
||||
)
|
||||
templates = [self._model_to_entity(m) for m in models]
|
||||
for t in templates:
|
||||
t.segments = self.list_segments(t.id)
|
||||
# 批量加载所有 segments,避免 N+1 查询
|
||||
if templates:
|
||||
template_ids = [t.id for t in templates]
|
||||
seg_models = (
|
||||
self.session.query(TemplateSegmentModel)
|
||||
.filter(TemplateSegmentModel.template_id.in_(template_ids))
|
||||
.order_by(TemplateSegmentModel.segment_order)
|
||||
.all()
|
||||
)
|
||||
# 按 template_id 分组
|
||||
seg_map: dict[str, list] = {}
|
||||
for sm in seg_models:
|
||||
seg_map.setdefault(sm.template_id, []).append(
|
||||
self._segment_model_to_entity(sm),
|
||||
)
|
||||
for t in templates:
|
||||
t.segments = seg_map.get(t.id, [])
|
||||
return templates
|
||||
|
||||
def get(self, template_id: str, user_id: str) -> Optional[Template]:
|
||||
@@ -74,7 +89,8 @@ class SQLAlchemyTemplateRepository:
|
||||
is_active=template.is_active,
|
||||
)
|
||||
self.session.add(model)
|
||||
self.session.commit()
|
||||
# flush 而非 commit,让 create + create_segments 在同一事务中提交
|
||||
self.session.flush()
|
||||
self.session.refresh(model)
|
||||
result = self._model_to_entity(model)
|
||||
result.segments = template.segments
|
||||
|
||||
@@ -70,20 +70,20 @@ class CreateTemplateUseCase:
|
||||
)
|
||||
template = self.repository.create(template)
|
||||
|
||||
if command.segments:
|
||||
segments = [
|
||||
TemplateSegment(
|
||||
id=uuid.uuid4().hex,
|
||||
template_id=template.id,
|
||||
segment_order=seg.segment_order,
|
||||
duration_min=seg.duration_min,
|
||||
duration_max=seg.duration_max,
|
||||
material_type=seg.material_type,
|
||||
)
|
||||
for seg in command.segments
|
||||
]
|
||||
self.repository.create_segments(segments)
|
||||
template.segments = segments
|
||||
# 始终调用 create_segments 以确保在同一事务中提交
|
||||
segments = [
|
||||
TemplateSegment(
|
||||
id=uuid.uuid4().hex,
|
||||
template_id=template.id,
|
||||
segment_order=seg.segment_order,
|
||||
duration_min=seg.duration_min,
|
||||
duration_max=seg.duration_max,
|
||||
material_type=seg.material_type,
|
||||
)
|
||||
for seg in command.segments
|
||||
]
|
||||
self.repository.create_segments(segments)
|
||||
template.segments = segments
|
||||
|
||||
return template
|
||||
|
||||
|
||||
Reference in New Issue
Block a user