RSQL JPA 使用映射表

问题描述

使用以下库帮助我在简单的标签搜索中实现一些逻辑过滤器:

    <dependency>
        <groupId>cz.jirutka.rsql</groupId>
        <artifactId>rsql-parser</artifactId>
        <version>2.1.0</version>
    </dependency>
    <dependency>
        <groupId>com.github.tennaito</groupId>
        <artifactId>rsql-jpa</artifactId>
        <version>2.0.2</version>
    </dependency>

这是我的两个 DAO 对象标签和目标,中间有一个简单的映射表:

标签

@Entity
@Table(name="tags")
public class Tag implements Comparable<Tag> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "tags_Seq")
    @SequenceGenerator(name = "tags_Seq",sequenceName = "tags_seq",allocationSize = 1)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name",unique = true)
    private String name;

    @Temporal( TemporalType.TIMESTAMP)
    @Column(name="creation_timestamp")
    @JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
    private Date created;

    @ManyToMany(mappedBy="tags")
    @JsonManagedReference
    List<Target> targets;

目标

@Entity
@Table(name="target",uniqueConstraints=@UniqueConstraint(columnNames={"target_id","target_name"}))
public class Target implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public enum TargetName {
        USER
    }


    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "tag_targets_Seq")
    @SequenceGenerator(name = "tag_targets_Seq",sequenceName = "tag_targets_seq",allocationSize = 1)
    private Integer id;


    @Column(name = "target_id")
    private Integer targetId;

    @Column(name = "target_name")
    @Enumerated(EnumType.STRING)
    private TargetName targetName;

    @Column(name = "active")
    private boolean active;

    @Temporal( TemporalType.TIMESTAMP)
    @Column(name="creation_timestamp")
    private Date created;

    @Temporal( TemporalType.TIMESTAMP)
    @Column(name="last_update_timestamp")
    private Date updated;

    @ManyToMany
    @JoinTable(name="tag_target",joinColumns = @JoinColumn(name = "Target_id",referencedColumnName = "ID"),inverseJoinColumns = @JoinColumn(name = "Tag_id",referencedColumnName = "ID")
    )
    @JsonBackReference
    private Set<Tag> tags= new HashSet<>();

    public void setTag(Tag tag){
        this.tags.add(tag);
    }

    public List<String> getTagsList(){
        List<String> list = new ArrayList<>();
        for(Tag t : this.tags){
            list.add(t.getName());
        }
        return list;
    }

我正在尝试实现 rsql 查询字符串搜索,以便:

    public List<Target> searchByQuery(String queryString) {
    RsqlVisitor<CriteriaQuery<Target>,EntityManager> visitor = new JpaCriteriaQueryVisitor<>();
    CriteriaQuery<Target> query;
    query = getCriteriaQuery(queryString,visitor);
    List<Target> resultList = entityManager.createquery(query).getResultList();
    if (resultList == null || resultList.isEmpty()){
        return Collections.emptyList();
    }
    return resultList;
}

private <T> CriteriaQuery<T> getCriteriaQuery(String queryString,RsqlVisitor<CriteriaQuery<T>,EntityManager> visitor) {
    Node rootNode;
    CriteriaQuery<T> query;
    try {
        rootNode = new RsqlParser().parse(queryString);
        query = rootNode.accept(visitor,entityManager);
    }catch (Exception e){
        //log.error("An error happened while executing Rsql query",e);
        throw new IllegalArgumentException(e.getMessage());
    }
    return query;
}

但是,当我不传递字符串时,它们似乎没有考虑对象之间的映射,例如,如果我传递:

search?query=(tags.name==test;tags.name!=PS4)

是的,我取回了带有 PS4 标签的商品

[
    {
        "id": 4,"targetId": 22,"targetName": "USER","active": false,"created": "2021-05-26T04:43:32.025+00:00","updated": "2021-05-26T04:43:32.025+00:00","tagsList": [
            "test","PS4"
        ]
    },{
        "id": 5,"targetId": 1,"created": "2021-05-26T04:43:46.873+00:00","updated": "2021-05-26T04:43:46.873+00:00","tagsList": [
            "test"
        ]
    }
]

在幕后,这就是 lib 正在做的事情:

2021-05-25 22:32:23,588 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.JpaCriteriaQueryVisitor: Creating CriteriaQuery for AndNode: (tags.name=='test';tags.name!='PS4')
2021-05-25 22:32:23,590 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.JpaPredicateVisitor: Creating Predicate for AndNode: (tags.name=='test';tags.name!='PS4')
2021-05-25 22:32:23,590 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating Predicate for logical node: (tags.name=='test';tags.name!='PS4')
2021-05-25 22:32:23,591 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating Predicates from all children nodes.
2021-05-25 22:32:23,591 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating Predicate for: tags.name=='test'
2021-05-25 22:32:23,591 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating Predicate for comparison node: tags.name=='test'
2021-05-25 22:32:23,591 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Property graph path : tags.name
2021-05-25 22:32:23,592 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Create a join between com.getinsured.tag.model.dao.TagTarget and com.getinsured.tag.model.dao.Tag.
2021-05-25 22:32:23,592 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Create property path for type com.getinsured.tag.model.dao.Tag property name.
2021-05-25 22:32:23,592 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Cast all arguments to type java.lang.String.
2021-05-25 22:32:23,592 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.misc.DefaultArgumentParser: Parsing argument 'test' as type String,thread http-nio-8088-exec-4
2021-05-25 22:32:23,592 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating predicate: propertyPath == [test]
2021-05-25 22:32:23,593 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating Predicate for: tags.name!='PS4'
2021-05-25 22:32:23,593 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating Predicate for comparison node: tags.name!='PS4'
2021-05-25 22:32:23,593 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Property graph path : tags.name
2021-05-25 22:32:23,593 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Create a join between com.getinsured.tag.model.dao.TagTarget and com.getinsured.tag.model.dao.Tag.
2021-05-25 22:32:23,598 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Create property path for type com.getinsured.tag.model.dao.Tag property name.
2021-05-25 22:32:23,599 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Cast all arguments to type java.lang.String.
2021-05-25 22:32:23,599 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.misc.DefaultArgumentParser: Parsing argument 'PS4' as type String,599 INFO  [http-nio-8088-exec-4] com.github.tennaito.rsql.jpa.PredicateBuilder: Creating predicate: propertyPath != [PS4]
Hibernate: select tagtarget0_.id as id1_2_,tagtarget0_.active as active2_2_,tagtarget0_.creation_timestamp as creation3_2_,tagtarget0_.target_id as target_i4_2_,tagtarget0_.target_name as target_n5_2_,tagtarget0_.last_update_timestamp as last_upd6_2_ from target tagtarget0_ inner join tag_target tags1_ on tagtarget0_.id=tags1_.target_id inner join tags tag2_ on tags1_.tag_id=tag2_.id inner join tag_target tags3_ on tagtarget0_.id=tags3_.target_id inner join tags tag4_ on tags3_.tag_id=tag4_.id where (lower(tag2_.name) like ?) and (lower(tag4_.name) not like ?)
Hibernate: select tags0_.target_id as target_i1_0_0_,tags0_.tag_id as tag_id2_0_0_,tag1_.id as id1_1_1_,tag1_.creation_timestamp as creation2_1_1_,tag1_.name as name3_1_1_ from tag_target tags0_ inner join tags tag1_ on tags0_.tag_id=tag1_.id where tags0_.target_id=?
Hibernate: select tags0_.target_id as target_i1_0_0_,tag1_.name as name3_1_1_ from tag_target tags0_ inner join tags tag1_ on tags0_.tag_id=tag1_.id where tags0_.target_id=?

理想情况下,这将返回具有“test”标签但没有 PS4 的目标,如果有人能指出我如何使用带有 rsql-jpa 的映射表的正确方向,那就太好了! 'm 在类似于此处描述的 toxi 设计之后,但在 rsql 中:

http://howto.philippkeller.com/2005/04/24/Tags-Database-schemas/

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)