powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Маппинг одной сущности дважды в hibernate
16 сообщений из 16, страница 1 из 1
Маппинг одной сущности дважды в hibernate
    #39254877
TepKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коллеги,
Есть непонятка с Hibernate 5.1. Он делает SELECT вместо JOIN при маппинге одной Entity дваждый из разных child'ов.

Вообщем задача такая:
Есть мероприятие\конференция которая содержит коллекцию спикеров-хедлайнеров и коллекция докладов.
Каждый спикер-хедлайнер маппится OneToOne к сущности UserEntity которая содержит всякие там детали (ФИО, соц. сети и прочее)
Каждый доклад так же маппится на SpeakerEntity а он соответственно так же на UserEntity.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
@Entity
public class EventEntity {
    @Id
    private int id;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "eventId")
    @Fetch(FetchMode.JOIN)
    private Set<SpeakerEntity> eventSpeaker;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "eventId")
    @Fetch(FetchMode.JOIN)
    private Set<EventLectureEntity> eventLecture;
}

@Entity
public class SpeakerEntity {
    @Id
    private int id;

    @Column(name = "event_id")
    private Integer eventId;

    @Column(name = "lecture_id")
    private Integer lectureId;
        
    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="username_id")
    @Fetch(FetchMode.JOIN)
    private UserEntity user;
}

@Entity
public class EventLectureEntity {
    @Id
    private int id;

    @Column(name = "event_id")
    private int eventId;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "lectureId")
    @Fetch(FetchMode.JOIN)
    private Set<SpeakerEntity> lectureSpeaker;
}

@Entity
public class UserEntity {
    @Id
    private int id;

    @Column
    private String username;
}

@Service
public class EventService {    
    @Autowired
    private EventDAO eventDAO;

    @Transactional
    public EventEntity getEvent(int id){
        return eventDAO.getEvent(id);
    }
}

@Repository
public class EventDAO {
    @Autowired
    private SessionFactory sessionFactory;

    public EventEntity getEvent(int id){
        return sessionFactory.getCurrentSession().get(EventEntity.class, id);
    }
}



Собственно проблема в том, что hibernate делает такой вот SELECT
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
select 
   evententit0_.id as id1_0_0_, 
   eventlectu1_.event_id as event_id2_1_1_, 
   eventlectu1_.id as id1_1_1_, 
   eventlectu1_.id as id1_1_2_, 
   eventlectu1_.event_id as event_id2_1_2_, 
   lecturespe2_.lecture_id as lecture_3_2_3_, 
   lecturespe2_.id as id1_2_3_, 
   lecturespe2_.id as id1_2_4_, 
   lecturespe2_.event_id as event_id2_2_4_, 
   lecturespe2_.lecture_id as lecture_3_2_4_, 
   lecturespe2_.username_id as username4_2_4_, 
   userentity3_.id as id1_3_5_, 
   userentity3_.username as username2_3_5_, 
   eventspeak4_.event_id as event_id2_2_6_,
   eventspeak4_.id as id1_2_6_, 
   eventspeak4_.id as id1_2_7_, 
   eventspeak4_.event_id as event_id2_2_7_, 
   eventspeak4_.lecture_id as lecture_3_2_7_, 
   eventspeak4_.username_id as username4_2_7_ 
from EVENT evententit0_ 
   left outer join EVENT_LECTURE eventlectu1_ on evententit0_.id=eventlectu1_.event_id 
   left outer join SPEAKER lecturespe2_ on eventlectu1_.id=lecturespe2_.lecture_id 
   left outer join USER userentity3_ on lecturespe2_.username_id=userentity3_.id 
   left outer join SPEAKER eventspeak4_ on evententit0_.id=eventspeak4_.event_id 
where evententit0_.id=?



А потом еще до SELECT'ивает. Чего я собственно не хочу . А хочу чтобы все JOIN'илось
Код: sql
1.
2.
3.
select userentity0_.id as id1_3_0_, userentity0_.username as username2_3_0_ from USER userentity0_ where userentity0_.id=?
select userentity0_.id as id1_3_0_, userentity0_.username as username2_3_0_ from USER userentity0_ where userentity0_.id=?
select userentity0_.id as id1_3_0_, userentity0_.username as username2_3_0_ from USER userentity0_ where userentity0_.id=?



Как мне заставить hibernate сущность UserEntity джоинить, а не доселективать?
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39254898
Mad_Head
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне недавно нужно было победить схожую проблему. Для меня проще всего было написать HQL запрос с явным "join fetch"
примерно
from
SpeakerEntity speaker
join fetch
speaker.user
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39254909
andreykaT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
лол. я бился с таким косяком. причем он там такие аномалии вываливал в п зависимости от некоторых обстоятельств, мало связанных с состоянием базы что волосы дыбом на спине вставали.

в общем, убрал фетч.тайп.игер у всех коллекций на лейзи - и всё пришло в адекват.

я понял что при игер хибер может начинать доставать заджоиные сущности не всегда так, как самое простое, а какими то запутанными неведомыми путями.

да и вообще, делая игер на коллекциях ты рискуешь вытащив одну сущность случайно вытащить всю базу в память.

имхо не очень хорошее решение.
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39254919
Mad_Head
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreykaT,

Тут на самом деле - это не проблема в fetch type. Так как fetch влияет на то когда будут получены данные, а не сколькими запросами. В случае автора данные вытягиваются при первом получении конревого объекта, но в n+1 запросов. К стати по умолчанию OneToOne имеет fetch = FetchType.EAGER (в JPA спеке точно).

Вот тут подробно ответили
http://stackoverflow.com/questions/1002547/onetoone-relationship-with-shared-primary-key-generates-n1-selects-any-workaro/3538465#3538465
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39254935
andreykaT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mad_Head,

я про мени ту ван. ван ту мени тоже по умолчанию игер.
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39254936
andreykaT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в смысле, наоборот.
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39255018
TepKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mad_Head,
Ну так в этом и проблема :) OneToOne я хочу именно EAGER и именно JOIN'ом. У меня же по факту EAGER случается, но SELECT'ом.
А в статье указано на сколько я понял именно как заставить OneToOne работать в режиме LAZY. А мне этого не надо :(
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39255496
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде по умолчанию нельзя настроить выборку с несколькими джойнами в одном бине ?!

или в новой версии уже можно ? т.е. только одна коллекция может быть джоин безууказания лайзи?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
@Entity
public class EventEntity {
    @Id
    private int id;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "eventId")
    @Fetch(FetchMode.JOIN)
    private Set<SpeakerEntity> eventSpeaker;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "eventId")
    @Fetch(FetchMode.JOIN)
    private Set<EventLectureEntity> eventLecture;
}



такая штука вообще без @Fetch(FetchMode.JOIN) работать не будет ! вроде как ?!




плюс нужно смотреть конфигурацию - возоожно вы указали нбеольшую глубину подзапросов и поэтому хибер добирает селектами ?

пробегитесь по вашим пропертям итд :

Код: java
1.
2.
3.
        properties.setProperty("hibernate.default_batch_fetch_size", "16");
        properties.setProperty("hibernate.max_fetch_depth", "3");
        properties.setProperty("hibernate.jdbc.fetch_size", "50");
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39255973
TepKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Вроде по умолчанию нельзя настроить выборку с несколькими джойнами в одном бине ?!

или в новой версии уже можно ? т.е. только одна коллекция может быть джоин безууказания лайзи?

Не знаю что для вас значит новая или старая, но 4ом хибере можно было в одном бине делать джойны нескольких child'ов. И они доставались из базы норм. В 3ем не помню уже :(

Atum1плюс нужно смотреть конфигурацию - возоожно вы указали нбеольшую глубину подзапросов и поэтому хибер добирает селектами ?

пробегитесь по вашим пропертям итд :

Код: java
1.
2.
3.
        properties.setProperty("hibernate.default_batch_fetch_size", "16");
        properties.setProperty("hibernate.max_fetch_depth", "3");
        properties.setProperty("hibernate.jdbc.fetch_size", "50");


Да мне это первое что в голову так же пришло. Но к сожалению это не помогло.
max_fetch_depth = 4, увеличение даже до 10 не даёт ожидаемого результата.
default_batch_fetch_size и fetch_size ИМХО из другой оперы :)

Хибер доберает селектами потому что я два раза выбираю сущность UserEntity по одному и тому же полю(primary key). Хибер думает что он первым джойном выбирает UserEntity поэтому и не включает его в join при запросе из базы. А когда получает корневую сущность до хибера доходит, что он выбрал не всё :) и начинает до заполнять объекты UserEntity.

Просто я думаю, что стопудоф есть какая то настроечка для этого, но какая вообще найти не могу. Даже загуглить не знаю как :(
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39256157
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JPQL HQL или JPA Criteria API

через них
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39256173
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TepKuH,

Есть у меня подозрение на одно ограничение. Точно не вспомню. Но раньше насильное желание всё заджоинить приводило к исключению. Может в последних версиях исключение заменили на насильственный SELECT?

Суть в том что при толстом JOIN, когда одна и та же сущность замаплена разными ассоциациями, ORM не может однозначно определить какая запись выборки относится к какой ассоциации. Одним из решений этой проблемы была замена не сортированной коллекции на List. Но нужно ещё замапить колонку для определения порядка элементов. Надо поискать предыдущее обсуждение по этому вопросу.
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39256181
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39256460
TepKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczTepKuH,

Есть у меня подозрение на одно ограничение. Точно не вспомню. Но раньше насильное желание всё заджоинить приводило к исключению. Может в последних версиях исключение заменили на насильственный SELECT?

А бес его знает :) Может заменили на SELECT :)

BlazkowiczTepKuH,
Суть в том что при толстом JOIN, когда одна и та же сущность замаплена разными ассоциациями, ORM не может однозначно определить какая запись выборки относится к какой ассоциации. Одним из решений этой проблемы была замена не сортированной коллекции на List. Но нужно ещё замапить колонку для определения порядка элементов. Надо поискать предыдущее обсуждение по этому вопросу.

Что самое интересное в ссылке, что вы привели они наоборот рекомендуют использовать Set вместо List. У меня ведь и так Set. В общем случаи хиберу Set больше нравится чем List или иные коллекции.
@LazyCollection(LazyCollectionOption.FALSE) к сожалению не прокатило :(
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39256462
TepKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1JPQL HQL или JPA Criteria API

через них
Это я пока оставляю, как воркэраунд.
...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39257595
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TepKuHКоллеги,
Есть непонятка с Hibernate 5.1. Он делает SELECT вместо JOIN при маппинге одной Entity дваждый из разных child'ов.

Вообщем задача такая:
Есть мероприятие\конференция которая содержит коллекцию спикеров-хедлайнеров и коллекция докладов.
Каждый спикер-хедлайнер маппится OneToOne к сущности UserEntity которая содержит всякие там детали (ФИО, соц. сети и прочее)
Каждый доклад так же маппится на SpeakerEntity а он соответственно так же на UserEntity.

Как мне заставить hibernate сущность UserEntity джоинить, а не доселективать?

Вот навеяло вашей темой

jpql как вернуть min max в одном запросе ?

решил в очередной раз поразбираться что же там такое генерится и прошел в ужас !!!

Простой запрос :
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
    public Employee findByEmployeeId(Integer id) {
       TypedQuery<Employee> query = em
               //.createQuery("select e from Employee e  where e.id = :id ",Employee.class)
               .createQuery("select e from Employee e JOIN FETCH e.employees b JOIN FETCH e.departmentId d where e.id = :id ",Employee.class)
               .setParameter("id", id);
        return query.getSingleResult();
    }
    




генерит :

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
Hibernate: 
    select
        employee0_.id as id1_1_0_,
        employees1_.id as id1_1_1_,
        department2_.id as id1_0_2_,
        employee0_.department_id as departme4_1_0_,
        employee0_.employee_id as employee5_1_0_,
        employee0_.name as name2_1_0_,
        employee0_.salary as salary3_1_0_,
        employees1_.department_id as departme4_1_1_,
        employees1_.employee_id as employee5_1_1_,
        employees1_.name as name2_1_1_,
        employees1_.salary as salary3_1_1_,
        employees1_.employee_id as employee5_1_0__,
        employees1_.id as id1_1_0__,
        department2_.name as name2_0_2_ 
    from
        employee employee0_ 
    inner join
        employee employees1_ 
            on employee0_.id=employees1_.employee_id 
    inner join
        department department2_ 
            on employee0_.department_id=department2_.id 
    where
        employee0_.id=?
Hibernate: 
    select
        employee0_.id as id1_1_0_,
        employee0_.department_id as departme4_1_0_,
        employee0_.employee_id as employee5_1_0_,
        employee0_.name as name2_1_0_,
        employee0_.salary as salary3_1_0_,
        department1_.id as id1_0_1_,
        department1_.name as name2_0_1_,
        employee2_.id as id1_1_2_,
        employee2_.department_id as departme4_1_2_,
        employee2_.employee_id as employee5_1_2_,
        employee2_.name as name2_1_2_,
        employee2_.salary as salary3_1_2_,
        shifts3_.employee_id as employee4_1_3_,
        shifts3_.id as id1_2_3_,
        shifts3_.id as id1_2_4_,
        shifts3_.action_datetime as action_d2_2_4_,
        shifts3_.employee_id as employee4_2_4_,
        shifts3_.operation_type as operatio3_2_4_ 
    from
        employee employee0_ 
    inner join
        department department1_ 
            on employee0_.department_id=department1_.id 
    left outer join
        employee employee2_ 
            on employee0_.employee_id=employee2_.id 
    left outer join
        shift shifts3_ 
            on employee2_.id=shifts3_.employee_id 
    where
        employee0_.id=?
Hibernate: 
    select
        shifts0_.employee_id as employee4_1_1_,
        shifts0_.id as id1_2_1_,
        shifts0_.id as id1_2_0_,
        shifts0_.action_datetime as action_d2_2_0_,
        shifts0_.employee_id as employee4_2_0_,
        shifts0_.operation_type as operatio3_2_0_ 
    from
        shift shifts0_ 
    where
        shifts0_.employee_id in (
            ?, ?, ?, ?, ?
        )
Hibernate: 
    select
        employees0_.employee_id as employee5_1_2_,
        employees0_.id as id1_1_2_,
        employees0_.id as id1_1_1_,
        employees0_.department_id as departme4_1_1_,
        employees0_.employee_id as employee5_1_1_,
        employees0_.name as name2_1_1_,
        employees0_.salary as salary3_1_1_,
        department1_.id as id1_0_0_,
        department1_.name as name2_0_0_ 
    from
        employee employees0_ 
    inner join
        department department1_ 
            on employees0_.department_id=department1_.id 
    where
        employees0_.employee_id in (
            ?, ?, ?, ?
        )
Hibernate: 
    select
        shifts0_.employee_id as employee4_1_1_,
        shifts0_.id as id1_2_1_,
        shifts0_.id as id1_2_0_,
        shifts0_.action_datetime as action_d2_2_0_,
        shifts0_.employee_id as employee4_2_0_,
        shifts0_.operation_type as operatio3_2_0_ 
    from
        shift shifts0_ 
    where
        shifts0_.employee_id in (
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )
Hibernate: 
    select
        employees0_.employee_id as employee5_1_2_,
        employees0_.id as id1_1_2_,
        employees0_.id as id1_1_1_,
        employees0_.department_id as departme4_1_1_,
        employees0_.employee_id as employee5_1_1_,
        employees0_.name as name2_1_1_,
        employees0_.salary as salary3_1_1_,
        department1_.id as id1_0_0_,
        department1_.name as name2_0_0_ 
    from
        employee employees0_ 
    inner join
        department department1_ 
            on employees0_.department_id=department1_.id 
    where
        employees0_.employee_id in (
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )
Hibernate: 
    select
        shifts0_.employee_id as employee4_1_1_,
        shifts0_.id as id1_2_1_,
        shifts0_.id as id1_2_0_,
        shifts0_.action_datetime as action_d2_2_0_,
        shifts0_.employee_id as employee4_2_0_,
        shifts0_.operation_type as operatio3_2_0_ 
    from
        shift shifts0_ 
    where
        shifts0_.employee_id in (
            ?, ?, ?
        )
Hibernate: 
    select
        employees0_.employee_id as employee5_1_2_,
        employees0_.id as id1_1_2_,
        employees0_.id as id1_1_1_,
        employees0_.department_id as departme4_1_1_,
        employees0_.employee_id as employee5_1_1_,
        employees0_.name as name2_1_1_,
        employees0_.salary as salary3_1_1_,
        department1_.id as id1_0_0_,
        department1_.name as name2_0_0_ 
    from
        employee employees0_ 
    inner join
        department department1_ 
            on employees0_.department_id=department1_.id 
    where
        employees0_.employee_id in (
            ?, ?, ?
        )

...
Рейтинг: 0 / 0
Маппинг одной сущности дважды в hibernate
    #39258448
TepKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1решил в очередной раз поразбираться что же там такое генерится и прошел в ужас !!!

Вы скорее всего не правильно создали hql. В вашем запросе я например не вижу джойна с shift'ом. А запрашиваемый объект Employee скорее всего с ним каким то образом маппится :)
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Маппинг одной сущности дважды в hibernate
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]