【问题标题】:Spring Data Specification for set contains operation集合的 Spring 数据规范包含操作
【发布时间】:2018-05-22 17:02:27
【问题描述】:

我有两个实体,AB。它们之间存在多对多关系,其中A 持有B 的列表。 如何编写规范以检索所有包含具有特定名称的BA 实体?示例:

@Service
public class YourService {

    @Resource
    private ARepository repository;

    // I know how to do this type of queries with specifications
    public List<A> getByB(B b) {
        return repository.findAll(Specifications.containsB(b));
    }

    //Question: how to write Specification for this type of query?
    public List<A> getByNameOfB(String name) {
         return repository.findAll(Specifications.containsBWithName(name));
    }
} 

实体:

@Entity
public class B {

        @Id
        @SequenceGenerator(sequenceName = "B_SEQ", name = "BSeq", allocationSize = 1)
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BSeq")
        private Long id;

        @Column(unique = true, updatable = false)
        private String name;
}

@Entity
public class A {

    @Id
    @SequenceGenerator(sequenceName = "A_SEQ", name = "ASeq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ASeq")
    private Long id;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "A_B",
            joinColumns = {@JoinColumn(name = "A_ID", nullable = false, updatable = false)},
            inverseJoinColumns = {@JoinColumn(name = "B_ID", nullable = false, updatable = false)})
    @Fetch(value = FetchMode.SUBSELECT)
    private List<B> bList;
}

元模型:

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(A.class)
public class A_ {
    public static volatile ListAttribute<A, B> bList;
}


@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(B.class)
public class B_ {
    public static volatile SingularAttribute<B, String> name;
}

检索:

public interface ARepository extends JpaRepository<A, Long>, JpaSpecificationExecutor<A> {
}

public class Specifications {

    public static Specification<A> containsB(B b) {
        return (root, query, cb) -> {
            Expression<List<B>> bList = root.get(A_.bList);
            return cb.isMember(b, bList);
        };
    }

    // HERE IS A QUESTION:

    public static Specification<A> containsBWithName(String name) {
        return (root, query, cb) -> {
            ListJoin<List<B>> bList = root.join(A_.bList);
            Expression<String> exp = bList.get(B_.name)
            //TODO how to check that name is one of the retrieved names?
            //PROBLEM, method below expects Expression<List<String>> instead of Expression<String>
            cb.isMember(name, exp); 
        };
    }
}

【问题讨论】:

    标签: java spring-data-jpa spring-data criteria-api


    【解决方案1】:

    我花了一些时间才弄清楚为什么接受的答案对我不起作用。 我必须这样做:

    public static Specification<A> containsBWithName(String name) {
        return (root, query, cb) -> {
            Join<Object, Object> bListJoin = root.join("bList", JoinType.INNER);
            return cb.equal(bListJoin.get("name"), name);
        };
    }
    

    Spring Data 1.11.9

    【讨论】:

    • 这个答案对我有用,而不是被接受的答案。春季数据 2.14
    【解决方案2】:

    尝试下一步:

    public static Specification<A> containsBWithName(String name) {
        return (root, query, cb) -> {
            root.join("bList", JoinType.INNER);
            return cb.equal(root.get("bList").get("name"), name);
        };
    }
    

    希望它能解决问题。

    Spring Data 版本 1.11.4

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多