У меня ниже двух сущностей. Сущность Instructor имеет отношение oneToMany к сущности Vehicle.
public class Instructor {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
private int id;
@Version
@Column(columnDefinition = "int(11) not null default 0")
private int version = 0;
@OneToMany(mappedBy = "instructor", orphanRemoval = true, cascade = CascadeType.ALL)
private Set<Vehicle> vehicles = new HashSet<>();
.....
public class Vehicle {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator =
"native")
@GenericGenerator(name = "native", strategy = "native")
private int id;
@ManyToOne(fetch = FetchType.LAZY)
private Student student;
@ManyToOne(fetch = FetchType.LAZY)
private Instructor instructor;
Я хочу получить всех инструкторов вместе с их транспортными средствами в одном запросе.Ниже я попробовал четыре способа сделать это, но я не могу сделать это с тестовым примером 2, 3 и 4.
Тестовый пример 1: с предложением JPQL join fetch.
@Test
@Transactional
@Rollback(false)
public void fetchTest1(){
List<Instructor> instructorsJpqlJoinFetch = em
.createQuery("select distinct i from
Instructor i join fetch i.vehicles v ",
Instructor.class)
.getResultList();
print(instructorsJpqlJoinFetch);
}
private void print(List<Instructor> instructors) {
instructors.forEach(i -> {
System.out.println("######Instructor Name : " + i.getName());
i.getVehicles().forEach(v -> {
System.out.println("######Instructor Vehicle
Number : " + v.getVehicleNumber());
});
});
Db Запрос отправлен в БД для случая 1:
select
distinct instructor0_.id as id1_2_0_,
vehicles1_.id as id1_5_1_,
instructor0_.address as address2_2_0_,
instructor0_.birth_date_time as birth_da3_2_0_,
instructor0_.birth_date_time_zone_offset as birth_da4_2_0_,
instructor0_.created_date as created_5_2_0_,
instructor0_.day_off_time as day_off_6_2_0_,
instructor0_.day_start_time as day_star7_2_0_,
instructor0_.father_name as father_n8_2_0_,
instructor0_.mother_name as mother_n9_2_0_,
instructor0_.name as name10_2_0_,
instructor0_.photo as photo11_2_0_,
instructor0_.monthly_salary as monthly12_2_0_,
instructor0_.updated_date as updated13_2_0_,
instructor0_.version as version14_2_0_,
vehicles1_.creation_date as creation2_5_1_,
vehicles1_.instructor_id as instruct8_5_1_,
vehicles1_.purchased_date_time as purchase3_5_1_,
vehicles1_.purchased_date_zone_offset as purchase4_5_1_,
vehicles1_.student_id as student_9_5_1_,
vehicles1_.updated_date as updated_5_5_1_,
vehicles1_.vechicle_type as vechicle6_5_1_,
vehicles1_.vehicle_number as vehicle_7_5_1_,
vehicles1_.instructor_id as instruct8_5_0__,
vehicles1_.id as id1_5_0__
from
instructor instructor0_
inner join
vehicle vehicles1_
on instructor0_.id=vehicles1_.instructor_id
В результате все инструкторы извлеченыиз db вместе с их транспортными средствами и после выполнения i.getVehicles () ни один запрос не переходит к db снова.Что должно быть правильным поведением.Я получаю это поведение с предложением JPQL join fetch.
Контрольный пример 2: пробовал то же самое с Criteria API, как показано ниже:
@Test
@Transactional
@Rollback(false)
public void fetchTest3() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Instructor> cq =
cb.createQuery(Instructor.class);
Root<Instructor> root = cq.from(Instructor.class);
root.join(Instructor_.vehicles);
List<Instructor> instructorsWithCriteria =
em.createQuery(cq.distinct(true).select(root)).
getResultList();
print(instructorsWithCriteria);
}
Запрос БД передан в БД для случая 2:
select distinct instructor0_.id as id1_2_,
instructor0_.address as address2_2_,
instructor0_.birth_date_time as birth_da3_2_,
instructor0_.birth_date_time_zone_offset as birth_da4_2_,
instructor0_.created_date as created_5_2_,
instructor0_.day_off_time as day_off_6_2_,
instructor0_.day_start_time as day_star7_2_,
instructor0_.father_name as father_n8_2_,
instructor0_.mother_name as mother_n9_2_,
instructor0_.name as name10_2_,
instructor0_.photo as photo11_2_,
instructor0_.monthly_salary as monthly12_2_,
instructor0_.updated_date as updated13_2_,
instructor0_.version as version14_2_
from
instructor instructor0_
inner join
vehicle vehicles1_
on instructor0_.id=vehicles1_.instructor_id
** В результатевсе инструкторы взяты из БД.Как только я нажимаю i.getVehciles () в методе print, запрос на получение транспортных средств этого инструктора отправляется в db.То же самое происходит со всеми инструкторами один за другим.То же самое происходит и в случаях 3 и 4 ниже.
Что следует передать в предложении select в случаях 2, 3, 4, чтобы столбцы транспортных средств также были выбраны в запросе?
**
Тестовый случай 3: JPQL в левом соединении
@Test
@Transactional
@Rollback(false)
public void fetchTest2() {
List<Instructor> instructorsJpqlLeftJoin = em
.createQuery("select distinct i from Instructor i left join
i.vehicles v ", Instructor.class)
.getResultList();
print(instructorsJpqlLeftJoin);
}
ДБ Запрос в дБ для случая 3:
select
distinct instructor0_.id as id1_2_,
instructor0_.address as address2_2_,
instructor0_.birth_date_time as birth_da3_2_,
instructor0_.birth_date_time_zone_offset as birth_da4_2_,
instructor0_.created_date as created_5_2_,
instructor0_.day_off_time as day_off_6_2_,
instructor0_.day_start_time as day_star7_2_,
instructor0_.father_name as father_n8_2_,
instructor0_.mother_name as mother_n9_2_,
instructor0_.name as name10_2_,
instructor0_.photo as photo11_2_,
instructor0_.monthly_salary as monthly12_2_,
instructor0_.updated_date as updated13_2_,
instructor0_.version as version14_2_
from
instructor instructor0_
left outer join
vehicle vehicles1_
on instructor0_.id=vehicles1_.instructor_id
Case 4 : Criteria API Left Join :
@Test
@Transactional
@Rollback(false)
public void fetchTest4() {
CriteriaBuilder cbLeftJoin = em.getCriteriaBuilder();
CriteriaQuery<Instructor> cqLeftJoin =
cbLeftJoin.createQuery(Instructor.class);
Root<Instructor> rootLeftJoin = cqLeftJoin.from(Instructor.class);
rootLeftJoin.join(Instructor_.vehicles, JoinType.LEFT);
List<Instructor> instructorsWithCriteriaLeftJoin = em
.createQuery(cqLeftJoin.distinct(true).
select(rootLeftJoin)).getResultList();
print(instructorsWithCriteriaLeftJoin);
}
ДБ Запрос для случая 4:
select
distinct instructor0_.id as id1_2_,
instructor0_.address as address2_2_,
instructor0_.birth_date_time as birth_da3_2_,
instructor0_.birth_date_time_zone_offset as birth_da4_2_,
instructor0_.created_date as created_5_2_,
instructor0_.day_off_time as day_off_6_2_,
instructor0_.day_start_time as day_star7_2_,
instructor0_.father_name as father_n8_2_,
instructor0_.mother_name as mother_n9_2_,
instructor0_.name as name10_2_,
instructor0_.photo as photo11_2_,
instructor0_.monthly_salary as monthly12_2_,
instructor0_.updated_date as updated13_2_,
instructor0_.version as version14_2_
from
instructor instructor0_
left outer join
vehicle vehicles1_
on instructor0_.id=vehicles1_.instructor_id
Что мне делать в случае 2,3,4чтобы столбцы транспортных средств также были выбраны в том же запросе, чтобы второстепенные выборки не переходили в db?