java - 在为嵌套对象创建自定义 Spring Data JPA 查询时获取 IllegalArgumentException
问题描述
我想创建一个自定义 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 合约和 @Version 用法的 AbstractBaseEntity 如下所示:
@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)!
解决方案
您不能在像 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);
推荐阅读
- python - 我如何知道 linebot URITemplateAction 中选择了哪个选项?
- arrays - Kotlin:十位数
- python - Dockerfile:pip install 失败并显示 requirements.txt(但成功使用单个包)
- python-3.x - 如何在条件位于列表中的情况下使用 np
- flutter - 颤振相机包显示时间码
- javascript - 解构 props 和 state 导致 ESlint 中的未使用状态错误
- mysql-workbench - 如何从工作台中删除例程组错误?
- c# - 发送可分辨 CA 列表作为 TLS 握手服务器 Hello 的一部分
- vpn - shadowsocks 或 l2tp 更快更稳定
- compilation - 在linux中编译tcl文件