【问题标题】:Using JdbcPagingItemReader causing join statements causing MySQLIntegrityConstraintViolationException使用 JdbcPagingItemReader 导致连接语句导致 MySQLIntegrityConstraintViolationException
【发布时间】:2015-05-13 10:36:27
【问题描述】:

我正在运行 Spring Batch 并使用 JdbcPagingItemReader。使用示例配置:

<bean id="dogQueryProvider"		class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
		<property name="databaseType" value="mysql" />
		<property name="dataSource" ref="dataSource" />
		<property name="selectClause"
			value="SELECT owner.id as ownerid, first_name, last_name, dog_name " />
		<property name="fromClause"
			value="FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id " />
		<property name="sortKey" value="owner.id" />
</bean>

我收到与以下相关的错误:

订单子句中的“id”列不明确;嵌套异常是 com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: order 子句中的列 'id' 不明确。

假设dog_ownerdog 表有id 列。我认为这与AbstractSqlPagingQueryProvider.getSortKeysWithoutAliases 有关,我认为它从指定为sortKeyowner.id 中剥离了owner。有解决此问题的建议吗?

【问题讨论】:

    标签: spring-batch


    【解决方案1】:

    您对它发生的原因的推理是正确的。在您的情况下,我希望使用您的别名来解决问题。因此,您已将 owner.id 别名为 ownerid,但是您不会在 sortkey 字段(或与此相关的连接子句)中使用它。使用别名应该没问题。

    【讨论】:

    • 感谢您的反馈。我最初尝试过。我认为这适用于对 firstPageSql 查询进行工作查询,但生成的剩余PagesSql 似乎无效,因为我在查询中得到类似 WHERE ((ownerid > ?)) 的内容,导致 MySQLSyntaxErrorException:'where 子句'中的未知列'ownerid'。不确定是否缺少配置。临时修复是覆盖 MySqlPagingQueryProvider。我会认为这个用例很常见
    • 我实际上认为这是一个错误。我创建了 Jira 问题 BATCH-2360 来跟踪它 (jira.spring.io/browse/BATCH-2360)。
    • 仅供参考。我在使用 H2 数据库进行测试时遇到了同样的错误。我认为 H2PagingQueryProvider 仍然没有修复。
    【解决方案2】:

    显然,这似乎仍在以某种形式发生,但有办法制作您的查询,这样别名就不会被删除。您可以通过选择不同的名称来重命名连接的列。

    你的 selectClause 变成了

    SELECT owner.id, owner.first_name, owner.last_name, dog.dog_name
    

    FromClause 变成

          FROM dog_owner owner
    INNER JOIN (SELECT d2.id AS dogId, d2.dog_name
                  FROM dog d2) AS dog
            ON owner.id = dog.dogId
    

    现在您应该可以使用“id”作为 sortKey,因为只有一列名称为“id”。即使您将 dog.dogId 添加到 selectClause 中,这仍然有效。

    【讨论】:

    • 为什么在春季批次中必须使用 sortkey.. 有什么原因吗?理想情况下,它应该是可选的,或者如果以防万一……我不明白 spring 迫使开发人员使用排序键的原因。
    【解决方案3】:

    我们遇到了这个问题,Spring 必须从返回的结果集中获取您的排序键才能正确分页。底层排序键用于 WHERE 子句,该子句不适用于列别名,因为 WHERE 在数据库级别的 SELECT 语句之前得到处理。

    我们的解决方案是SELECT owner.id as "owner.id",以便可以使用相同名称从结果集中检索排序键。执行 SELECT owner.id 会将列 id 放入您的结果集中,这在您的情况下会导致列不明确的问题。与上一个答案的嵌套查询相比,我们更喜欢这种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 2016-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多