spel sql jpa 通过interface 进行字段id中文映射

目的是将某一个字段返回数据通过处理进行pid—>转换为pidName的复杂处理
方案有两个:
1.通过sql直接进行处理
2.通过返回interface进行处理
方案一: 一坨屎 sql 在查询中通过left join 多张表 COALESCE 进行判断进行展示

前方高能

    @Query(value = "SELECT id, gameId, pid, NewUser, newSourcePercent , totalSourcePercent, USER, sumUser, channelId, subChannelId , dt, gameName, channelName, subChannelName , " +
            "COALESCE(gssctr.prName, gssctr.drName, gssctr.evName, '未知') AS plateName " +
            "FROM ( SELECT gssctr.id AS id, gssctr.game_id AS gameId, gssctr.pid AS pid, gssctr.n_user AS NewUser , " +
            "IF(gsctr.USER = 0, 0, FORMAT(gssctr.n_user * 100 / gsctr.USER, 2)) AS newSourcePercent , " +
            "IF(gsctr.USER = 0, 0, FORMAT(gssctr.USER * 100 / gsctr.USER, 2)) AS totalSourcePercent , " +
            "gssctr.USER AS USER, gsctr.USER AS sumUser, gssctr.channel_id AS channelId, gssctr.sub_channel_id AS subChannelId, gssctr.dt AS dt , g.NAME AS gameName, c.NAME AS channelName, sc.NAME AS subChannelName, " +
            "pr.NAME AS prName, dr.NAME AS drName , ev.NAME AS evName " +
            "FROM game_source_sub_channel_total_report gssctr " +
            "LE
### 如何在JPA中实现动态表名功能 #### 使用RelationalPathBase类 通过`RelationalPathBase`类可以手动指定表名。此方法适用于QueryDSL框架中的场景,允许开发者灵活地定义实体对应的数据库表名称。具体来说,可以通过以下方式创建一个动态表对象: ```java public class DynamicTable<T> extends RelationalPathBase<T> { public DynamicTable(Class<? extends T> type, String tableName) { super(type, "variable", null, tableName); } } ``` 这种方式的核心在于构造函数参数中的`table`字段可以直接传入目标表名[^1]。 --- #### 自定义命名策略 另一种常见的做法是通过自定义Hibernate的命名策略来实现动态表名映射。这通常涉及重写`PhysicalNamingStrategy`接口或者利用Spring Data JPA提供的扩展机制完成。例如,在配置文件中启用如下属性即可支持基于表达式的动态表名替换: ```properties spring.jpa.hibernate.naming.physical-strategy=com.example.CustomPhysicalNamingStrategy ``` 配合`@Table(name="#{T(com.example.Config).getTableName()}")`注解形式声明逻辑上的表名解析规则[^2]。 --- #### 定义SQL拦截器 对于更复杂的业务需求(比如运行时决定具体的物理存储位置),推荐采用AOP思想设计全局性的SQL语句修改方案——即编写继承自`EmptyInterceptor`的基础组件并注册至SessionFactory实例当中去应用它。下面展示了一个简单的例子用于演示如何把原有的硬编码式FROM子句替换成由上下文传递过来的新值: ```java @Slf4j public class TableNameInterceptor extends EmptyInterceptor { private static final ThreadLocal<Map<String, String>> TABLE_MAP = new ThreadLocal<>(); @Override public String onPrepareStatement(String sql) { Map<String, String> tableMapping = TABLE_MAP.get(); if (Objects.nonNull(tableMapping)) { Set<Map.Entry<String, String>> entries = tableMapping.entrySet(); for (Map.Entry<String, String> entry : entries) { Pattern pattern = Pattern.compile("\\b" + entry.getKey() + "\\b"); Matcher matcher = pattern.matcher(sql.toLowerCase()); while (matcher.find()) { log.debug("Replacing {} with {}", entry.getValue(), entry.getKey()); sql = matcher.replaceFirst(entry.getValue()); } } } return sql; } public static void setDynamicTables(Map<String, String> mappings){ TABLE_MAP.set(mappings); } } ``` 随后记得激活这个插件生效路径: ```yaml spring: jpa: properties: hibernate.session_factory.session_scoped_interceptor: com.package.TableNameInterceptor ``` 最后调用API之前同步更新当前线程关联的数据结构内容以便即时反映更改后的状态[^3]: ```java Map<String, String> mapping = Collections.singletonMap("original_table_name","target_table_name"); TableNameInterceptor.setDynamicTables(mapping); repository.findAll(); ``` --- #### 原生查询结合SpEL表达式 如果仅需针对某些特定操作引入灵活性而无需全面覆盖整个项目,则可考虑直接书写带有占位符标记的标准SQL字符串再借助于Spring Expression Language(SpEL)语法对其求值得到最终形态供执行层消费。像这样一段代码片段就很好地诠释了这一理念的实际运用效果: ```java @Repository public interface UserRepository extends JpaRepository<User,Integer>{ @Modifying @Transactional @Query(value="DELETE FROM ${#tableName} WHERE id=:id ",nativeQuery=true) Integer removeById(@Param("tableName")String tableName,@Param("id")Long id); } ``` 注意这里`${}`包裹部分会被视作模板变量参与后续处理流程直至生成实际可用的结果集为止[^4]。 --- ### 总结 综上所述,有多种途径可供选择以达成相同目的—使应用程序具备适应不同底层数据源布局的能力的同时保持较高的抽象层次不变。每种技术路线都有各自适用范围以及局限之处,因此应当依据实际情况权衡利弊之后择优选用最为合适的解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值