【问题标题】:JPA Specifications with nested List带有嵌套列表的 JPA 规范
【发布时间】:2022-01-20 21:58:39
【问题描述】:

英雄可能不在俱乐部。英雄可以在一个或多个俱乐部中。

@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);
    }
}

除 inClubs 外,一切正常。

“非法尝试取消引用基本类型的路径源 [null.clubs];嵌套异常是 java.lang.IllegalStateException:非法尝试取消引用基本类型的路径源 [null.clubs]”

英雄可能不在任何俱乐部这一事实是可以的。

【问题讨论】:

  • 您返回的是 null 而不是 Specification!

标签: spring-boot rest jpa many-to-many specifications


【解决方案1】:

这里需要使用 .join() 而不是 .get():

return (root, query, cb) -> root.join(Hero_.CLUBS).get(Club_.ID).in(clubIdList);

我希望有人会觉得它有用。

【讨论】:

    猜你喜欢
    • 2023-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2020-05-20
    • 1970-01-01
    • 2023-01-15
    • 2016-06-09
    相关资源
    最近更新 更多