SpringBoot JPA使用UUID从MySQL查询记录返回null问题
问题:MySQL中UUID作为实体ID,JPA按ID查询返回null(数据库存在对应记录)
在MySQL数据库中使用UUID作为实体主键,通过JPA的findById方法查询时始终返回null,但通过Workbench确认数据库中确实存在该ID对应的记录。尝试将UUID以VARCHAR类型存储后问题仍未解决。
相关代码如下:
初始BaseEntity
@Getter(AccessLevel.PUBLIC) @MappedSuperclass public abstract class BaseEntity { @Id() @GeneratedValue(strategy = GenerationType.UUID) UUID id; @CreationTimestamp Date createdAt; }
ArticlesRepository
@Repository public interface ArticlesRepository extends JpaRepository<ArticleEntity, UUID> { ArticleEntity findBySlug(String slug); Optional<ArticleEntity> findById(UUID id); }
ArticlesService
@Service public class ArticlesService { public final ArticlesRepository articlesRepository; public final UsersRepository usersRepository; public ArticlesService( ArticlesRepository articlesRepository, UsersRepository usersRepository ) { this.articlesRepository = articlesRepository; this.usersRepository = usersRepository; } public List<ArticleEntity> getAllArticles(){ List<ArticleEntity> articlesIterable = articlesRepository.findAll(); return StreamSupport.stream(articlesIterable.spliterator(),false) .collect(Collectors.toList()); } public ArticleEntity getArticleBySlug(String slug){ var article = articlesRepository.findBySlug(slug); if(slug==null){ return null; } return article; } public ArticleEntity createArticle(CreateArticleDTO createArticleDTO, String authorUsername){ var author = usersRepository.findByUsername(authorUsername); return articlesRepository.save( ArticleEntity.builder() .title(createArticleDTO.getTitle()) .slug(createArticleDTO.getTitle().toLowerCase().replaceAll(" ","-")) .subtitle(createArticleDTO.getSubtitle()) .body(createArticleDTO.getBody()) .author(author) .build() ); } public Optional<ArticleEntity> getArticleById(UUID id){ return articlesRepository.findById(id); } }
尝试修改后的BaseEntity(无效)
public abstract class BaseEntity { @Id() @GeneratedValue(strategy = GenerationType.UUID) @JdbcTypeCode(SqlTypes.BINARY) UUID id; @CreationTimestamp Date createdAt; }
解决方案
1. 对齐数据库字段类型与JPA映射
MySQL存储UUID推荐用CHAR(36)(UUID字符串固定36位含连字符),同时明确JPA字段映射:
@Id @GeneratedValue(strategy = GenerationType.UUID) @Column(columnDefinition = "CHAR(36)") private UUID id;
2. 统一UUID大小写格式
若数据库字段使用区分大小写的排序规则(如utf8mb4_bin),需确保JPA生成的UUID与数据库存储的大小写一致:
- 存储时强制转小写/大写
- 查询时校验传入UUID的格式匹配数据库存储值
3. 校验UUID生成与存储格式一致性
检查GenerationType.UUID生成的UUID是否带连字符,若数据库存储的是无连字符的32位字符串,会导致匹配失败。手动打印生成的UUID和数据库中的值对比,确保格式完全一致。
4. 避免不必要的二进制存储
@JdbcTypeCode(SqlTypes.BINARY)会将UUID转为二进制字节数组存储,若未配置正确的类型转换器,极易导致查询匹配失败。非特殊需求建议直接用字符串存储UUID。
5. 清除EntityManager缓存
若之前查询过该ID返回null,一级缓存可能留存错误结果,可调用entityManager.clear()清除缓存后再查询,或使用findById的重载方法指定LockModeType.NONE绕过缓存。
内容的提问来源于stack exchange,提问作者Darth Plagueis
相关产品推荐
相关产品推荐

