Выберите только подмножество коллекции сущностей - PullRequest
0 голосов
/ 26 марта 2020

Если у меня есть сущность, которая содержит @OneToMany, с использованием JPA Как выбрать сущность и только подмножество связанных дочерних элементов? Я не могу использовать аннотации @Where или @Filter.

Подробнее Я перевожу нашу бизнес-модель во что-то более общее, поэтому не беспокойтесь о примере, не имеющем смысла в реале Но у Query есть много (больше, чем этот пример) случаев 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();

Тестовый класс

@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);
    }
}

Теперь при отладке I GET является родительским объектом с ОБА дочерними элементами в наборе. Что я ХОЧУ является родителем только с c1 (блондин = истина).

Каким должен быть запрос, чтобы отфильтровать связанные дочерние объекты, которые не соответствуют критериям?

Я стараюсь избегать выполнения: Query Parents, для каждого родителя Query Children, соответствующего критериям. Редактировать После дополнительного тестирования я обнаружил, что это не работает только при выполнении тестов, ie, проблема заключается в получении ожидаемого результата с использованием H2 DB в модульных тестах. Запрос работает нормально при работе с фактическим MySQL экземпляром.

1 Ответ

0 голосов
/ 26 марта 2020

Вам не нужно @Query (по крайней мере, для простых запросов, подобных этому). Если вы используете spring-data-jpa, вы можете просто написать такой метод в своем классе репозитория

List<Parent> findByChildrenSet_Blonde(boolean isBlonde)

spring -data сформулирует и выполнит запрос для вас, посмотрев на имя метода. _ означает поле зависимого класса

Теперь вы можете вызывать эту функцию следующим образом

findByChildrenSet_Blonde(true)

Вы также можете написать

List<Parent> findByChildrenSet_BlondeTrue()
...