Spring 数据 JDBC 一对多关系导致大量日志警告
Spring Data JDBC one-to-many relation causes lots of log warnings
摘要:Spring 数据发出警告,因为它 SELECT
在同一列中两次。警告是:
(...) WARN o.s.d.j.core.convert.ResultSetAccessor : ResultSet contains id multiple times
这是 spring-boot-starter-data-jdbc
通过 Spring Boot 2.5.5 (documentation)。我正在处理一个非常基本的一对多关系:
为简洁起见,我已尽可能减少实体 类,同时保留警告:
Outlet.java
(...)
@Table("outlet")
public class Outlet {
@Id
private String outletId;
@MappedCollection(idColumn = "outlet_id", keyColumn = "id")
private Map<String, OfferedService> offeredServices;
(...)
}
OfferedService.java
(...)
@Table("offered_service")
public class OfferedService {
@Id
private String id;
private String outletId;
(...)
}
存储库也是最基本的...
OutletRepository.java
(...)
public interface OutletRepository extends CrudRepository<Outlet, String> {}
...在我的应用程序代码中,我只是在此存储库上执行 findAll
:
(...)
outletRepo.findAll();
(...)
这会导致查询选择同一列两次,随后会出现来自 Spring 数据 ResultSetAccessor
:
的警告
DEBUG o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [
SELECT "outlet"."outlet_id" AS "outlet_id" FROM "outlet"]
DEBUG o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
DEBUG o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [
SELECT "offered_service"."id" AS "id",
"offered_service"."outlet_id" AS "outlet_id",
"offered_service"."id" AS "id"
FROM "offered_service"
WHERE "offered_service"."outlet_id" = ?]
TRACE o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value:
column index 1, parameter value [xyz012], value class [java.lang.String], SQL type 12
WARN o.s.d.j.core.convert.ResultSetAccessor : ResultSet contains id multiple times
WARN o.s.d.j.core.convert.ResultSetAccessor : ResultSet contains id multiple times
(...repeated many times...)
我在这里做错了什么?另外,对于 findAll
,这不应该首先是 JOIN
吗?
您有两件事映射到列 offered_service.outlet_id
:
从Outlet
到OfferedService
的一对多映射和属性OfferedService.outletId
.
如果这些应该不同,您可以使用注释来更改它们映射到的列,但我假设您是故意这样做的,以便在 OfferedService
中提供 outletId
实体。
虽然这可行,但它有点像 hack,可能会在未来的版本中崩溃。
推荐的做法是使用 @Transient
使 outletId
成为瞬态,并在添加 OfferedService
时使用纯 java 代码设置其值Outlet
.
有一篇关于此的博客文章:https://spring.io/blog/2021/09/22/spring-data-jdbc-how-do-i-make-bidirectional-relationships
似乎还有另一个问题,其中 Spring 数据 JDBC 执行 select OfferedService.id
两次。我不确定为什么会这样。对我来说看起来像个错误。但是您可能可以完全删除 id
,因为映射键和 outlet_id
应该形成一个完美的主键。
摘要:Spring 数据发出警告,因为它 SELECT
在同一列中两次。警告是:
(...) WARN o.s.d.j.core.convert.ResultSetAccessor : ResultSet contains id multiple times
这是 spring-boot-starter-data-jdbc
通过 Spring Boot 2.5.5 (documentation)。我正在处理一个非常基本的一对多关系:
为简洁起见,我已尽可能减少实体 类,同时保留警告:
Outlet.java
(...)
@Table("outlet")
public class Outlet {
@Id
private String outletId;
@MappedCollection(idColumn = "outlet_id", keyColumn = "id")
private Map<String, OfferedService> offeredServices;
(...)
}
OfferedService.java
(...)
@Table("offered_service")
public class OfferedService {
@Id
private String id;
private String outletId;
(...)
}
存储库也是最基本的...
OutletRepository.java
(...)
public interface OutletRepository extends CrudRepository<Outlet, String> {}
...在我的应用程序代码中,我只是在此存储库上执行 findAll
:
(...)
outletRepo.findAll();
(...)
这会导致查询选择同一列两次,随后会出现来自 Spring 数据 ResultSetAccessor
:
DEBUG o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [
SELECT "outlet"."outlet_id" AS "outlet_id" FROM "outlet"]
DEBUG o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
DEBUG o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [
SELECT "offered_service"."id" AS "id",
"offered_service"."outlet_id" AS "outlet_id",
"offered_service"."id" AS "id"
FROM "offered_service"
WHERE "offered_service"."outlet_id" = ?]
TRACE o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value:
column index 1, parameter value [xyz012], value class [java.lang.String], SQL type 12
WARN o.s.d.j.core.convert.ResultSetAccessor : ResultSet contains id multiple times
WARN o.s.d.j.core.convert.ResultSetAccessor : ResultSet contains id multiple times
(...repeated many times...)
我在这里做错了什么?另外,对于 findAll
,这不应该首先是 JOIN
吗?
您有两件事映射到列 offered_service.outlet_id
:
从Outlet
到OfferedService
的一对多映射和属性OfferedService.outletId
.
如果这些应该不同,您可以使用注释来更改它们映射到的列,但我假设您是故意这样做的,以便在 OfferedService
中提供 outletId
实体。
虽然这可行,但它有点像 hack,可能会在未来的版本中崩溃。
推荐的做法是使用 @Transient
使 outletId
成为瞬态,并在添加 OfferedService
时使用纯 java 代码设置其值Outlet
.
有一篇关于此的博客文章:https://spring.io/blog/2021/09/22/spring-data-jdbc-how-do-i-make-bidirectional-relationships
似乎还有另一个问题,其中 Spring 数据 JDBC 执行 select OfferedService.id
两次。我不确定为什么会这样。对我来说看起来像个错误。但是您可能可以完全删除 id
,因为映射键和 outlet_id
应该形成一个完美的主键。