简体   繁体   English

JPA 规格与嵌套列表

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM