在为嵌套对象创建自定义 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 JPA GROUP BY 查询中返回自定义对象
spring data mongodb查询嵌套对象和嵌套对象的性能
Spring Data Neo4j - 将自定义分析器添加到 lucene 索引 (PerFieldAnalyzerWrapper)