如何在JPAQuery中使用INNER JOIN?

约翰·学生

我精确地说,我是Java Developper一年级的法国学生。而且我很确定我的问题甚至对我想做的事情都不正确。然后,我希望下面的解释会更清楚!

我正在使用以下程序开发一个多模块应用程序:Spring Boot,Spring安全性,Hibernate,Spring Data,Spring MVC和Thymeleaf。

这是我的回购

我目前正在研究一种可处理多条件请求的方法。我正在使用Querydsl。

这是该领域涉及的部分:

母实体

@Entity
@Table(name="element")
@Inheritance(strategy = InheritanceType.JOINED)
@Getter
@Setter
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public abstract class Element {

//----------ATTRIBUTES----------

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    @NotNull
    @Size(min=4,max=50)
    private String name;
    private LocalDateTime createDate;
    private LocalDateTime updateDate;
    @OneToMany/*(mappedBy = "element")*/
    @JoinColumn(name = "element_id")
    private List< Comment > comments;
//..

子实体

/**
 * Bean used to define a book or a document that contains one or many climbing areas
 */
@Entity
@Table(name="atlas")
@PrimaryKeyJoinColumn(name = "element_id")
@Getter
@Setter
@NoArgsConstructor
@ToString( exclude = {"areas" , "bookingRequests" , "user"})
public class Atlas extends Element {

//----------ATTRIBUTES----------

    @ManyToMany
    @JoinTable(
        name = "areas_in_atlases",
        joinColumns = { @JoinColumn(name = "atlas_id") },
        inverseJoinColumns = { @JoinColumn(name = "area_id") } )
    private List< Area > areas;
    private String scale;
    private String country;
    private String region;
    private String department;
    private boolean available;
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
    @OneToMany(mappedBy = "atlas", cascade = CascadeType.ALL)
    private List<BookingRequest> bookingRequests;
//..



/**
 * Bean used to define an area with one or many climbing crag
 */
@Entity
@Table(name="area")
@PrimaryKeyJoinColumn(name = "element_id")
@Getter
@Setter
@NoArgsConstructor
@ToString
@EqualsAndHashCode( callSuper = true )
public class Area extends Element {

//----------ATTRIBUTES----------

    @ManyToMany(mappedBy = "areas")
    private List< Atlas > atlases;
    private Atlas atlas;
    @OneToMany/*(mappedBy = "area", fetch = FetchType.LAZY)*/
    @JoinColumn(name = "area_id")
    private List< Crag > crags;
    private int approachDuration;
    private String locality;
    @OneToMany/*(mappedBy = "area", fetch = FetchType.LAZY)*/
    @JoinColumn(name = "area_id")
    private List< Parking > parking;
    private String rockType;
//..

我的多标准方法的第一部分正在工作(我想不是很优雅):

@Override
public Page<Atlas> searchAtlasByNameAndCountryAndRegionAndDepartment( int page, int size, String name, String country, String region, String department ){

    QAtlas qAtlas = QAtlas.atlas;

    ArrayList< Predicate > predicates = new ArrayList<>();

    List<Atlas> atlases;

    if( !name.equals( "" ) ){
        predicates.add( qAtlas.name.containsIgnoreCase(name) );
    }
    if( !country.equals( "" ) ){
        predicates.add( qAtlas.country.containsIgnoreCase(country) );
    }
    if( !region.equals( "" ) ){
        predicates.add( qAtlas.region.containsIgnoreCase(region) );
    }
    if( !department.equals( "" ) ){
        predicates.add( qAtlas.department.containsIgnoreCase(department) );
    }

    BooleanBuilder booleanBuilder = new BooleanBuilder();

    for ( Predicate predicate: predicates ) {
        booleanBuilder.and(predicate);
    }

    atlases = ( List< Atlas > ) getDaoFactory().getAtlasRepository().findAll( booleanBuilder );

    long total = ( long ) atlases.size( );

    return new PageImpl(atlases, PageRequest.of( page, size ), total );
}

但是我迷上了将使用仅在Atlas中使用的字段(例如Country)在Area中进行搜索的方法。

    @Override
    public Page< Area > searchAreaByNameAndCountryAndRegionAndDepartment( int page, int size, String name, String country, String region, String department ){

        QAtlas qAtlas = QAtlas.atlas;
        QArea qArea = QArea.area;

        final JPAQueryFactory queryFactory = new JPAQueryFactory(em);


        List<Area> areas = queryFactory.selectFrom(qArea)
                                   .innerJoin(qAtlas)
                                   .where(
                                           qArea.name.containsIgnoreCase(name),
                                           qAtlas.country.containsIgnoreCase(country),
                                           qAtlas.department.containsIgnoreCase(department),
                                           qAtlas.region.containsIgnoreCase(region)
                                   )
                                   .fetch();

        long total = ( long ) areas.size( );

        return new PageImpl(areas, PageRequest.of( page, size ), total );
    }

当前控制台说:

ervlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'atlas.areas' [select area
from org.thibaut.wheretoclimb.model.entity.Area area
  inner join atlas.areas as area
where lower(area.name) like ?1 escape '!' and lower(atlas.country) like ?2 escape '!' and lower(atlas.department) like ?1 escape '!' and lower(atlas.region) like ?1 escape '!']] with root cause

org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'atlas.areas' [select area
from org.thibaut.wheretoclimb.model.entity.Area area
  inner join atlas.areas as area
where lower(area.name) like ?1 escape '!' and lower(atlas.country) like ?2 escape '!' and lower(atlas.department) like ?1 escape '!' and lower(atlas.region) like ?1 escape '!']

有谁可以帮我这个查询吗?

非常感谢您的宝贵时间!

解决方案:

public Page< Area > searchAreaByNameAndCountryAndRegionAndDepartment( int page, int size, String name, String country, String region, String department ){

        QAtlas qAtlas = QAtlas.atlas;
        QArea qArea = QArea.area;

        JPAQueryFactory queryFactory = new JPAQueryFactory(em);

        BooleanBuilder booleanBuilder = new BooleanBuilder();

        if( ! name.equals( "" ) ){
            booleanBuilder.and( qArea.name.containsIgnoreCase(name) );
        }
        if( ! country.equals( "" ) ){
            booleanBuilder.and( qAtlas.country.containsIgnoreCase(country) );
        }
        if( ! region.equals( "" ) ){
            booleanBuilder.and( qAtlas.region.containsIgnoreCase(region) );
        }
        if( ! department.equals( "" ) ){
            booleanBuilder.and( qAtlas.department.containsIgnoreCase(department) );
        }

        List<Area> areas = queryFactory.from(qAtlas)
                                   .innerJoin(qAtlas.areas, qArea)
                                   .where(booleanBuilder)
                                   .select(qArea)
                                   .fetch();

        long total = ( long ) areas.size( );

        return new PageImpl(areas, PageRequest.of( page, size ), total );
    }

非常感谢您的宝贵时间!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章