forked from WebEducationPlatform/CRM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Hibernate annotations guide.txt
277 lines (247 loc) · 17.3 KB
/
Hibernate annotations guide.txt
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
Hebernate annotations guide
Информация актуальна на 06.06.2019
Для просмотра результатов sql-запросов есть библиотека.
<dependency>
<groupId>com.integralblue</groupId>
<artifactId>log4jdbc-spring-boot-starter</artifactId>
<version>1.0.2</version>
</dependency>
***************************************************************************************
Полезные ссылки
https://www.solidsyntax.be/2013/10/17/fetching-collections-hibernate/
https://vladmihalcea.com/tutorials/hibernate/
***************************************************************************************
class Client
Если оставить дефолтное fetchType.LAZY, на доске clientPhones все равно сразу загружаются на доске, как будто стоит fetchType.EAGER, скорее всего, потому что fetchType.LAZY - не требование, а подсказка для ORM. Но на странице "Все клиенты" телефоны загружаются для каждого клиента отдельно. Чтобы сразу не загружать слишком много коллекций, используется BatchSize. size = 30, потому что на странице "Все клиенты" загружается по 30 клиентов.
/**
* We reduce number of requests with FetchType.EAGER.
* ElementCollection uses cascadeType.ALL and orphanRemoval = true by default.
* We use BatchSize to control our queries and not request too many entities.
* OrderColumn used to maintain the persistent order of a list.
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name="client_phones", joinColumns = @JoinColumn(name="client_id"))
@Column(name="client_phone", unique = true)
@OrderColumn(name = "numberInList")
@BatchSize(size = 30)
private List<String> clientPhones = new ArrayList<>();
Если оставить дефолтное fetchType.LAZY, на доске clientEmails все равно сразу загружаются, как будто стоит fetchType.EAGER, скорее всего, потому что fetchType.LAZY - не требование, а подсказка для ORM. Но на странице "Все клиенты" емэйлы загружаются для каждого клиента отдельно. Чтобы сразу не загружать слишком много коллекций, используется BatchSize. size = 30, потому что на странице "Все клиенты" загружается по 30 клиентов.
/**
* We reduce number of requests with FetchType.EAGER.
* ElementCollection uses cascadeType.ALL and orphanRemoval = true by default.
* We use BatchSize to control our queries and not request too many entities.
* OrderColumn used to maintain the persistent order of a list.
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name="client_emails", joinColumns = @JoinColumn(name="client_id"))
@Column(name="client_email", unique = true)
@OrderColumn(name = "numberInList")
@BatchSize(size = 30)
private List<String> clientEmails = new ArrayList<>();
Двунаправленная связь OneToMany через таблицу, можно было бы сделать однонаправленную с дополнительным столбцом на стороне ManyToOne.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
* We use BatchSize to control our queries and not request too many entities.
*/
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@BatchSize(size = 50)
@JoinTable(name = "client_whatsapp_message",
joinColumns = {@JoinColumn(name = "client_id",foreignKey = @ForeignKey(name = "FK_WHATSAPP_MESSAGE_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "whatsapp_message_number",foreignKey = @ForeignKey(name = "FK_WHATSAPP_MESSAGE"))})
private List<WhatsappMessage> whatsappMessages = new ArrayList<>();
Двунаправленная связь ManyToOne через таблицу, если бы все клиенты на доске не загружались через статусы, можно было бы сделать однонаправленную с дополнительным столбцом на стороне ManyToOne.
/**
* We use FetchType.LAZY for lazy initialization.
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "status_id")
@JoinTable(name = "status_clients",
joinColumns = {@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "FK_USER"))},
inverseJoinColumns = {@JoinColumn(name = "status_id", foreignKey = @ForeignKey(name = "FK_STATUS"))})
private Status status;
Однонаправленная связь ManyToOne, желательно сделать fetchType.LAZY, но нужно действовать аккуратно, так как возникают эксепшены, когда хибернейт подсовывает прокси вместо сущности.
/**
* ManyToOne uses fetchType.EAGER by default.
*/
@ManyToOne
@JoinColumn(name = "owner_user_id")
private User ownerUser;
Однонаправленная связь ManyToOne, желательно сделать fetchType.LAZY, но нужно действовать аккуратно, так как возникают эксепшены, когда хибернейт подсовывает прокси вместо сущности.
/**
* ManyToOne uses fetchType.EAGER by default.
*/
@ManyToOne
@JoinColumn(name = "owner_mentor_id")
private User ownerMentor;
При загрузке доски не загружаются, все нормально, а при загрузке страницы "Все клиенты" почему-то загружаются селектами на каждого клиента.
/**
* OrderBy determines the ordering of the elements.
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
* We use BatchSize to control our queries and not request too many entities.
*/
@JsonIgnore
@OrderBy("date DESC")
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@BatchSize(size = 25)
@JoinTable(name = "client_comment",
joinColumns = {@JoinColumn(name = "client_id", foreignKey = @ForeignKey(name = "FK_COMMENT_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "comment_id", foreignKey = @ForeignKey(name = "FK_COMMENT"))})
private List<Comment> comments = new ArrayList<>();
При загрузке доски не загружаются, все нормально, а при загрузке страницы "Все клиенты" почему-то загружаются селектами на каждого клиента.
/**
* OrderBy determines the ordering of the elements.
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
* We use BatchSize to control our queries and not request too many entities.
*/
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "history_client",
joinColumns = {@JoinColumn(name = "client_id", foreignKey = @ForeignKey(name = "FK_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "history_id", foreignKey = @ForeignKey(name = "FK_HISTORY"))})
@OrderBy("id DESC")
@BatchSize(size = 25)
private List<ClientHistory> history = new ArrayList<>();
При загрузке доски и при загрузке страницы "Все клиенты" не загружаются, все нормально.
/**
* OrderBy determines the ordering of the elements.
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
* We use BatchSize to control our queries and not request too many entities.
*/
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "feedback_client",
joinColumns = {@JoinColumn(name = "client_id", foreignKey = @ForeignKey(name = "FK_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "feedback_id", foreignKey = @ForeignKey(name = "FK_FEEDBACK"))})
@OrderBy("id DESC")
@BatchSize(size = 25)
private List<ClientFeedback> feedback = new ArrayList<>();
При загрузке доски и при загрузке страницы "Все клиенты" не загружаются, все нормально.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
* We use BatchSize to control our queries and not request too many entities.
*/
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "client_job",
joinColumns = {@JoinColumn(name = "client_id", foreignKey = @ForeignKey(name = "FK_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "job_id", foreignKey = @ForeignKey(name = "FK_JOB"))})
@BatchSize(size = 25)
private List<Job> jobs = new ArrayList<>();
При загрузке доски загружаются в непонятной последовательности, а при загрузке страницы "Все клиенты" почему-то загружаются селектами на каждого клиента.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* We use FetchType.EAGER because this field is used in Transactional method and have to initialize before.
* We use BatchSize to control our queries and not request too many entities.
*/
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@BatchSize(size = 25)
@JoinTable(name = "client_social_network",
joinColumns = {@JoinColumn(name = "client_id", foreignKey = @ForeignKey(name = "FK_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "social_network_id", foreignKey = @ForeignKey(name = "FK_SOCIAL_NETWORK"))})
private List<SocialProfile> socialProfiles = new ArrayList<>();
При загрузке доски и при загрузке страницы "Все клиенты" не загружаются, все нормально.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
* We use BatchSize to control our queries and not request too many entities.
*/
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@BatchSize(size = 25)
@JoinTable(name = "client_sms_info",
joinColumns = {@JoinColumn(name = "client_id", foreignKey = @ForeignKey(name = "FK_CLIENT"))},
inverseJoinColumns = {@JoinColumn(name = "sms_info_id", foreignKey = @ForeignKey(name = "FK_SMS_INFO"))})
private List<SMSInfo> smsInfo = new ArrayList<>();
При загрузке доски и при загрузке страницы "Все клиенты" не загружаются, все нормально.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
* OneToMany uses FetchType.LAZY by default.
*/
@JsonIgnore
@OneToMany(mappedBy = "client", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CallRecord> callRecords = new ArrayList<>();
Двунаправленная связь OneToOne, желательно сделать однонаправленную через MapsId в сущности Student, а из клиента убрать это поле. При загрузке страницы "Все клиенты" загружается селектами для каждого клиента.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
*/
@JsonIgnore
@OneToOne(mappedBy = "client", cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "student_id")
private Student student;
Двунаправленная связь OneToOne, желательно сделать однонаправленную через MapsId в сущности SlackInviteLink, а из клиента убрать это поле. При загрузке доски НЕ загружается селектами, все нормально.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
*/
@JsonIgnore
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "slack_invite_link_id")
private SlackInviteLink slackInviteLink;
Двунаправленная связь OneToOne, желательно сделать однонаправленную через MapsId в сущности Passport, а из клиента убрать это поле. При загрузке страницы "Все клиенты" загружается селектами для каждого клиента.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
*/
@OneToOne(mappedBy = "client", cascade = CascadeType.ALL, orphanRemoval = true)
private Passport passport;
Двунаправленная связь OneToOne, желательно сделать однонаправленную через MapsId в сущности ContractLinkData, а из клиента убрать это поле. При загрузке страницы "Все клиенты" загружается селектами для каждого клиента.
/**
* We use CascadeType.ALL to manage entity through Client's entity.
* OrphanRemoval needs for a disconnected instance is automatically removed.
*/
@OneToOne(mappedBy = "client", cascade = CascadeType.ALL, orphanRemoval = true)
private ContractLinkData contractLinkData;
***************************************************************************************
class Status
Чтобы загрузить всех клиентов за один запрос, используем SUBSELECT. Использовать его для таких ситуаций не рекомендуется, но это лучшее, что можно выбрать, пока клиенты будут загружаться через статусы.
/**
* Клиенты (студенты) с данным статусом
* OneToMany uses FetchType.LAZY by default.
* We use FetchMode.SUBSELECT for loading all elements of all collections.
*/
@JsonIgnore
@OneToMany
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(name = "status_clients",
joinColumns = {@JoinColumn(name = "status_id", foreignKey = @ForeignKey(name = "FK_STATUS"))},
inverseJoinColumns = {@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "FK_USER"))})
private List<Client> clients;
Чтобы загрузить все роли за один запрос, используем SUBSELECT. Так как ролей немного, тут он отлично подходит.
/**
* ManyToMany uses FetchType.LAZY by default.
* We use FetchMode.SUBSELECT because we have limited quantity of roles,
* and almost all of them are in the session.
*/
@ManyToMany
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(name = "status_roles",
joinColumns = {@JoinColumn(name = "status_id", foreignKey = @ForeignKey(name = "FK_STATUS"))},
inverseJoinColumns = {@JoinColumn(name = "role_id", foreignKey = @ForeignKey(name = "FK_ROLE"))})
private List<Role> role;
***************************************************************************************
class User
Чтобы загрузить все роли за один запрос, используем SUBSELECT. Так как ролей немного, тут он отлично подходит.
/**
* Права (роль)
* FetchType.EAGER for for initialize all fields.
* We use FetchMode.SUBSELECT for loading all elements of all collections.
*/
@NotNull
@ManyToMany(fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(name = "permissions",
joinColumns = {@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "FK_USER"))},
inverseJoinColumns = {@JoinColumn(name = "role_id", foreignKey = @ForeignKey(name = "FK_ROLE"))})
private List<Role> role = new ArrayList<>();