Spring Boot JPA HQL查询-如何检查数组内部元素的某个值

oxcyiej7  于 2023-03-18  发布在  Spring
关注(0)|答案(1)|浏览(174)

bounty将在7天后过期。回答此问题可获得+50声望奖励。lingar希望引起更多人关注此问题。

今天我有了这个过滤器。它起作用了。

@Query(value =  "SELECT DISTINCT e from SocialEvent e "
        + "join e.multiPropsValuesSet m "
        + "WHERE ( "
        + "((m in ?1   OR COALESCE(?1, NULL) is null )"     
        +")"
        +" AND  (COALESCE(?2, NULL) is null  OR m in ?2 ) "
        + "AND  (COALESCE(?3, NULL) is null  OR m in ?3 ) "
        + ") "
        + "AND "
        + "((e.fromAge BETWEEN ?4 AND ?5) "
        + "OR (e.toAge BETWEEN ?4 AND ?5)"
        + "OR (?4 BETWEEN e.fromAge AND e.toAge )) "
        + "AND (e.date BETWEEN ?6 AND ?7) "
        + "ORDER BY e.date ASC"   /*, nativeQuery=true - cause errror*/)
List<SocialEvent> filter16Main(
        List <MultiPropValue> eventTypes,
        List <MultiPropValue> areas, List <MultiPropValue> jewLvlKeep,
        int fromAge, int toAge,
        Date from , Date to);

List eventTypes表示一些对象的集合(列表)。
每个多属性值都有一个列表形式的connectedValuesId。

我想在查询中添加一个条件,该条件将在连接值的每个项目内部进行搜索。
例如,我想添加以下内容:

@Query(value =  "SELECT DISTINCT e from SocialEvent e "
            + "join e.multiPropsValuesSet m "
            + "WHERE ( "
            + "(("
            + "(m in ?1   OR COALESCE(?1, NULL) is null )"
            + " OR "
            + "(m.id in ?1.connectedValuesIds ) "   //--->new condition.    
            +")"
            +" AND  (COALESCE(?2, NULL) is null  OR m in ?2 ) "
            + "AND  (COALESCE(?3, NULL) is null  OR m in ?3 ) "
            + ") "
            + "AND "
            + "((e.fromAge BETWEEN ?4 AND ?5) "
            + "OR (e.toAge BETWEEN ?4 AND ?5)"
            + "OR (?4 BETWEEN e.fromAge AND e.toAge )) "
            + "AND (e.date BETWEEN ?6 AND ?7) "
            + "ORDER BY e.date ASC"   /*, nativeQuery=true - cause errror*/)
    List<SocialEvent> filter16Main(
            List <MultiPropValue> eventTypes,
            List <MultiPropValue> areas, List <MultiPropValue> jewLvlKeep,
            int fromAge, int toAge,
            Date from , Date to);

我知道我需要的步骤是:
1.从集合项中获取所有connectedValuesId。
1.检查是否m.id在此处找到www.example.com。

换句话说-我想检查集合内部元素的一些属性

以上代码在启动应用程序时生成此错误:

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: 1. near line 1, column 178 [SELECT DISTINCT e from com.lingar.SocialEvents.socialEvent.entities.SocialEvent e join e.multiPropsValuesSet m WHERE ( (((m in ?1   OR COALESCE(?1, NULL) is null ) OR (m.id in ?1.connectedValuesIds ) ) AND  (COALESCE(?2, NULL) is null  OR m in ?2 ) AND  (COALESCE(?3, NULL) is null  OR m in ?3 ) ) AND ((e.fromAge BETWEEN ?4 AND ?5) OR (e.toAge BETWEEN ?4 AND ?5)OR (?4 BETWEEN e.fromAge AND e.toAge )) AND (e.date BETWEEN ?6 AND ?7) ORDER BY e.date ASC]

我已经尝试了很多东西,也在谷歌上搜索了很多。
我不希望对exist查询进行重大更改。

以简单的方式实现它的正确方法是什么?

其他相关代码:

实体:

public class SocialEvent {
    
    
    //...
    @ManyToMany
    @CollectionTable(name="social_events_multi_values")
    private Set<MultiPropValue> multiPropsValuesSet = new HashSet<MultiPropValue>();

多属性值的父级:

@Data
@MappedSuperclass
    public abstract class TextPiece {
    //...
    @ElementCollection
        @CollectionTable    
        private List<Long> connectedValuesIds = new ArrayList<>();
 }

多属性值:

public class MultiPropValue extends TextPiece{
    private @Id 
//...
}
tjvv9vkg

tjvv9vkg1#

基本思想是创建一个实用方法来提取id列表并利用SpEL,类似于:

package tld;

...

public interface SocialEventRepository extends JpaRepository<SocialEvent, Long> {

    @Query(value = "SELECT DISTINCT e from SocialEvent e "
            + "join e.multiPropsValuesSet m "
            + "WHERE ( "
            + "(("
            + "(m in ?1   OR COALESCE(?1, NULL) is null )"
            + " OR "
            + "(m.id in (:#{T(tld.SocialEventRepository).extractIds(#eventTypes)})) "   //--->new condition.
            + ")"
            + " AND  (COALESCE(?2, NULL) is null  OR m in ?2 ) "
            + "AND  (COALESCE(?3, NULL) is null  OR m in ?3 ) "
            + ") "
            + "AND "
            + "((e.fromAge BETWEEN ?4 AND ?5) "
            + "OR (e.toAge BETWEEN ?4 AND ?5)"
            + "OR (?4 BETWEEN e.fromAge AND e.toAge )) "
            + "AND (e.date BETWEEN ?6 AND ?7) "
            + "ORDER BY e.date ASC")
    List<SocialEvent> filter16Main(
            List<MultiPropValue> eventTypes,
            List<MultiPropValue> areas, List<MultiPropValue> jewLvlKeep,
            int fromAge, int toAge,
            Date from, Date to);

    static List<Long> extractIds(List<MultiPropValue> values) {
        return values.stream().map(MultiPropValue::getConnectedValuesIds)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }
}

不过,我会推荐给move to Criteria API

相关问题