UUID 主键未按预期映射到标准 existsById Jpa
UUID Primary Key not mapped as expected with standard existsById Jpa
我正在尝试引入 UUID 作为实体的主键,BINARY(16) 是其在 mysql 数据库中的表示形式。
我所拥有的是例如 UserId 是 UUID:
//the column definition in the Entity
@Id
@Column(name="user_id", columnDefinition = "BINARY(16)")
@ColumnTransformer(
read="bin_to_uuid(user_id)",
write="uuid_to_bin(?)")
private UUID userId;
//repository methods
@Transactional
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.userId= :id ")
int updateUserStatus(@Param("id") UUID id, @Param("status") UserStatus status);
@Query("SELECT count(u) from User u WHERE u.userId= bin_to_uuid(:id)")
int existsByUserId(@Param("id") UUID id);
但是请注意,在 existsByUserId 中我必须添加 bin_to_uuid(:id) 而不是直接比较。我不太明白为什么我必须这样做,我通过直接查看数据库中的查询找到了这个解决方法并想出了这个。更新查询不添加 bin_to_uuid 而 select 计数。标准的 existsById 实现也不适用于 UUID ..
我有关于此的附加代码:
public void updateUserStatus(UUID id, int status) throws UserNotFoundException {
int rowsUpdated = userRepository.updateUserStatus(id, UserStatus.values()[status]);
if (rowsUpdated == 0) {
throw new UserNotFoundException(id);
}
}
public List<User> getFollowedBloggersByUser(UUID id, Pageable p) throws UserNotFoundException {
if (userRepository.existsByUserId(id) == 0) {
throw new UserNotFoundException(id);
} else {
return userFollowRepository.findByFollowerId(id,p);
}
}
我不明白这两个查询之间的区别。但是在 DEBUG 模式下日志中的查询是:
update users set status=? where user_id=?
binding parameter [1] as [INTEGER] - [1]
binding parameter [2] as [BINARY] - [420090c1-1a28-11eb-b98e-00155d2849a9]
select count(1) as col_0_0_ from users user0_ where bin_to_uuid(user0_.user_id)=bin_to_uuid(?)
binding parameter [1] as [BINARY] - [9e9eeb09-6a6d-405d-abd6-802c9c2c811d]
mysql 常规日志显示如下:
update users set status=1 where user_id=x'420090C11A2811EBB98E00155D2849A9'
select count(1) as col_0_0_ from users user0_ where bin_to_uuid(user0_.user_id)=bin_to_uuid(x'9E9EEB096A6D405DABD6802C9C2C811D')
如果有人能指出我对此的解释或展示更好的方法,我将不胜感激。谢谢!
对于后代来说,事实证明,列变换器的读取部分绝对是多余的,并且会产生上述问题。 JPA 绝对能够将 uuid 正确显示为字符串。所以你只需要用 write 属性:
创建 columntransformer
@ColumnTransformer(write="uuid_to_bin(?)")
我正在尝试引入 UUID 作为实体的主键,BINARY(16) 是其在 mysql 数据库中的表示形式。
我所拥有的是例如 UserId 是 UUID:
//the column definition in the Entity
@Id
@Column(name="user_id", columnDefinition = "BINARY(16)")
@ColumnTransformer(
read="bin_to_uuid(user_id)",
write="uuid_to_bin(?)")
private UUID userId;
//repository methods
@Transactional
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.userId= :id ")
int updateUserStatus(@Param("id") UUID id, @Param("status") UserStatus status);
@Query("SELECT count(u) from User u WHERE u.userId= bin_to_uuid(:id)")
int existsByUserId(@Param("id") UUID id);
但是请注意,在 existsByUserId 中我必须添加 bin_to_uuid(:id) 而不是直接比较。我不太明白为什么我必须这样做,我通过直接查看数据库中的查询找到了这个解决方法并想出了这个。更新查询不添加 bin_to_uuid 而 select 计数。标准的 existsById 实现也不适用于 UUID ..
我有关于此的附加代码:
public void updateUserStatus(UUID id, int status) throws UserNotFoundException {
int rowsUpdated = userRepository.updateUserStatus(id, UserStatus.values()[status]);
if (rowsUpdated == 0) {
throw new UserNotFoundException(id);
}
}
public List<User> getFollowedBloggersByUser(UUID id, Pageable p) throws UserNotFoundException {
if (userRepository.existsByUserId(id) == 0) {
throw new UserNotFoundException(id);
} else {
return userFollowRepository.findByFollowerId(id,p);
}
}
我不明白这两个查询之间的区别。但是在 DEBUG 模式下日志中的查询是:
update users set status=? where user_id=?
binding parameter [1] as [INTEGER] - [1]
binding parameter [2] as [BINARY] - [420090c1-1a28-11eb-b98e-00155d2849a9]
select count(1) as col_0_0_ from users user0_ where bin_to_uuid(user0_.user_id)=bin_to_uuid(?)
binding parameter [1] as [BINARY] - [9e9eeb09-6a6d-405d-abd6-802c9c2c811d]
mysql 常规日志显示如下:
update users set status=1 where user_id=x'420090C11A2811EBB98E00155D2849A9'
select count(1) as col_0_0_ from users user0_ where bin_to_uuid(user0_.user_id)=bin_to_uuid(x'9E9EEB096A6D405DABD6802C9C2C811D')
如果有人能指出我对此的解释或展示更好的方法,我将不胜感激。谢谢!
对于后代来说,事实证明,列变换器的读取部分绝对是多余的,并且会产生上述问题。 JPA 绝对能够将 uuid 正确显示为字符串。所以你只需要用 write 属性:
创建 columntransformer@ColumnTransformer(write="uuid_to_bin(?)")