JPA-hibernate @Table(name =“动态表名” )
记录一下hibernate动态设置表名的一些坑
首先maven引入等不贴了,到这一步,一般来说,maven肯定引入了
首先需要自定义一个类,主要用来解析表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.expression.BeanFactoryAccessor; import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.expression.Expression; import org.springframework.expression.ParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component; /** * 自定义命名策略(实现支持解析#{javaConfig.property}获取表名功能 ) * * @author Java大笨笨 * @since 2019-03-26 */ @Component public class MySpringPhysicalNamingStrategy extends PhysicalNamingStrategyStandardImpl implements ApplicationContextAware { private final StandardEvaluationContext context = new StandardEvaluationContext(); private final SpelExpressionParser parser = new SpelExpressionParser(); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this .context.addPropertyAccessor( new BeanFactoryAccessor()); this .context.setBeanResolver( new BeanFactoryResolver(applicationContext)); this .context.setRootObject(applicationContext); } @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) { String nameStr = name.getText(); if (nameStr.contains(ParserContext.TEMPLATE_EXPRESSION.getExpressionPrefix())){ //参考SimpleElasticsearchPersistentEntity 实现思想,将tableName参数的值支持表达式获取 Expression expression = this .parser.parseExpression(nameStr, ParserContext.TEMPLATE_EXPRESSION); return Identifier.toIdentifier((String)expression.getValue( this .context, String. class )); } else { //默认方式不变 return super .toPhysicalTableName(name, jdbcEnvironment); } } } |
注意,这个类要继承一个PhysicalNamingStrategyStandardImpl,这个取决于你目前项目中的naming.physical-strategy,我之前用的是PhysicalNamingStrategyStandardImpl,所以这里继承并重新toPhysicalTableName方法。
yml配置
1 2 3 4 5 6 7 8 9 10 11 12 13 | spring: jpa: database: mysql show-sql: true hibernate: ddl-auto: none database-platform: org.hibernate.dialect.MySQL5InnoDBDialect properties: hibernate.format_sql: false hibernate.naming.physical-strategy: xxxxx你的包名.MySpringPhysicalNamingStrategy hibernate.cache.use_second_level_cache: false hibernate.search. default .directory_provider: filesystem hibernate.search. default .indexBase: c:\\xxxx |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * @author java大笨笨 * @create 2021-02-23 16:07 */ @Component ( "optionsConfig" ) public class OptionsConfig { @Value ( "${site.options.table_name}" ) private String optionsTableName; public String getOptionsTableName() { return optionsTableName; } public void setOptionsTableName(String optionsTableName) { this .optionsTableName = optionsTableName; } } |
注意@Component("optionsConfig"),给个名字,否则会在表达式解析时候找不到这个类
1 2 3 4 5 6 7 8 | */ @Entity @Table (name = "#{optionsConfig.optionsTableName}" ) public class Options { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private long id; ………… |
最后这样,在name中写入表达式即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】