口才和会议场景

This commit is contained in:
zhonghua1
2026-01-09 19:41:18 +08:00
parent 99d644d082
commit 602338b27b
49 changed files with 5747 additions and 13 deletions

View File

@@ -0,0 +1,246 @@
# 后端修复转文本更新时去掉tenant_id限制
## ⚡ 快速修复(推荐)
**最快解决方案**在Mapper接口中添加自定义更新方法
1.`AudioManagementSegmentsMapper.java` 中添加:
```java
@InterceptorIgnore(tenantLine = "true")
@Update("UPDATE audio_management_segments SET recording_text = #{recordingText}, transcribe_end_time = #{transcribeEndTime} WHERE id = #{id}")
int updateTranscriptionWithoutTenant(
@Param("id") String id,
@Param("recordingText") String recordingText,
@Param("transcribeEndTime") LocalDateTime transcribeEndTime
);
```
2. 在Controller的转文本方法中
```java
boolean updateSuccess = audioManagementSegmentsService.update(textUpdateEntity, textUpdateWrapper);
```
替换为:
```java
int updateCount = audioManagementSegmentsMapper.updateTranscriptionWithoutTenant(
segmentId, transcriptionText, LocalDateTime.now()
);
boolean updateSuccess = updateCount > 0;
```
---
## 问题描述
在转文本功能中,更新 `audio_management_segments` 表时MyBatis-Plus 的多租户插件自动添加了 `AND tenant_id = null` 条件,导致更新失败。
从日志可以看到:
```sql
UPDATE audio_management_segments SET recording_text=?, transcribe_end_time=?
WHERE (id = ?) AND tenant_id = null
```
## 解决方案
### 方案1在Controller层使用baseMapper直接更新最简单有效
在转文本的Controller方法中直接使用 `baseMapper` 更新绕过Service层的多租户拦截
```java
@PostMapping("/transcribe/{id}")
@Operation(summary = "转文本", description = "分段音频文件转文本")
public ResponseEntity<Map<String, Object>> transcribeSegmentById(
@Parameter(description = "分段ID", required = true)
@PathVariable String id) {
try {
// ... 转文本逻辑 ...
// 更新录音文本 - 直接使用baseMapper绕过多租户拦截
AudioManagementSegments textUpdateEntity = new AudioManagementSegments();
textUpdateEntity.setRecordingText(transcriptionText);
textUpdateEntity.setTranscribeEndTime(LocalDateTime.now());
LambdaUpdateWrapper<AudioManagementSegments> textUpdateWrapper = new LambdaUpdateWrapper<>();
textUpdateWrapper.eq(AudioManagementSegments::getId, segmentId);
// 关键:使用 baseMapper 直接更新,并设置忽略多租户拦截
// 方法1使用 @SqlParser(filter = true) - 旧版本MyBatis-Plus
// 方法2直接调用 baseMapper.update但需要在Mapper方法上添加注解
// 推荐在Mapper接口中添加自定义更新方法
int updateCount = audioManagementSegmentsMapper.updateTranscriptionWithoutTenant(
segmentId,
transcriptionText,
LocalDateTime.now()
);
boolean updateSuccess = updateCount > 0;
// ... 其他逻辑 ...
} catch (Exception e) {
// ... 错误处理 ...
}
}
```
### 方案2在Mapper接口中添加自定义更新方法推荐
`AudioManagementSegmentsMapper` 中添加自定义更新方法,使用 `@InterceptorIgnore` 注解:
```java
@Mapper
public interface AudioManagementSegmentsMapper extends BaseMapper<AudioManagementSegments> {
/**
* 更新转文本结果,忽略多租户拦截
*/
@InterceptorIgnore(tenantLine = "true")
@Update("UPDATE audio_management_segments SET recording_text = #{recordingText}, transcribe_end_time = #{transcribeEndTime} WHERE id = #{id}")
int updateTranscriptionWithoutTenant(
@Param("id") String id,
@Param("recordingText") String recordingText,
@Param("transcribeEndTime") LocalDateTime transcribeEndTime
);
}
```
然后在Controller中调用
```java
// 在转文本方法中
int updateCount = audioManagementSegmentsMapper.updateTranscriptionWithoutTenant(
segmentId,
transcriptionText,
LocalDateTime.now()
);
boolean updateSuccess = updateCount > 0;
```
### 方案3在Service层添加专门的方法并禁用多租户拦截
`AudioManagementSegmentsService` 接口中添加新方法:
```java
public interface AudioManagementSegmentsService extends IService<AudioManagementSegments> {
/**
* 更新转文本结果,忽略多租户拦截
*/
boolean updateTranscription(String id, String recordingText, LocalDateTime transcribeEndTime);
}
```
在实现类中:
```java
@Service
public class AudioManagementSegmentsServiceImpl extends ServiceImpl<AudioManagementSegmentsMapper, AudioManagementSegments>
implements AudioManagementSegmentsService {
@Override
@InterceptorIgnore(tenantLine = "true") // 禁用多租户拦截
public boolean updateTranscription(String id, String recordingText, LocalDateTime transcribeEndTime) {
AudioManagementSegments entity = new AudioManagementSegments();
entity.setId(id);
entity.setRecordingText(recordingText);
entity.setTranscribeEndTime(transcribeEndTime);
LambdaUpdateWrapper<AudioManagementSegments> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(AudioManagementSegments::getId, id);
// 注意这里仍然可能被拦截所以最好使用Mapper的自定义方法
return this.update(entity, wrapper);
}
}
```
**注意**如果方案3仍然被拦截请使用方案2Mapper层的自定义方法
### 方案4配置多租户插件排除该表全局方案
在 MyBatis-Plus 的多租户配置中,排除 `audio_management_segments` 表:
```java
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 多租户插件
TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
tenantInterceptor.setTenantLineHandler(new TenantLineHandler() {
@Override
public Expression getTenantId() {
// 返回租户ID从上下文获取
String tenantId = TenantContextHolder.getTenantId();
return tenantId != null ? new StringValue(tenantId) : null;
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean ignoreTable(String tableName) {
// 排除 audio_management_segments 表,不进行多租户拦截
return "audio_management_segments".equalsIgnoreCase(tableName);
}
});
interceptor.addInnerInterceptor(tenantInterceptor);
return interceptor;
}
}
```
**注意**:这个方案会影响所有对 `audio_management_segments` 表的操作,请确保安全性。
### 方案4使用自定义SQL不推荐但可行
如果以上方案都不适用可以使用自定义SQL直接执行更新语句
```java
@Mapper
public interface AudioManagementSegmentsMapper extends BaseMapper<AudioManagementSegments> {
@Update("UPDATE audio_management_segments SET recording_text = #{recordingText}, transcribe_end_time = #{transcribeEndTime} WHERE id = #{id}")
int updateTranscription(@Param("id") String id,
@Param("recordingText") String recordingText,
@Param("transcribeEndTime") LocalDateTime transcribeEndTime);
}
```
## 推荐方案(按优先级)
### 最推荐方案2 - Mapper层自定义方法
**强烈推荐使用方案2**在Mapper接口中添加自定义更新方法使用 `@InterceptorIgnore` 注解:
**优点**
1. ✅ 最直接有效,不会被拦截器拦截
2. ✅ 只影响转文本的更新操作
3. ✅ 不影响其他查询和更新操作
4. ✅ 代码清晰,易于维护
5. ✅ 性能好直接执行SQL
**实现步骤**
1.`AudioManagementSegmentsMapper` 接口中添加方法见方案2代码
2. 在Controller中调用 `audioManagementSegmentsMapper.updateTranscriptionWithoutTenant()`
3. 替换原来的 `service.update()` 调用
### 备选方案方案4 - 配置排除表
如果方案2不适用可以使用方案4在配置中排除整个表
- ⚠️ 会影响所有对该表的操作
- ⚠️ 需要确保安全性
- ✅ 一次配置,全局生效
## 注意事项
1. 如果使用方案3全局排除表会影响所有对该表的操作需要确保安全性
2. 如果使用方案4自定义SQL需要手动处理SQL注入防护
3. 修改后需要测试其他功能是否受影响