我有两个实体A
和B
。它们之间存在多对多关系,其中A
包含B
列表。 如何编写规范以检索包含具有特定名称的A
的所有B
个参与者?示例:
@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);
};
}
}
答案 0 :(得分:7)
尝试下一步:
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数据版 1.11.4
答案 1 :(得分:2)
花了一些时间才弄清楚为什么接受的答案对我没用。 我不得不这样做:
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