在为嵌套对象创建自定义 Spring Data JPA 查询时获取 IllegalArgumentException

Posted

技术标签:

【中文标题】在为嵌套对象创建自定义 Spring Data JPA 查询时获取 IllegalArgumentException【英文标题】:Getting IllegalArgumentException while creating custom Spring Data JPA query for nested object 【发布时间】:2019-11-15 11:08:26 【问题描述】:

我想创建一个自定义 Spring Data 查询,该查询将查找两个日期之间培训师的所有培训。

培训班长这样:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
@Builder
public class Training extends AbstractBaseEntity 

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @OneToMany(mappedBy = "training", cascade = CascadeType.ALL)
  List<Exercise> exercises = new ArrayList<>();

  @Column(name = "difficulty_level", nullable = false)
  @Enumerated(EnumType.STRING)
  private DifficultyLevel difficultyLevel;

  @Column(name = "completed")
  boolean completed;

  @OneToOne(targetEntity = Training.class, fetch = FetchType.LAZY)
  private TrainingParticipants trainingParticipants;

  @OneToOne(targetEntity = Training.class, fetch = FetchType.LAZY)
  private TrainingDate trainingDate;

嵌套类如:

@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TrainingParticipants 

  @Id
  @GeneratedValue
  private Long id;

  @OneToOne(targetEntity = TrainingParticipants.class)
  private User trainer;

  @ElementCollection(targetClass = TrainingParticipants.class)
  private Set<User> trainee;

@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
class TrainingDate 

  @Id
  @GeneratedValue
  private Long id;

  private LocalDateTime startDate;

  private LocalDateTime endDate;

HashCodeEquals 合约的 AbstractBaseEntity 和 @Version 用法如下所示:

@ToString
@MappedSuperclass
@Getter
@SuperBuilder
public abstract class AbstractBaseEntity 

  @Version
  protected long version = 0;

  @JsonIgnore
  @Transient
  protected UUID uuid = UUID.randomUUID();

  @Override
  public boolean equals(Object o) 
    if (this == o) 
      return true;
    
    if (o == null || getClass() != o.getClass()) 
      return false;
    
    AbstractBaseEntity that = (AbstractBaseEntity) o;
    return uuid.equals(that.getUuid());
  

  @Override
  public int hashCode() 
    return uuid.hashCode();
  

  public AbstractBaseEntity(long version) 
    this.version = version;
  

  public AbstractBaseEntity() 
  

我使用JpaRepository 使用方法创建了一个培训存储库,方法如下:

@Repository
interface TrainingRepository extends JpaRepository<Training, Long> 

  List<Training> findAllByTrainingParticipants_Trainer_IdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual(
      Long trainerId,
      LocalDateTime trainingStartDate,
      LocalDateTime trainingEndDate);

  default List<Training> findAllTrainerTrainingsBetweenStartAndEndDate(
      Long trainerId,
      LocalDateTime trainingStartDate,
      LocalDateTime trainingEndDate) 

    return findAllByTrainingParticipants_Trainer_IdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual(
        trainerId, trainingStartDate, trainingEndDate);
  

借助 IntelliJ 提示,我创建了一个自定义查询,它将找出两个日期之间的所有培训师培训。问题是,通过上述方法,我收到了一个异常,如下所示:

Caused by: java.lang.IllegalArgumentException: Failed to create the query for method public abstract java.util.List com.application.training.TrainingRepository.findAllByTrainingParticipants_Trainer_IdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual(java.lang.Long,java.time.LocalDateTime,java.time.LocalDateTime)! Unable to locate Attribute  with the the given name [trainer] on this ManagedType [com.application.common.AbstractBaseEntity]

我有点困惑,因为过去当我与正常工作的 IDE 提示合作时。同时,我知道我可以使用经典的 SQL 方法,但在这种情况下 Spring Data 是可取的。我将不胜感激有关如何修复查询并达到目标的建议。

编辑:

对于没有_ 分隔符的变体,我有如下错误:

Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.appplication.training.TrainingRepository.findAllByTrainingParticipantsTrainerIdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual(java.lang.Long,java.time.LocalDateTime,java.time.LocalDateTime)! Unable to locate Attribute  with the the given name [trainer] on this ManagedType [com.application.common.AbstractBaseEntity]

使用分隔符看起来像:

Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.application.training.TrainingRepository.findAllByTrainingParticipants_Trainer_IdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual(java.lang.Long,java.time.LocalDateTime,java.time.LocalDateTime)! Unable to locate Attribute  with the the given name [trainer] on this ManagedType [com.application.common.AbstractBaseEntity]

编辑 2: 建议@Simon Martinelli 后出现如下错误:

Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.application.training.TrainingRepository.findAllByTrainingParticipants_Trainer_IdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual(java.lang.Long,java.time.LocalDateTime,java.time.LocalDateTime)!

【问题讨论】:

为什么方法签名中有_?使用骆驼案 @SimonMartinelli 感谢您的回答,它用于课堂培训中的嵌套对象。删除后仍然无法正常工作。 能否更新异常信息 @SimonMartinelli 不幸的是,启动应用程序时错误是一样的。 Btu 你得到 findAllByTrainingParticipants_Trainer_IdAndTrainingStartDateLessThanEqualAndTrainingEndDateGreaterThanEqual 我说删除 _ 那么它应该是另一条消息 【参考方案1】:

您不能在像 trainingParticipants 这样的 ToMany 关系的查询中导航。

您必须加入这两个实体才能拥有 trainingParticipants 的别名。 因此,您不能为此查询使用 Spring Data JPA 查询方法,而必须创建 JPQL 查询或规范。

@Query("select t from Training t join t.trainingParticipants p " +
       "where p.trainer id = :trainerId and t.trainingDate.startDate <= :trainingStartDate " +
       "and t.trainingDate.endDate <= :trainingEndDate")
List<Training> findTrainingOfTrainer(Long trainerId, LocalDateTime trainingStartDate, LocalDateTime trainingEndDate);

【讨论】:

@非常感谢您的回答。在消除一个小错字 p.trainerId 并将 nativeQuery 标志设置为 true 后,应用程序启动时不会出现错误。我会尽快检查查询结果是否正确。到目前为止 big + 为您提供快速响应。 不,您不必将 nativeQuery 设置为 ture。这不是原生查询! 感谢您的耐心等待。问题是没有这个标志应用程序无法启动。我发布了一个错误作为编辑部分。我知道这不是本机查询,我检查这个标志只是为了测试目的,因为今天我在 IntelliJ 中遇到了一个非常奇怪的语法和提示问题,这对我来说完全无法理解。 尝试为方法使用另一个名称,例如 findTrainingFromTrainer

以上是关于在为嵌套对象创建自定义 Spring Data JPA 查询时获取 IllegalArgumentException的主要内容,如果未能解决你的问题,请参考以下文章

使用本机查询从 Spring Data 返回自定义对象

如何从 Spring Data JPA GROUP BY 查询中返回自定义对象

Spring Data JPA:嵌套实体的批量插入

使用 Spring DATA JPA 创建自定义查询?

spring data mongodb查询嵌套对象和嵌套对象的性能

Spring Data Neo4j - 将自定义分析器添加到 lucene 索引 (PerFieldAnalyzerWrapper)