You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring JPA用@EmbeddedId创建仓库报错:找不到UserRef的'empty'属性

问题描述

我尝试通过@Embeddable和@EmbeddedId创建Repository,相关代码如下:

UserRef 实体类

public class UserRef {  

  @EmbeddedId
  private UserRefId id;  
}

UserRefId 嵌入式ID类

public class UserRefId implements Serializable {

  @NotNull
  @Column(name = "USER_TYPE_CD")
  private String userTypeCd; 

  @NotNull
  @Column(name = "USER_INTERNAL_CD")
  private String userInternalCd; 
}

但运行应用时抛出异常:

nested exception is java.lang.IllegalArgumentException : Failed to create query for method public abstract repository.UserRefRepository.findById(java.lang.String) ! No property 'empty' found for type 'UserRef'

我的Repository接口代码如下:

@Repository
public interface UserRefRepository extends JpaRepository <UserRef, UserRefId> { 
  public Map<String, Map<String, String>>  findById (String refTypeCd); 
}

我尝试修改驼峰命名但完全无效,请问我哪里出错了?


问题原因及解决方法

核心问题

  1. 方法名冲突:JpaRepository自带了findById(ID id)默认方法,参数类型是你指定的泛型ID(UserRefId),返回Optional<T>。你自定义的findById(String refTypeCd)和默认方法重名,但参数、返回类型都不匹配,导致Spring Data JPA解析方法名时逻辑混乱,触发错误。
  2. 返回类型不合法:直接让Repository返回Map<String, Map<String, String>>不符合Spring Data JPA的方法返回规则,复杂集合类型会加剧解析错误。
  3. 嵌入式ID类缺失必要注解:UserRefId没有添加@Embeddable注解,JPA无法识别它是可嵌入的ID类。

解决步骤

  1. 重命名自定义方法
    改成和默认findById不冲突的名字,同时遵循嵌入式属性的路径命名规则(用id.属性名的结构):

    @Repository
    public interface UserRefRepository extends JpaRepository<UserRef, UserRefId> {
        // 对应UserRef.id.userTypeCd的属性路径
        List<UserRef> findByIdUserTypeCd(String refTypeCd);
    }
    
  2. 调整返回类型
    Repository优先返回实体或实体集合,如需Map结构,在业务层将查询结果转换:

    // 业务层示例
    public Map<String, Map<String, String>> convertToMap(List<UserRef> userRefs) {
        return userRefs.stream()
                .collect(Collectors.groupingBy(
                    ref -> ref.getId().getUserTypeCd(),
                    Collectors.toMap(
                        ref -> ref.getId().getUserInternalCd(),
                        ref -> // 这里映射你需要的值
                    )
                ));
    }
    
  3. 完善嵌入式ID类
    添加@Embeddable注解,同时补充无参构造函数、equals和hashCode方法(JPA强制要求):

    @Embeddable
    public class UserRefId implements Serializable {
    
        @NotNull
        @Column(name = "USER_TYPE_CD")
        private String userTypeCd; 
    
        @NotNull
        @Column(name = "USER_INTERNAL_CD")
        private String userInternalCd; 
    
        // 无参构造函数
        public UserRefId() {}
    
        // 带参构造函数(可选,方便使用)
        public UserRefId(String userTypeCd, String userInternalCd) {
            this.userTypeCd = userTypeCd;
            this.userInternalCd = userInternalCd;
        }
    
        // 重写equals和hashCode
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            UserRefId userRefId = (UserRefId) o;
            return Objects.equals(userTypeCd, userRefId.userTypeCd) && Objects.equals(userInternalCd, userRefId.userInternalCd);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(userTypeCd, userInternalCd);
        }
    
        // getter、setter方法
        public String getUserTypeCd() { return userTypeCd; }
        public void setUserTypeCd(String userTypeCd) { this.userTypeCd = userTypeCd; }
        public String getUserInternalCd() { return userInternalCd; }
        public void setUserInternalCd(String userInternalCd) { this.userInternalCd = userInternalCd; }
    }
    

内容的提问来源于stack exchange,提问作者DoGoodToEveryone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:38:20