编辑:好的,我在这里搞得一团糟,但我希望这次我更接近正确的答案。
考虑一下(id像John的1一样自动生成,等等):
INSERT INTO some_user (name) VALUES ('John');INSERT INTO some_user (name) VALUES ('Ariel');INSERT INTO some_user (name) VALUES ('Brian');INSERT INTO some_user (name) VALUES ('Kelly');INSERT INTO some_user (name) VALUES ('Tom');INSERT INTO some_user (name) VALUES ('Sonya');INSERT INTO product (owner_id,name) VALUES (1,'Nokia 3310');INSERT INTO product (owner_id,name) VALUES (2,'Sony Xperia Aqua');INSERT INTO product (owner_id,name) VALUES (3,'IPhone 4S');INSERT INTO product (owner_id,name) VALUES (1,'Xiaomi MI5');INSERT INTO product (owner_id,name) VALUES (3,'Samsung Galaxy S7');INSERT INTO product (owner_id,name) VALUES (3,'Sony Xperia Z3');INSERT INTO following_relationship (follower_id, owner_id) VALUES (4,1);INSERT INTO following_relationship (follower_id, owner_id) VALUES (5,1);INSERT INTO following_relationship (follower_id, owner_id) VALUES (4,2);INSERT INTO following_relationship (follower_id, owner_id) VALUES (6,2);INSERT INTO following_relationship (follower_id, owner_id) VALUES (6,3);INSERT INTO following_relationship (follower_id, owner_id) VALUES (1,3);基于您提供的实体的简化版本,以及SomeUser Entity,例如:
@Entitypublic class FollowingRelationship {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private Long id;@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)@JoinColumn(name = "owner_id")SomeUser owner;@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)@JoinColumn(name = "follower_id")SomeUser follower;...@Entitypublic class Product {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private Long id;@ManyToOne()@JoinColumn(name = "owner_id")private SomeUser owner;@Columnprivate String name;...@Entitypublic class SomeUser {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private Long id;@Columnprivate String name;@oneToMany(mappedBy = "owner")private Set<Product> products = new HashSet<Product>();@oneToMany(mappedBy = "owner")private Set<FollowingRelationship> ownedRelationships = new HashSet<FollowingRelationship>();@oneToMany(mappedBy = "follower")private Set<FollowingRelationship> followedRelationships = new HashSet<FollowingRelationship>();我创建了像这样的规范:
public static Specification<Product> joinTest(SomeUser input) { return new Specification<Product>() { public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Join<Product,SomeUser> userProd = root.join("owner"); Join<FollowingRelationship,Product> prodRelation = userProd.join("ownedRelationships"); return cb.equal(prodRelation.get("follower"), input); } };}现在,当我们执行以下查询时:
SomeUser someUser = someUserRepository.findOne(Specifications.where(ProductSpecifications.userHasName("Kelly")));List<Product> thatProducts = productRepository.findAll(Specifications.where(ProductSpecifications.joinTest(someUser)));System.out.println(thatProducts.toString());我们得到:
[Product [id=1, name=Nokia 3310], Product [id=4, name=Xiaomi MI5], Product [id=2, name=Sony Xperia Aqua]]
在我看来,这等效于:“从另一个用户关注的所有用户那里获取所有产品”-获取Kelly正在关注的所有用户的产品。



