[英]JPA Specifications with nested List
Heroes may not be in clubs.英雄可能不在俱乐部。 Heroes can be in one or more clubs.
英雄可以在一个或多个俱乐部中。
@Entity
@Table(name = "heroes")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Hero {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@OrderColumn(name = "name")
private String name;
@Column(name = "title")
private String title;
@ManyToOne(optional = false)
@JoinColumn(name = "hero_class_id")
@Getter
private HeroClass heroClass;
@ManyToMany
@JoinTable(name = "hero_club",
joinColumns = @JoinColumn(name = "hero_id"),
inverseJoinColumns = @JoinColumn(name = "club_id"))
private List<Club> clubs;
}
@Entity
@Table(name = "clubs")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Club {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@OrderColumn(name = "title")
private String title;
@OrderColumn(name = "description")
private String description;
}
public class HeroSpecifications {
public static Specification<Hero> likeName(String name) {
if (name == null) {
return null;
}
return (root, query, cb) -> cb.like(cb.lower(root.get(Hero_.NAME)), "%" + name.toLowerCase() + "%");
}
public static Specification<Hero> likeTitle(String title) {
if (title == null) {
return null;
}
return (root, query, cb) -> cb.like(cb.lower(root.get(Hero_.TITLE)), "%" + title.toLowerCase() + "%");
}
public static Specification<Hero> likeHeroClassDescription(String heroClassDescription) {
if (heroClassDescription == null) {
return null;
}
return (root, query, cb) -> cb.like(cb.lower(root.get(Hero_.heroClass).get("description")), "%" + heroClassDescription.toLowerCase() + "%");
}
public static Specification<Hero> inClubs(List<Integer> clubIdList) {
if (clubIdList == null) {
return null;
}
return (root, query, cb) -> {
return cb.and(cb.isNotEmpty(root.get(Hero_.CLUBS)), root.get(Hero_.CLUBS).get("id").in(clubIdList));
};
}
}
@Service
@RequiredArgsConstructor
public class HeroServiceImpl implements HeroService {
private final HeroRepository heroRepository;
...
@Override
public Page<Hero> searchHero(Pageable pageable, HeroSearchDTO heroSearchDTO) {
String name = heroSearchDTO.getName();
String title = heroSearchDTO.getTitle();
List<Integer> clubIdList = heroSearchDTO.getClubIdList();
String likeHeroClassDescription = heroSearchDTO.getHeroClassDescription();
return heroRepository.findAll(where(likeName(name)
.and(likeTitle(title))
.and(likeHeroClassDescription(likeHeroClassDescription))
.and(inClubs(clubIdList))), pageable);
}
}
Everything works except inClubs.除 inClubs 外,一切正常。
"Illegal attempt to dereference path source [null.clubs] of basic type; nested exception is java.lang.IllegalStateException: Illegal attempt to dereference path source [null.clubs] of basic type" “非法尝试取消引用基本类型的路径源 [null.clubs];嵌套异常是 java.lang.IllegalStateException:非法尝试取消引用基本类型的路径源 [null.clubs]”
The fact that heroes may not be in any club is OK.英雄可能不在任何俱乐部的事实是可以的。
Need use.join() instead of.get() here:这里需要 use.join() 而不是 .get() :
return (root, query, cb) -> root.join(Hero_.CLUBS).get(Club_.ID).in(clubIdList);
I hope someone will find it useful.我希望有人会发现它有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.