如何根据Spring的某些条件应用不同名称的@Table注解?

问题描述 投票:0回答:1

问题:保留关键字

由于历史原因,我有一个名为

User
的实体类,Hibernate 默认计算表名称为
user
。该名称是一个保留的 SQL 关键字,至少在 Postgres 上无需引用即可中断,但它可以在 DB2i 等其他 RDBMS 上工作。此外,DB2i 不仅使用该不带引号的名称,而且由于它不带引号,因此还应用大写名称折叠。这意味着在生产中一些名为
USER
的表已经存在。虽然 Postgres 不支持这种不带引号的具体表名称,但它可以创建其他表,但应用小写名称折叠,因此当前 RDBMS 之间的表命名方案有所不同。

不同的名称与引用

这就是事情变得困难的地方:理论上,最好的方法是始终简单地引用所有标识符,但从一开始就不是这样,所以我现在有小写和大写的表名,具体取决于 RDBMS用过的。这意味着在 DB2i 上将值引用到

user
失败,但在 Postgres 上可以。将值引用到
USER
在 DB2i 上有效,但至少在 Postgres 上看起来很奇怪,因为其他名称都是小写的。

有条件使用不同的名称吗?

我知道该问题还有许多其他可能的解决方案,例如引用和重命名所有内容、仅将一张表重命名为

user_account
、实施不同的自定义命名策略等。但我想知道的是是否可以应用同一类有两个不同的
@Table
注释,具体取决于某些 Spring 属性。类似于以下内容,仅具有一个且相同的类:

@ConditionalOnProperty(
  value="spring.jpa.properties.hibernate.dialect",
  havingValue = "com.ibm.as400.access.AS400JDBCDriver"
  matchIfMissing = true)
@Table(name = "\"user\"")
public class User extends BusinessEntity {

@ConditionalOnProperty(
  value="spring.jpa.properties.hibernate.dialect",
  havingValue = "com.ibm.as400.access.AS400JDBCDriver"
  matchIfMissing = false)
@Table(name = "\"USER\"")
public class User extends BusinessEntity {

在上面的示例中,

@ConditionalOnProperty
的目标是类,而不是
@Table
。我希望
@Table
取决于属性。

那么,类似的事情有可能吗?

谢谢!

java spring postgresql hibernate spring-annotations
1个回答
0
投票

有几个选项可以解决您的问题(所有这些选项实际上都很糟糕,因为最好的选择是重命名表):

  1. hibernate.auto_quote_keyword
    设置为
    true
    ,因为 这是 Mark Rotteveel 的建议

  2. 利用物理命名策略,例如:

public class ReservedWordAwareCamelCaseToUnderscoresNamingStrategy extends CamelCaseToUnderscoresNamingStrategy {

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        Identifier suggested = super.toPhysicalTableName(name, jdbcEnvironment);
        Dialect dialect = jdbcEnvironment.getDialect();
        if (...) {
            return ...
        }
        return suggested;
    }

}
  1. 利用
    Integrator
    SPI
    :
public class LegacyUserTableNameIntegrator implements Integrator {

    @Override
    public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
        Dialect dialect = serviceRegistry.getService(JdbcEnvironment.class).getDialect();
        for (PersistentClass persistentClass : metadata.getEntityBindings()) {
            if (persistentClass.getMappedClass() == User.class) {
                persistentClass.getRootClass().getTable().setName("...");
            }


        }
    }

    ...

}
© www.soinside.com 2019 - 2024. All rights reserved.