-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCurso Spring Boot && MVC com Thymeleaf
4314 lines (3398 loc) · 196 KB
/
Curso Spring Boot && MVC com Thymeleaf
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Curso Spring Boot && MVC com Thymeleaf
Informações Complementares
--------------------------
. Como configurar a página default quando for chamado o contexto "/" do site:
Page index.html will be default if one this possibilities:
Solution 1: index.html page inside public
create an index.html page inside resources/public/index.html
Solution 2: index.html page inside static
create an index.html page inside resources/static/index.html
Solution 3: Using controller Mapping
Create a controller with@RequestMapping("/") which will return view name but for this requires any view configuration. Here is spring boot jsp example
package com.javadeveloperzone.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by Java Developer Zone on 19-07-2017.
*/
@Controller
public class IndexController {
@RequestMapping("/")
public String index() {
return "Spring Boot Example";
}
}
. Principais propriedades do arquivo application.properties
spring.main.banner-mode=off
logging.level.org.springframework=error
spring.jpa.hibernate.ddl-auto=none
spring.datasource.initialization-mode=always
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/desenv
spring.datasource.username=supervisor
spring.datasource.password=brasil2
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
#Show all queries
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
#logging.level.org.hibernate.type=error
#spring.mvc.view.prefix=/templates/
spring.thymeleaf.suffix=.jsp
# Allow Thymeleaf templates to be reloaded at dev time
spring.thymeleaf.cache: false
spring.thymeleaf.mode: html
Aula 3 - Anotações Spring Framework
. Principais anoteações para objetos componentes:
@Component
É uma anotação básica para criar qualquer tipo de bean gerenciado pelo Spring Framework.
Normalmente usada quando não se define um bean como @Repository ou @Service.
@Repository
Define um bean como sendo do tipo persistente para uso em classes de acesso a banco de
dados. A partir desta anotação o Spring pode usar recursos referentes a persistência, como
tratar as exceções específicas para este fim.
@Service
Usado para classes do tipo serviço (Service Layer), que possuem, por
exemplo, regras de negócios.
@Autowired
Anotação usada para informar ao Spring que ele deve injetar a variável
anotada na classe em que está declarada
Exemplo 1
@Service
public class ComputadorService {
@Autowired
private ComputadorDao dao;
public void salvar(Computador computador) {
dao.saveOrUpdate(computador);
}
}
@Autowired pode ser declarada sobre variáveis de instancia, métodos set()
das variáveis de instancia e sobre métodos construtores.
Exemplo 2
@Service
public class ComputadorService{
private ComputadorDao dao;
@Autowired
public void setComputadorDAO(ComputadorDao dao){
this.dao = dao;
}
public void salvar(Computador computador) {
dao.saveOrUpdate(computador);
}
}
Exemplo 3
@Service
public class ComputadorService{
private ComputadorDao dao;
@Autowired
public ComputadorService(ComputadorDao dao) {
this.dao = dao;
}
public void salvar(Computador computador) {
dao.saveOrUpdate(computador);
}
}
Aula 6 - Anotações do Spring MVC
. @Controller
Transforma a classe em um bean do tipo controller do MVC.
Exemplo:
@Controller
public class ComputadorController {
//métodos e atributos omitidos
}
. @RequestMapping
Usada para mapear URLs de acesso a um controller e aos métodos contidos nele;
Exemplo:
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
// Também podemos definir verbos HTTP (POST, GET, ...) de acesso aos métodos.
@RequestMapping(path = “/listagem”, method = RequestMethod.GET)
public String getComputadores() {
}
}
. Alguns atributos da annotation @RequestMapping:
headers : @RequestMapping( headers=["Accept=application/json; text/html"] ["Accept="*/*"])
produces:
Outras opções que podem ser usadas no lugar do @RequestMapping:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
. Exemplo de uso a partir do cliente e testando com Postman
. Declare a função javascript na página web:
$(document).ready(
function() {
var objPessoa = { "nome" : "", "cpf" : "106.523.608-58"} ;
$("#send").on("click",function(){
$.ajax({
type: "GET",
url: "../pessoa/api",
data: objPessoa ,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(response){
alert(response[0].nome)
},
failure: function (response) {
alert(response.d);
},
error: function (response) {
alert(response.d);
}
});
});
});
. Declare o metodo na classe restful
@RestController
@RequestMapping("pessoa/api")
public class PessoaResource {
@Autowired
PessoaService pessoaService;
@RequestMapping(method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE,
headers = "Accept=*/*")
public @ResponseBody List<Pessoa> findPessoa( Pessoa pessoa) {
...
}
}
. No Postman, ir na aba .form-data e colocar o parâmetro "cpf" com value "106.523.608-58"
. @PathVariable
Tem o objetivo de extrair da URL um parâmetro que foi incluído como path da
URL.
Exemplo:
http://localhost:8080/demo/computadores/listagem/ibm
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@RequestMapping(path = “/listagem/{marca}”, method = RequestMethod.GET)
public String getComputadoresPorMarca(@PathVariable(“marca”) String marca) {
System.out.println( marca );
}
}
. @RequestParam
Tem o objetivo capturar um parâmetro de consulta (Query Param) enviado por
uma solicitação.
http://localhost:8080/demo/computadores/listagem?marca=ibm
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@RequestMapping(path = “/listagem”, method = RequestMethod.GET)
public String getComputadoresPorMarca(@RequestParam(name = “marca”) String marca) {
}
}
. @RequestBody
Mapeia o corpo HttpRequest para um objeto de transferência ou domínio, permitindo a
desserialização automática do corpo HttpRequest de entrada em um objeto Java.
public class LoginForm {
private String username;
private String password;
//...
}
...
@PostMapping("/request")
public ResponseEntity postController( @RequestBody LoginForm loginForm) {
exampleService.fakeAuthenticate(loginForm);
return ResponseEntity.ok(HttpStatus.OK);
}
...
curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data
'{"username": "johnny", "password": "password"}' "https://localhost:8080/.../request"
. @ResponseBody
Informa a um controlador que o objeto retornado é serializado automaticamente no JSON e passado
de volta ao objeto HttpResponse
public class ResponseTransfer {
private String text;
//standard getters/setters
}
...
@PostMapping("/response")
@ResponseBody
public ResponseTransfer postResponseController(
@RequestBody LoginForm loginForm) {
return new ResponseTransfer("Thanks For Posting!!!");
}
// {"text":"Thanks For Posting!!!"}
. @ModelAttribute
Pode ser usado sobre a assinatura de um método ou como argumento de um método.
Quando utilizado no metodo, ao executar a classe através de alguma das outras annotation nela
como: @RequestMapping, ou @GetMapping, ou @PostMapping, etc. O metodo da annotation @ModelAttribute
será executa antes de qualquer outra annotation, para somente depois ir para a annotation destino.
Exemplo - Uso no metodo
@Controller
public class MyController {
@Autowired
private IMessageService messageService;
@GetMapping("/pageOne")
public String getPageOne() {
return "pageOne";
}
@GetMapping("/pageTwo")
public String getPageTwo() {
return "pageTwo";
}
@ModelAttribute("motd")
public String message() {
return messageService.getMessage();
}
}
Quando utilizado na assinatura associa os parâmetros, geralmente vindo de formulários,
com os atributos do componente.
Exemplo - Uso na assinatura
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@PostMapping(“/save”)
public String salvar(@ModelAttribute Computador computador) {
}
}
. @Valid
Anotação responsável por injetar a validação back-end via Hibernate Validator,
Bean Validation ou Spring Validator.
Exemplo:
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@PostMapping(“/save”)
public String salvar(@Valid Computador computador) {
}
}
Aula 7 - Objetos de Resposta MVC
. ModelMap, ModelAndView, Model - Todos são objetos "forward", ou seja, são objetos levados
para as páginas.
. ModelMap
Objeto usado para enviar dados a página como resposta de uma solicitação.
Trabalha como uma resposta do tipo forward.
Exemplo
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@Autowired
private ComputadorDao dao;
@GetMapping(“/listagem”)
public String getComputadores(ModelMap model) {
List<Computador> computadores = dao.findAll();
model.addAttribute(“computadores”, computadores);
return “lista”;
}
}
. ModelAndView
Objeto usado para enviar dados a página como resposta de uma solicitação.
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@Autowired
private ComputadorDao dao;
@GetMapping(“/listagem”)
public ModelAndView getComputadores() {
List<Computador> computadores = dao.findAll();
ModelAndView model = new ModelAndView(“lista”);
model.addObject(“computadores”, computadores);
return model;
}
}
. Model
@Controller
public class GreetingController {
@RequestMapping(path = "/getWithModel", method = RequestMethod.GET)
public String getWithModel(@RequestParam("name") String name, Model model) {
Greeting greeting = new Greeting(name);
model.addAttribute("greeting", greeting);
return "greet";
}
}
...
greet.html
----------
<!DOCTYPE html>
<html>
<body>
Hello <span th:text="${greeting.name}"/>!
</body>
</html>
. Map
@GetMapping("/getMessageAndTime")
public String getMessageAndTime(ModelMap map) {
var ldt = LocalDateTime.now();
var fmt = DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.MEDIUM);
fmt.withLocale(new Locale("sk", "SK"));
fmt.withZone(ZoneId.of("CET"));
String time = fmt.format(ldt);
map.addAttribute("message", message).addAttribute("time", time);
return "show";
}
...
show.fthl Página Fremaker
---------
<!DOCTYPE html>
<html>
<head>
<title>Message</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>
Message: ${message}
</p>
<#if time??>
<p>Date and time: ${time}</p>
</#if>
</body>
</html>
. ModelMap & ModelAndView
Adicionamos parâmetros de resposta no objeto ModelMap e retornamos um
ModelAndView.
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@Autowired
private ComputadorDao dao;
@GetMapping(“/listagem”)
public ModelAndView getComputadores(ModelMap model) {
List<Computador> computadores = dao.findAll();
model.addAttribute(“computadores”, computadores);
return new ModelAndView(“lista”, model);
}
}
. Redirect
É uma operação usada para redirecionar a resposta de uma solicitação a outra
solicitação.
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@Autowired
private ComputadorDao dao;
@GetMapping(“/listagem”)
public ModelAndView getComputadores(ModelMap model) {
List<Computador> computadores = dao.findAll();
model.addAttribute(“computadores”, computadores);
return new ModelAndView(“lista”, model);
}
@PostMapping(“/save”)
public String addComputador(Computador computador) {
dao.save(computador);
return “redirect:/computadores/listagem”
}
}
Importante: o redirect não consegue levar os objetos de parâmetos, pois esses são
forward.
Redirect é uma operação usada para redirecionar a resposta de uma solicitação a outra
solicitação.
Importante: Para levar parâmetos através de redirect precisamos utilizar o objeto
RedirectAttributes
@Controller
@RequestMapping(“/computadores”)
public class ComputadorController {
@Autowired
private ComputadorDao dao;
@GetMapping(“/listagem”)
public ModelAndView getComputadores(ModelMap model) {
List<Computador> computadores = dao.findAll();
model.addAttribute(“computadores”, computadores);
return new ModelAndView(“lista”, model);
}
@PostMapping(“/save”)
public String addComputador(Computador computador, RedirectAttributes attrib) { // <--
dao.save(computador);
attrib.addFlashAttribute(“mensagem”, “Computador inserido com sucesso”); // <--
return “redirect:/computadores/listagem”
}
}
A classe RedirectAttributes também poderá ser utilizada para armazenar objetos na sessão
para que após o redirecionamento possa ser utilizado, por exemplo:
@PostMapping("/salvar")
public String salvar(@ModelAttribute Departamento departamento, RedirectAttributes attr) {
try {
service.salvar(departamento);
attr.addFlashAttribute("success", "Departamento salvo com sucesso.");
}catch( Exception e) {
e.printStackTrace();
}
return "redirect:/departamentos/cadastrar";
}
// Na página ficaria:
<div th:if="${success} != null">
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="oi oi-check"></i>
<span>
<strong th:text="${success}"></strong>
</span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
Aulas 9 a 13 - Iniciando o desenvolvimento do projeto
. Crie um projeto Maven com os parâmetros abaixo:
Name : demo-mvc
Group : com.mballem.curso.boot
Artifact : demo-mvc
Package : com.mballem.curso.boot
Dependencias : Devtools, Thymeleaf, JPA, Web, Postgres
. Importar as páginas de exemplos para dentro do projeto
. Acesse a pasta de Material do Curso Spring Boot && MVC...
. Copie as pastas Cargo, Departamento e Funcionario; e a página home.html
para dentro da pasta resources/templates
. Copie todas as subpastas da pasta "static" para dentro da pasta static do projeto.
. Acesse o arquivo application.properties e acrescente o conteúdo abaixo:
spring.main.banner-mode=off
logging.level.org.springframework=error
spring.jpa.hibernate.ddl-auto=none
spring.datasource.initialization-mode=always
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/desenv
spring.datasource.username=supervisor
spring.datasource.password=brasil2
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
#Show all queries
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
#logging.level.org.hibernate.type=error
#spring.mvc.view.prefix=/templates/
#spring.thymeleaf.suffix=.jsp
# Allow Thymeleaf templates to be reloaded at dev time
spring.thymeleaf.cache: false
spring.thymeleaf.mode: html
. Acesse o link abaixo para verificar o site do webjars:
https://www.webjars.org/
https://useiconic.com/open
https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.pdf
. Neste link é possível localizar as bibliotecas disponíveis no
maven e pegar as versões mais recentes delas para linkar nos
nossos projetos.
. Observe que as bibliotecas vem associada ao <groupId>org.webjars</groupId>
o que faz do webjars um grande associador de bibliotecas.
. O site useiconic é o site onde encontra-se informações sobre os icones da biblioteca
open-iconic
. Acesse o pom.xml e coloque as linhas abaixo nele:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.4.1-1</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>open-iconic</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jquery-mask-plugin</artifactId>
<version>1.14.15</version>
</dependency>
. Como definir o path das bibliotecas dentro das paginas (<script src="..." e <link rel="...")
de acordo com as definições do webjars.
. É necessário que a dependência esteja definida no pom.xml, exemplo:
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jquery-maskmoney</artifactId>
<version>3.0.2</version>
</dependency>
. Para encontrar a dependência correta para inserir no pom.xml acesse o site do webjar (https://www.webjars.org/), localize a
biblioteca e copie a referência maven para dentro do pom.xml
. Na estrutura do projeto, acesse o nó "Maven Dependencies";
. Localize a biblioteca desejada;
. Dentro da dependencia vá até o nó {lib}/META-INF/resources/webjars/
. A partir deste nó gere o path para as tags <script...> e <link...>, por exemplo:
Maven Dependencies
+-- jquery-maskmoney-3.0.2.jar
+-- META-INF
+-- resources
+-- web-jars
+-- jquery-maskmoney # --> o mapeamento começa aqui
+-- 3.0.2
+-- dist
+-- jquery-maskmoney.min.js
Exemplo: <script th:src="@{/webjars/jquery-maskmoney/3.0.2/dist/jquery.maskMoney.min.js}"></script>
. Para mais informações, acesse o site https://www.springboottutorial.com/spring-boot-with-jquery-and-bootstrap-web-jars
Aulas 14 a 19 - Classes de Dominio
. Starter para JPA
Durante a Seção 3 vamos realizar o mapeamento objeto relacional com base em anotação da JPA.
Porém, para que isso seja possível, será necessário incluir no projeto as bibliotecas da JPA,
para se ter acesso as anotações. Por conta disso, vamos incluir o módulo de JPA do Spring
Framework, via starter do Spring Boot. O starter em questão será o spring-boot-starter-data-jpa,
como pode ser visto a seguir:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Com a inclusão desta dependencia termos então acesso a todos os recursos da JPA e Hibernate para
os mapeamentos, operações de CRUD e até mesmo para validações com Hibernate Validator.
. Classes de Entidades
O pacote com.mballem.curso.boot.domain vai conter as classes de entidades da aplicação.
Classes de entidades são aquelas que têm relação com as tabelas do banco de dados.
Em um banco de dados, cada linha de uma tabela é também chamada de entidade, sendo assim,
uma classe é conhecida como classe de entidade porque representa uma linha de uma tabela.
As classes de entidades serão mapeadas via anotações da especificação JPA,
algumas dessas anotações estão descritas a seguir:
@Entity: Usada sobre a assinatura da classe para marcá-la perante o
Hibernate/JPA que esta é uma classe de mapeamento objeto relacional;
@Table: Informa ao Hibernate/JPA que a tabela que está sendo mapeada
é aquela com o nome descrito na propriedade name da anotação. A
anotação ainda possui a propriedade indexes, onde foi configurado um
índice que não permite que mais de uma linha na tabela contenha
registros com o mesmo título e mesma data de início;
@Id: Usada para mapear a coluna referente à chave primária da tabela.
Esta anotação é obrigatória no mapeamento. Caso não seja adicionada
uma exceção será lançada em tempo de execução;
@GeneratedValue: É utilizada para informar que a geração da chave
primária da entidade será gerenciada pelo Hibernate e deve ser
adicionada junto a anotação @Id. Quando não anotamos o campo com
essa opção, significa que a responsabilidade de gerar e gerenciar as
chaves primárias serão da aplicação;
@Column: Seu uso tem como finalidade mapear uma coluna da tabela. Se
essa anotação não for declarada, o nome do atributo deverá ter o
mesmo nome da coluna. Essa anotação possui alguns atributos para
definir, por exemplo, se a coluna aceita valores nulos ou não
(nullable), o tamanho de uma coluna varchar (length), entre outros;
@Enumerated: Usada para mapear uma coluna a partir de um atributo do
tipo enum. Assim, podemos indicar se vamos gravar esse dado de forma ordinal,
a partir da posição do tipo declarado no enum, ou pelo da constante.
@OneToOne: Sua função é mapear o relacionamento entre duas tabelas no banco de
dados que tenha relação do tipo 1x1.
@OneToMany: Para mapear o lado fraco da relação um para muitos. O lado fraco é o
lado 1, já lado forte seria o lado N da relação. Nessa anotação devemos incluir
o atributo mappedBy com o nome do atributo que representa o lado fraco lá no
mapeamento da classe de lado forte.
@ManyToOne: Tem como objetivo mapear o atributo referente a chave estrangeira
em um relacionamento 1xN. A classe anotada com essa anotação é considerada o
lado forte da relação 1xN.
@JoinColumn: Uma de suas funções é nomear a chave estrangeira de um relacionamento
1xN ou 1x1. Deve ser declarada sobre o atributo que representa a chave estrangeira.
As classes de entidades neste projeto vão herdar da classe
com.mballem.curso.boot.domain.AbstractEntity algumas características
como os métodos getId() e setId(), além dos métodos toString(), equals() e hashCode().
Deste modo, não será necessário implementar em cada classe de entidade a
propriedade id nem os métodos citados acima. Outro ponto importante é em relação a
interface java.io.Serializable a qual deve ser implementada em classes de entidades
como uma boa pratica. Essa interface será implementada em AbstractEntity, assim,
automaticamente as classes filhas herdarão essa característica.
. Código Fonte da classe AbstractEntity:
package com.mballem.curso.boot.domain;
import java.io.Serializable;
import javax.persistence.*;
@SuppressWarnings("serial") // Coloque esta annotation para suprimir o Warning da implementação "Serializable"
@MappedSuperclass
public abstract class AbstractEntity<ID extends Serializable> implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private ID id;
public ID getId() {
return id;
}
public void setId(ID id) {
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AbstractEntity<?> other = (AbstractEntity<?>) obj; // Corrigir a Warning colocando <?>
// que vem sem qdo fazemos a geração pelo eclipse
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "id = " + id;
}
}
As classes de entidades que irão estender AbstractEntity são Departamento, Cargo,
Endereco e Funcionario. No banco de dados essas classes estão, respectivamente,
representadas pelas tabelas: departamentos, cargos, enderecos e funcionarios.
E o relacionamento entre elas estão descritos a seguir:
Departamentos (1) x (N) Cargos
Cargos (1) x (N) Funcionarios
Funcionarios (1) x (1) Enderecos
+---------------------+
| DEPARTAMENTOS |
+---------------------+
| id : bigint(20) |
+---------------------+
| nome : Varchar(60) |
+---------------------+
^
|
| id_departamento_fk : id
|
|
+----------------------------------+
| CARGOS |
+----------------------------------+
| id : bigint(20) |
+----------------------------------+
| nome : Varchar(60) |
| id_departamento_fk : bigint(20) |
+----------------------------------+
^
|
| cargo_id_fk : id
|
|
+----------------------------------+
| FUNCIONARIOS |
+----------------------------------+
| id : bigint(20) |
+----------------------------------+
| data_entrada : date |
| data_saida : date |
| nome : varchar(255) |
| salario : decimal(7,2) |
| cargo_id_fk : bigint(20) |
| endereco_id_fk : bigint(20) |
+----------------------------------+
^
|
| endereco_id_fk : id
|
|
+----------------------------------+
| ENDERECOS |
+----------------------------------+
| id : bigint(20) |
+----------------------------------+
| bairro : varchar(255) |
| cep : varchar(9) |
| cidade : varchar(255) |
| complemento : varchar(255) |
| logradouro : varchar(255) |
| numero : int(11) |
| uf : varchar(2) |
+----------------------------------+
Para mapear o relacionamento entre as tabelas departamentos e cargos,
usamos as classes Departamento e Cargo. Na classe Departamento usamos a
anotação @OneToMany sobre a declaração do atributo cargos.
@Entity
@Table(name = "DEPARTAMENTOS")
public class Departamento extends AbstractEntity<Long> {
@Column(name = "nome", nullable = false, unique = true, length = 60)
private String nome;
@OneToMany(mappedBy = "departamento")
private List<Cargo> cargos;
// métodos get/set omitidos
}
Já no mapeamento da classe Cargo, a anotação @ManyToOne deve ser declarada
junto ao atributo departamento. Ainda sobre este atributo, declaramos a anotação
@JoinColumn, para informar o nome da coluna que armazena as chaves estrangeiras
do relacionamento na tabela de cargos.
@Entity
@Table(name = "CARGOS")
public class Cargo extends AbstractEntity<Long> {
@Column(name = "nome", nullable = false, unique = true, length = 60)
private String nome;
@ManyToOne
@JoinColumn(name = "id_departamento_fk")
private Departamento departamento;
@OneToMany(mappedBy = "cargo")
private List<Funcionario> funcionarios;
// métodos get/set omitidos
}
A classe Cargo também deve possuir o mapeamento do lado fraco entre os relacionamento
1xN com Funcionario. Sendo assim, o atributo funcionarios, do tipo java.util.List,
é anotado com @OneToMany.
O valor do propriedade mappedBy deve coincidir com o nome do atributo mapeado na classe
Funcionario que representa a chave estrangeira deste relacionamento.
Este atributo é o cargo, anotado com @ManyToOne e @JoinColumn.
@Entity
@Table(name = "FUNCIONARIOS")
public class Funcionario extends AbstractEntity<Long> {
@Column(nullable = false, unique = true)
private String nome;