Select 只是实体集合的一个子集
Select only a subset of an Entities Collection
如果我有一个包含 @OneToMany
的实体,使用 JPA 我如何 select 实体并且只有相关 children 的一个子集?我无法使用 @Where
或 @Filter
注释。
更多详情
我正在将我们的业务模型转化为更通用的东西,所以不要担心这个例子在 IRL 中没有意义。但是查询有很多(比这个例子更多)left join fetch
个案例。朋友没有关系,只有一个字符串名称。
@Entity
public class Parent {
@Id
@GeneratedValue
private int parentId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "friendId")
private Friend friends;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL)
private Set<Child> childrenSet = new HashSet<>();
}
@Entity
public class Child {
@Id
@GeneratedValue
private int childId;
private boolean blonde;
@ManyToOne(fetchType.LAZY, cascade = CascadeType.ALL)
private Parent parent;
}
@Query( "SELECT p " +
"FROM Parent p " +
"JOIN FETCH p.friends f " +
"LEFT JOIN FETCH p.childrenSet c " +
"WHERE f.name IS NOT NULL " +
"AND c.blonde = true")
List<Parent> getParentsWithListOfOnlyBlondeChildren();
测试Class
@Transactional
@SpringBootTest
@RunWith(SpringRunner.class)
@DataJpaTest
public class TestParentRepo {
@PersistenceContxt
private EntityManager entityManager;
@Autowired
private ParentRepo parentRepo;
@Before
public void setup() {
Child c1 = new Child();
c1.setBlonde(true);
Child c2 = new Child();
c2.setBlonde(false);
Friend friend1 = new Friend();
friend1.setName("friend1");
Set<Child> children = new HashSet<>();
children.add(c1);
children.add(c2);
Parent parent1 = new Parent();
parent1.setFriends(friend1);
c1.setParent(parent1);
c2.setParent(parent1);
entityManager.persist(friend1);
entityManager.persist(parent1);
entityManager.persist(c1);
entityManager.persist(c2);
entityManager.flush();
entityManager.clear();
}
@Test
public void runTest() {
List<Parent> parent = parentRepo.getParentsWithListOfOnlyBlondeChildren();
System.out.println(parent);
}
}
现在调试时我 GET 是 Parent Object 和集合中的两个 children。我想要的是只有c1的parent(金发=真)。
查询必须是什么才能过滤掉不符合条件的相关 Child 实体?
我试图避免做:查询 Parents,每个 parent 查询 Children 匹配条件。
编辑
经过更多测试后,我发现这仅在 运行 测试时不起作用,即问题在于在单元测试中使用 H2 DB 获得预期结果。当 运行 一个实际的 MySQL 实例时查询工作正常。
你不需要 @Query
(至少对于像这样的简单查询),如果你正在使用 spring-data-jpa
,你可以在你的存储库中写一个这样的方法 class
List<Parent> findByChildrenSet_Blonde(boolean isBlonde)
spring-data 将通过查看方法名称为您制定和执行查询。 _
表示依赖class字段
现在你可以像这样调用这个函数了
findByChildrenSet_Blonde(true)
你也可以写成
List<Parent> findByChildrenSet_BlondeTrue()
如果我有一个包含 @OneToMany
的实体,使用 JPA 我如何 select 实体并且只有相关 children 的一个子集?我无法使用 @Where
或 @Filter
注释。
更多详情
我正在将我们的业务模型转化为更通用的东西,所以不要担心这个例子在 IRL 中没有意义。但是查询有很多(比这个例子更多)left join fetch
个案例。朋友没有关系,只有一个字符串名称。
@Entity
public class Parent {
@Id
@GeneratedValue
private int parentId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "friendId")
private Friend friends;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL)
private Set<Child> childrenSet = new HashSet<>();
}
@Entity
public class Child {
@Id
@GeneratedValue
private int childId;
private boolean blonde;
@ManyToOne(fetchType.LAZY, cascade = CascadeType.ALL)
private Parent parent;
}
@Query( "SELECT p " +
"FROM Parent p " +
"JOIN FETCH p.friends f " +
"LEFT JOIN FETCH p.childrenSet c " +
"WHERE f.name IS NOT NULL " +
"AND c.blonde = true")
List<Parent> getParentsWithListOfOnlyBlondeChildren();
测试Class
@Transactional
@SpringBootTest
@RunWith(SpringRunner.class)
@DataJpaTest
public class TestParentRepo {
@PersistenceContxt
private EntityManager entityManager;
@Autowired
private ParentRepo parentRepo;
@Before
public void setup() {
Child c1 = new Child();
c1.setBlonde(true);
Child c2 = new Child();
c2.setBlonde(false);
Friend friend1 = new Friend();
friend1.setName("friend1");
Set<Child> children = new HashSet<>();
children.add(c1);
children.add(c2);
Parent parent1 = new Parent();
parent1.setFriends(friend1);
c1.setParent(parent1);
c2.setParent(parent1);
entityManager.persist(friend1);
entityManager.persist(parent1);
entityManager.persist(c1);
entityManager.persist(c2);
entityManager.flush();
entityManager.clear();
}
@Test
public void runTest() {
List<Parent> parent = parentRepo.getParentsWithListOfOnlyBlondeChildren();
System.out.println(parent);
}
}
现在调试时我 GET 是 Parent Object 和集合中的两个 children。我想要的是只有c1的parent(金发=真)。
查询必须是什么才能过滤掉不符合条件的相关 Child 实体?
我试图避免做:查询 Parents,每个 parent 查询 Children 匹配条件。
编辑
经过更多测试后,我发现这仅在 运行 测试时不起作用,即问题在于在单元测试中使用 H2 DB 获得预期结果。当 运行 一个实际的 MySQL 实例时查询工作正常。
你不需要 @Query
(至少对于像这样的简单查询),如果你正在使用 spring-data-jpa
,你可以在你的存储库中写一个这样的方法 class
List<Parent> findByChildrenSet_Blonde(boolean isBlonde)
spring-data 将通过查看方法名称为您制定和执行查询。 _
表示依赖class字段
现在你可以像这样调用这个函数了
findByChildrenSet_Blonde(true)
你也可以写成
List<Parent> findByChildrenSet_BlondeTrue()