【问题标题】:Spring Data JDBC MappedCollection casing issues with Postgres + OraclePostgres + Oracle 的 Spring Data JDBC MappedCollection 大小写问题
【发布时间】:2022-10-07 19:43:05
【问题描述】:

这是我目前的回购结构,我正在寻找一种适用于 Postgres 和 OracleDB 的解决方案,并且最好不涉及更改我的数据库模式以适应 ORM。使用 Postgres 还是 Oracle 在 spring.datasource.url 文件中的 application.properties 中定义。

data class NewsCover(
    @Id val tenantId: TenantId,
    val openOnStart: Boolean,
    val cycleDelay: Int,

    @MappedCollection(idColumn = "tenant_id", keyColumn = "tenant_id")
    val sections: Set<NewsCoverSection>,
)

data class NewsCoverSection(
    @Id val id: NewsCoverSectionId,
    val title: String,
    val pinnedOnly: Boolean,
    val position: Int,
    val tenantId: TenantId,
    ... some other fields ...
)

interface NewsCoverRepo : CrudRepository<NewsCover, TenantId> { ... }

这适用于 Postgresql,但与 Oracle 一起使用时会产生错误:

SELECT "NEWS_COVER_SECTION"."ID" AS "ID", "NEWS_COVER_SECTION"."TITLE" AS "TITLE", "NEWS_COVER_SECTION"."POSITION" AS "POSITION", "NEWS_COVER_SECTION"."TENANT_ID" AS "TENANT_ID", "NEWS_COVER_SECTION"."PINNED_ONLY" AS "PINNED_ONLY" 
FROM "NEWS_COVER_SECTION" 
WHERE "NEWS_COVER_SECTION"."tenant_id" = ?

请参阅 @MappedCollection 中引用的 idColumn/keyColumn 名称。它们是小写的。这对 Postgres 来说很好,但不适用于 Oracle。将 tenant_id 更改为 TENANT_ID 可以解决 Oracle 的问题,但会破坏 Postgres。

我尝试了什么:

  1. Oracle 的NamingStrategy 覆盖,但我似乎无法覆盖那些引用的标识符。
  2. @MappedCollection 中的条件列名,但@MappedCollection 只接受编译时常量,不支持SpEL,所以我无法根据spring.datasource.url 属性进行区分。

    当数据库是 Postgres 和 "NEWS_COVER_SECTION"."TENANT_ID" 当数据库是 Oracle 时,我有什么想法可以让它查询 "news_cover_section"."tenant_id" 吗?

【问题讨论】:

  • 全部大写的查询在 Oracle 中应该可以正常工作。
  • 我的问题是让它与 Postgres 和 Oracle 一起工作,这取决于哪个数据库被配置为数据源。我在 @MappedCollection 注释中引用了列标​​识符。 @MappedCollection(idColumn = "tenant_id", keyColumn = "tenant_id") 与 Postgres 一起使用,@MappedCollection(idColumn = "TENANT_ID", keyColumn = "TENANT_ID") 与 Oracle 一起使用。但两者都不适用于两个数据库。
  • 你应该告诉你的混淆层绝不引用任何标识符。
  • 谢谢,这似乎是目前最简单的解决方案。禁用 forceQuote 在其他地方产生了一些小问题,但这些问题很容易管理。

标签: spring postgresql oracle spring-data-jdbc


【解决方案1】:

正如您所发现的,您可以通过将forceQuote property of the JdbcMappingContext 设置为false 来禁用引用所有名称的行为。

或者,您可以通过在架构创建脚本中引用名称以一致的方式在两个数据库上创建架构。

第一个选项允许您不摆弄数据库模式。 但它使应用程序依赖于避免数据库关键字,例如:ORDERUSER

第二个选项可以说是概念上更清晰的选项,因为它实际上对两个数据库使用相同的模式(就名称而言),这本身当然很有价值。但是以引用名称为代价,因为 Postgres 不遵守 SQL 标准规定的将未引用的名称视为大写的行为。

注意:现在有一个issue for supporting SpEL expressions for table and column names

【讨论】:

    猜你喜欢
    • 2019-04-22
    • 2020-06-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    相关资源
    最近更新 更多