diff --git a/S300-SBoot-JPA-ORM/.idea/.gitignore b/S300-SBoot-JPA-ORM/.idea/.gitignore
new file mode 100644
index 0000000..4aa91ea
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/S300-SBoot-JPA-ORM/.idea/.name b/S300-SBoot-JPA-ORM/.idea/.name
new file mode 100644
index 0000000..54d8eec
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/.name
@@ -0,0 +1 @@
+spring-boot-basic
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/codeStyles/Project.xml b/S300-SBoot-JPA-ORM/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..c2621b8
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/codeStyles/Project.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/codeStyles/codeStyleConfig.xml b/S300-SBoot-JPA-ORM/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..df5f35d
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/compiler.xml b/S300-SBoot-JPA-ORM/.idea/compiler.xml
new file mode 100644
index 0000000..3ddd90a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/compiler.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/dataSources.xml b/S300-SBoot-JPA-ORM/.idea/dataSources.xml
new file mode 100644
index 0000000..96b0e73
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/dataSources.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ postgresql
+ true
+ org.postgresql.Driver
+ jdbc:postgresql://localhost:5432/postgres
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/encodings.xml b/S300-SBoot-JPA-ORM/.idea/encodings.xml
new file mode 100644
index 0000000..4140949
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/jarRepositories.xml b/S300-SBoot-JPA-ORM/.idea/jarRepositories.xml
new file mode 100644
index 0000000..a468a99
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__antlr_antlr_2_7_7.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__antlr_antlr_2_7_7.xml
new file mode 100644
index 0000000..536821c
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__antlr_antlr_2_7_7.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_4.xml
new file mode 100644
index 0000000..4fb416b
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_4.xml
new file mode 100644
index 0000000..eaa1d2c
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_classmate_1_5_1.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_classmate_1_5_1.xml
new file mode 100644
index 0000000..3b35db3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_classmate_1_5_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_12_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_12_4.xml
new file mode 100644
index 0000000..ee37165
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_12_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_12_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_12_4.xml
new file mode 100644
index 0000000..000575c
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_12_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_12_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_12_4.xml
new file mode 100644
index 0000000..f28c2fe
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_12_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_12_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_12_4.xml
new file mode 100644
index 0000000..378fcdd
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_12_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_12_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_12_4.xml
new file mode 100644
index 0000000..0b38ca4
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_12_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_12_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_12_4.xml
new file mode 100644
index 0000000..d2469df
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_12_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_5_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_5_0.xml
new file mode 100644
index 0000000..2995696
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_sun_activation_jakarta_activation_1_2_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_sun_activation_jakarta_activation_1_2_2.xml
new file mode 100644
index 0000000..b761c86
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_sun_activation_jakarta_activation_1_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_sun_istack_istack_commons_runtime_3_0_12.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_sun_istack_istack_commons_runtime_3_0_12.xml
new file mode 100644
index 0000000..9af2b23
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_sun_istack_istack_commons_runtime_3_0_12.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml
new file mode 100644
index 0000000..c987dd2
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_zaxxer_HikariCP_4_0_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_zaxxer_HikariCP_4_0_3.xml
new file mode 100644
index 0000000..dbe58c5
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__com_zaxxer_HikariCP_4_0_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml
new file mode 100644
index 0000000..be8b4b3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml
new file mode 100644
index 0000000..5ddce8f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_persistence_jakarta_persistence_api_2_2_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_persistence_jakarta_persistence_api_2_2_3.xml
new file mode 100644
index 0000000..913d3a6
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_persistence_jakarta_persistence_api_2_2_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_transaction_jakarta_transaction_api_1_3_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_transaction_jakarta_transaction_api_1_3_3.xml
new file mode 100644
index 0000000..85df205
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_transaction_jakarta_transaction_api_1_3_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml
new file mode 100644
index 0000000..2810cb2
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__mysql_mysql_connector_java_8_0_26.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__mysql_mysql_connector_java_8_0_26.xml
new file mode 100644
index 0000000..520ad76
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__mysql_mysql_connector_java_8_0_26.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_22.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_22.xml
new file mode 100644
index 0000000..77723ca
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_22.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_22.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_22.xml
new file mode 100644
index 0000000..db39ab4
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_22.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_minidev_accessors_smart_2_4_7.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_minidev_accessors_smart_2_4_7.xml
new file mode 100644
index 0000000..3e45701
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_minidev_accessors_smart_2_4_7.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_minidev_json_smart_2_4_7.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_minidev_json_smart_2_4_7.xml
new file mode 100644
index 0000000..0702e19
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__net_minidev_json_smart_2_4_7.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_12_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_12_0.xml
new file mode 100644
index 0000000..15427c5
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_12_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_14_1.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_14_1.xml
new file mode 100644
index 0000000..708458f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_14_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_14_1.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_14_1.xml
new file mode 100644
index 0000000..470a4e3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_14_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_50.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_50.xml
new file mode 100644
index 0000000..315a01a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_50.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_50.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_50.xml
new file mode 100644
index 0000000..efe2661
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_50.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_50.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_50.xml
new file mode 100644
index 0000000..a70ed2e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_50.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml
new file mode 100644
index 0000000..e6ecab0
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_aspectj_aspectjweaver_1_9_7.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_aspectj_aspectjweaver_1_9_7.xml
new file mode 100644
index 0000000..ff596e3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_aspectj_aspectjweaver_1_9_7.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_assertj_assertj_core_3_19_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_assertj_assertj_core_3_19_0.xml
new file mode 100644
index 0000000..34941e9
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_assertj_assertj_core_3_19_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_checkerframework_checker_qual_3_5_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_checkerframework_checker_qual_3_5_0.xml
new file mode 100644
index 0000000..b41c4fe
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_checkerframework_checker_qual_3_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_dom4j_dom4j_2_1_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_dom4j_dom4j_2_1_3.xml
new file mode 100644
index 0000000..c400430
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_dom4j_dom4j_2_1_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_glassfish_jaxb_jaxb_runtime_2_3_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_glassfish_jaxb_jaxb_runtime_2_3_4.xml
new file mode 100644
index 0000000..fd6a9bf
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_glassfish_jaxb_jaxb_runtime_2_3_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_glassfish_jaxb_txw2_2_3_4.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_glassfish_jaxb_txw2_2_3_4.xml
new file mode 100644
index 0000000..f5ba177
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_glassfish_jaxb_txw2_2_3_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml
new file mode 100644
index 0000000..130329b
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hibernate_common_hibernate_commons_annotations_5_1_2_Final.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hibernate_common_hibernate_commons_annotations_5_1_2_Final.xml
new file mode 100644
index 0000000..73228ef
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hibernate_common_hibernate_commons_annotations_5_1_2_Final.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hibernate_hibernate_core_5_4_32_Final.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hibernate_hibernate_core_5_4_32_Final.xml
new file mode 100644
index 0000000..82e8efe
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_hibernate_hibernate_core_5_4_32_Final.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_javassist_javassist_3_27_0_GA.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_javassist_javassist_3_27_0_GA.xml
new file mode 100644
index 0000000..eb801fc
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_javassist_javassist_3_27_0_GA.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_jboss_jandex_2_2_3_Final.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_jboss_jandex_2_2_3_Final.xml
new file mode 100644
index 0000000..9cc5eeb
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_jboss_jandex_2_2_3_Final.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_4_2_Final.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_4_2_Final.xml
new file mode 100644
index 0000000..42b1c0e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_4_2_Final.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_2.xml
new file mode 100644
index 0000000..85b487a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_2.xml
new file mode 100644
index 0000000..b693012
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_2.xml
new file mode 100644
index 0000000..c74eb1a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_2.xml
new file mode 100644
index 0000000..cfd0b6f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_2.xml
new file mode 100644
index 0000000..d70ccaa
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_2.xml
new file mode 100644
index 0000000..1744b10
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mapstruct_mapstruct_1_4_2_Final.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mapstruct_mapstruct_1_4_2_Final.xml
new file mode 100644
index 0000000..dc4063a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mapstruct_mapstruct_1_4_2_Final.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mapstruct_mapstruct_processor_1_4_2_Final.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mapstruct_mapstruct_processor_1_4_2_Final.xml
new file mode 100644
index 0000000..27dd97d
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mapstruct_mapstruct_processor_1_4_2_Final.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mockito_mockito_core_3_9_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mockito_mockito_core_3_9_0.xml
new file mode 100644
index 0000000..4e68823
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mockito_mockito_core_3_9_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_9_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_9_0.xml
new file mode 100644
index 0000000..e47ac06
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_9_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_objenesis_objenesis_3_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_objenesis_objenesis_3_2.xml
new file mode 100644
index 0000000..6b24b4f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_objenesis_objenesis_3_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml
new file mode 100644
index 0000000..718b32e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_ow2_asm_asm_9_1.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_ow2_asm_asm_9_1.xml
new file mode 100644
index 0000000..c8c7d46
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_ow2_asm_asm_9_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_postgresql_postgresql_42_2_23.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_postgresql_postgresql_42_2_23.xml
new file mode 100644
index 0000000..215d391
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_postgresql_postgresql_42_2_23.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_projectlombok_lombok_1_18_20.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_projectlombok_lombok_1_18_20.xml
new file mode 100644
index 0000000..7b4ef61
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_projectlombok_lombok_1_18_20.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml
new file mode 100644
index 0000000..69c5c8a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_32.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_32.xml
new file mode 100644
index 0000000..4460fd3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_32.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_32.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_32.xml
new file mode 100644
index 0000000..75b9f50
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_32.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_5_3.xml
new file mode 100644
index 0000000..bbe224e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_5_3.xml
new file mode 100644
index 0000000..4014df0
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_5_3.xml
new file mode 100644
index 0000000..2e6a648
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_aop_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_aop_2_5_3.xml
new file mode 100644
index 0000000..452e2e4
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_aop_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_data_jpa_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_data_jpa_2_5_3.xml
new file mode 100644
index 0000000..d59f864
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_data_jpa_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_jdbc_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_jdbc_2_5_3.xml
new file mode 100644
index 0000000..91f127d
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_jdbc_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_5_3.xml
new file mode 100644
index 0000000..b398592
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_5_3.xml
new file mode 100644
index 0000000..b5c21a2
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_5_3.xml
new file mode 100644
index 0000000..04da179
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_5_3.xml
new file mode 100644
index 0000000..7b7b8f6
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_5_3.xml
new file mode 100644
index 0000000..3edbf52
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_5_3.xml
new file mode 100644
index 0000000..8d5f328
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_5_3.xml
new file mode 100644
index 0000000..60b4c7a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_data_spring_data_commons_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_data_spring_data_commons_2_5_3.xml
new file mode 100644
index 0000000..7cac8c4
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_data_spring_data_commons_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_data_spring_data_jpa_2_5_3.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_data_spring_data_jpa_2_5_3.xml
new file mode 100644
index 0000000..55b50dc
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_data_spring_data_jpa_2_5_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_aop_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_aop_5_3_9.xml
new file mode 100644
index 0000000..a444650
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_aop_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_aspects_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_aspects_5_3_9.xml
new file mode 100644
index 0000000..b6aee10
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_aspects_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_beans_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_beans_5_3_9.xml
new file mode 100644
index 0000000..990971e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_beans_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_context_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_context_5_3_9.xml
new file mode 100644
index 0000000..98bd36a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_context_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_core_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_core_5_3_9.xml
new file mode 100644
index 0000000..0140c8b
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_core_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_expression_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_expression_5_3_9.xml
new file mode 100644
index 0000000..99e5928
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_expression_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_9.xml
new file mode 100644
index 0000000..e1b465e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_jdbc_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_jdbc_5_3_9.xml
new file mode 100644
index 0000000..b20e4d2
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_jdbc_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_orm_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_orm_5_3_9.xml
new file mode 100644
index 0000000..98e3093
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_orm_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_test_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_test_5_3_9.xml
new file mode 100644
index 0000000..2491913
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_test_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_tx_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_tx_5_3_9.xml
new file mode 100644
index 0000000..3903748
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_tx_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_web_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_web_5_3_9.xml
new file mode 100644
index 0000000..4645262
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_web_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_9.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_9.xml
new file mode 100644
index 0000000..de40cc4
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_8_2.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_8_2.xml
new file mode 100644
index 0000000..240445a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_8_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_yaml_snakeyaml_1_28.xml b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_yaml_snakeyaml_1_28.xml
new file mode 100644
index 0000000..e13f0e1
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/libraries/Maven__org_yaml_snakeyaml_1_28.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/misc.xml b/S300-SBoot-JPA-ORM/.idea/misc.xml
new file mode 100644
index 0000000..3007f2e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/misc.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/modules.xml b/S300-SBoot-JPA-ORM/.idea/modules.xml
new file mode 100644
index 0000000..42b47d8
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/uiDesigner.xml b/S300-SBoot-JPA-ORM/.idea/uiDesigner.xml
new file mode 100644
index 0000000..b93ac08
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/.idea/vcs.xml b/S300-SBoot-JPA-ORM/.idea/vcs.xml
new file mode 100644
index 0000000..2e3f692
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S300-SBoot-JPA-ORM/src/main/resources/application.yml b/S300-SBoot-JPA-ORM/src/main/resources/application.yml
index 8eaaf25..2b1a6a7 100644
--- a/S300-SBoot-JPA-ORM/src/main/resources/application.yml
+++ b/S300-SBoot-JPA-ORM/src/main/resources/application.yml
@@ -17,8 +17,8 @@ spring:
debug: enabled
datasource:
- username: "knits-orm"
- password: "jpa-tutorial"
+ username: "postgres"
+ password: "postgres"
jpa:
database: postgresql
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo01/Office.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo01/Office.java
index db7e3e5..31bf385 100644
--- a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo01/Office.java
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo01/Office.java
@@ -17,4 +17,5 @@ public class Office {
private String street;
+
}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/Employee.java
new file mode 100644
index 0000000..b87c709
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/Employee.java
@@ -0,0 +1,24 @@
+package com.knits.jpa.orm.d01.one.to.one.demo02.sharedpk;
+
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "employee")
+@Data
+public class Employee {
+
+ @Id
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @OneToOne
+ @MapsId
+ private Office office;
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/EmployeeRepository.java
new file mode 100644
index 0000000..02804db
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d01.one.to.one.demo02.sharedpk;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/Office.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/Office.java
new file mode 100644
index 0000000..b31ba90
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/Office.java
@@ -0,0 +1,19 @@
+package com.knits.jpa.orm.d01.one.to.one.demo02.sharedpk;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Office {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String city;
+
+ private String street;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/OfficeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/OfficeRepository.java
new file mode 100644
index 0000000..9d971fa
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/OfficeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d01.one.to.one.demo02.sharedpk;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface OfficeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/TestJpaDemo02.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/TestJpaDemo02.java
new file mode 100644
index 0000000..0099436
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo02/sharedpk/TestJpaDemo02.java
@@ -0,0 +1,138 @@
+package com.knits.jpa.orm.d01.one.to.one.demo02.sharedpk;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d01.one.to.one.demo02.*") //otherwise finds all other entities in subpackages
+@EnableJpaRepositories("com.knits.jpa.orm.d01.one.to.one.demo02.*") //otherwise doesnt create jpa repositories instances
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02"
+})
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaDemo02 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private OfficeRepository officeRepository;
+
+ @BeforeEach // fill data before each test than IDs same all time.
+ @Rollback(value = false)
+ public void initDatabase(){
+
+ Office office = new Office();
+ office.setCity("A Mock City");
+ office.setStreet("A Mock Street");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Anton");
+ employee.setLastName("Mezhenin");
+ employee.setOffice(office);
+
+ officeRepository.save(office);
+ employeeRepository.save(employee);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployee(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ Assertions.assertThat(employee.getId()).isEqualTo(1L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithSameOfficeId(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ Assertions.assertThat(employee.getOffice().getId()).isEqualTo(1L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfEmployees(){
+
+ List employees = employeeRepository.findAll();
+
+ Assertions.assertThat(employees.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeTest(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ employee.setLastName("Great");
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+
+ Assertions.assertThat(employeeUpdated.getLastName()).isEqualTo("Great");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void deleteEmployee(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(1L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //firstly have to delete employee and after office
+ public void deleteEmployeeAndOffice(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ employeeRepository.delete(employee);
+
+ Office office = officeRepository.findById(1L).get();
+
+ officeRepository.delete(office);
+
+ Office office1 = null;
+
+ Optional optionalOffice = officeRepository.findById(1L);
+
+ if(optionalOffice.isPresent()){
+ office1 = optionalOffice.get();
+ }
+
+ Assertions.assertThat(office1).isNull();
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/Employee.java
new file mode 100644
index 0000000..a6ce7cf
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/Employee.java
@@ -0,0 +1,33 @@
+package com.knits.jpa.orm.d01.one.to.one.demo03.linktable;
+
+import lombok.Data;
+import org.hibernate.annotations.Cascade;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "employee")
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @OneToOne
+ @JoinTable(name = "EMPLOYEE_OFFICE_JOIN_TABLE",
+ joinColumns = {
+ @JoinColumn(name = "EMPLOYEE_FK", referencedColumnName = "id")
+ },
+ inverseJoinColumns = {
+ @JoinColumn(name = "OFFICE_FK", referencedColumnName = "id", unique = true)
+ }
+ )
+ private Office office;
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/EmployeeRepository.java
new file mode 100644
index 0000000..f92a389
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/EmployeeRepository.java
@@ -0,0 +1,9 @@
+package com.knits.jpa.orm.d01.one.to.one.demo03.linktable;
+
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/Office.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/Office.java
new file mode 100644
index 0000000..07245e7
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/Office.java
@@ -0,0 +1,19 @@
+package com.knits.jpa.orm.d01.one.to.one.demo03.linktable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Office {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String city;
+
+ private String street;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/OfficeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/OfficeRepository.java
new file mode 100644
index 0000000..a7f106c
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/OfficeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d01.one.to.one.demo03.linktable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface OfficeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/TestJpaDemo03.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/TestJpaDemo03.java
new file mode 100644
index 0000000..61f6646
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo03/linktable/TestJpaDemo03.java
@@ -0,0 +1,139 @@
+package com.knits.jpa.orm.d01.one.to.one.demo03.linktable;
+
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d01.one.to.one.demo03.*") //otherwise finds all other entities in subpackages
+@EnableJpaRepositories("com.knits.jpa.orm.d01.one.to.one.demo03.*") //otherwise doesnt create jpa repositories instances
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-03"
+})
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaDemo03 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private OfficeRepository officeRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase(){
+
+ Office office = new Office();
+ office.setCity("A Mock City");
+ office.setStreet("A Mock Street");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Anton");
+ employee.setLastName("Mezhenin");
+ employee.setOffice(office);
+
+ officeRepository.save(office);
+ employeeRepository.save(employee);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getId()).isEqualTo(52L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithOfficeId(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getOffice().getId()).isEqualTo(1L);
+ }
+
+ @Test
+ public void getListOfEmployees(){
+
+ List employees = employeeRepository.findAll();
+
+ Assertions.assertThat(employees.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.setLastName("Great");
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+
+ Assertions.assertThat(employeeUpdated.getLastName()).isEqualTo("Great");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete data from Employee and join table without conflicts. Office exists
+ public void deleteEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //Firstly have to delete employee and after delete office
+ public void deleteOffice(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Office office = officeRepository.findById(1L).get();
+
+ officeRepository.delete(office);
+
+ Office office1 = null;
+
+ Optional optionalOffice = officeRepository.findById(1L);
+
+ if(optionalOffice.isPresent()){
+ office1 = optionalOffice.get();
+ }
+
+ Assertions.assertThat(office1).isNull();
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/Employee.java
new file mode 100644
index 0000000..fc79f41
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/Employee.java
@@ -0,0 +1,32 @@
+package com.knits.jpa.orm.d01.one.to.one.demo04.bidirectionaljointable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "employee")
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @OneToOne
+ @JoinTable(name = "EMPLOYEE_OFFICE_JOIN_TABLE",
+ joinColumns = {
+ @JoinColumn(name = "EMPLOYEE_FK", referencedColumnName = "id")
+ },
+ inverseJoinColumns = {
+ @JoinColumn(name = "OFFICE_FK", referencedColumnName = "id", unique = true)
+ }
+ )
+ private Office office;
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/EmployeeRepository.java
new file mode 100644
index 0000000..2a55439
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d01.one.to.one.demo04.bidirectionaljointable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/Office.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/Office.java
new file mode 100644
index 0000000..80737d0
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/Office.java
@@ -0,0 +1,22 @@
+package com.knits.jpa.orm.d01.one.to.one.demo04.bidirectionaljointable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Office {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String city;
+
+ private String street;
+
+ @OneToOne(mappedBy = "office")
+ private Employee employee;
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/OfficeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/OfficeRepository.java
new file mode 100644
index 0000000..e6a614f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/OfficeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d01.one.to.one.demo04.bidirectionaljointable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface OfficeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/TestJpaDemo04.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/TestJpaDemo04.java
new file mode 100644
index 0000000..3eb1a03
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo04/bidirectionaljointable/TestJpaDemo04.java
@@ -0,0 +1,141 @@
+package com.knits.jpa.orm.d01.one.to.one.demo04.bidirectionaljointable;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d01.one.to.one.demo04.*") //otherwise finds all other entities in subpackages
+@EnableJpaRepositories("com.knits.jpa.orm.d01.one.to.one.demo04.*") //otherwise doesnt create jpa repositories instances
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-04"
+})
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaDemo04 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private OfficeRepository officeRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase(){
+
+ Office office = new Office();
+ office.setCity("A Mock City");
+ office.setStreet("A Mock Street");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Anton");
+ employee.setLastName("Mezhenin");
+
+ office.setEmployee(employee);
+ employee.setOffice(office);
+
+ officeRepository.save(office);
+ employeeRepository.save(employee);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getId()).isEqualTo(52L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithOfficeId(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getOffice().getId()).isEqualTo(1L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfEmployees(){
+
+ List employees = employeeRepository.findAll();
+
+ Assertions.assertThat(employees.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.setLastName("Great");
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+
+ Assertions.assertThat(employeeUpdated.getLastName()).isEqualTo("Great");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete Employee without conflicts. Office exists
+ public void deleteEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //Firstly have to delete employee and then delete office
+ public void deleteOffice(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Office office = officeRepository.findById(1L).get();
+
+ officeRepository.delete(office);
+
+ Office office1 = null;
+
+ Optional optionalOffice = officeRepository.findById(1L);
+
+ if(optionalOffice.isPresent()){
+ office1 = optionalOffice.get();
+ }
+
+ Assertions.assertThat(office1).isNull();
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/Employee.java
new file mode 100644
index 0000000..109703e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/Employee.java
@@ -0,0 +1,24 @@
+package com.knits.jpa.orm.d01.one.to.one.demo05.bidirectionalCascade;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "employee")
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @OneToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "office_id")
+ private Office office;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/EmployeeRepository.java
new file mode 100644
index 0000000..46743b5
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d01.one.to.one.demo05.bidirectionalCascade;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/Office.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/Office.java
new file mode 100644
index 0000000..6249633
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/Office.java
@@ -0,0 +1,26 @@
+package com.knits.jpa.orm.d01.one.to.one.demo05.bidirectionalCascade;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Office {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String city;
+
+ private String street;
+
+ @OneToOne(
+ mappedBy = "office",
+ fetch = FetchType.LAZY,
+ cascade = CascadeType.ALL
+ )
+ private Employee employee;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/OfficeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/OfficeRepository.java
new file mode 100644
index 0000000..f125d86
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/OfficeRepository.java
@@ -0,0 +1,6 @@
+package com.knits.jpa.orm.d01.one.to.one.demo05.bidirectionalCascade;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface OfficeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/TestJpaDemo05.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/TestJpaDemo05.java
new file mode 100644
index 0000000..d8c8a78
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d01/one/to/one/demo05/bidirectionalCascade/TestJpaDemo05.java
@@ -0,0 +1,95 @@
+package com.knits.jpa.orm.d01.one.to.one.demo05.bidirectionalCascade;
+
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d01.one.to.one.demo05.*") //otherwise finds all other entities in subpackages
+@EnableJpaRepositories("com.knits.jpa.orm.d01.one.to.one.demo05.*") //otherwise doesnt create jpa repositories instances
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-05"
+})
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaDemo05 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private OfficeRepository officeRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase(){
+
+ Office office = new Office();
+ office.setCity("A Mock City");
+ office.setStreet("A Mock Street");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Anton");
+ employee.setLastName("Mezhenin");
+
+ office.setEmployee(employee);
+ employee.setOffice(office);
+
+ officeRepository.save(office);
+ employeeRepository.save(employee);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete data from Employee and join table without conflicts. Office exists
+ public void deleteEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //Can delete office and employee by cascade
+ public void deleteOffice(){
+
+ Office office = officeRepository.findById(1L).get();
+
+ officeRepository.delete(office);
+
+ Office office1 = null;
+
+ Optional optionalOffice = officeRepository.findById(1L);
+
+ if(optionalOffice.isPresent()){
+ office1 = optionalOffice.get();
+ }
+
+ Assertions.assertThat(office1).isNull();
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo01/TestJpaOneToManyDemo01.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo01/TestJpaOneToManyDemo01.java
index 5ac3199..07b81b6 100644
--- a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo01/TestJpaOneToManyDemo01.java
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo01/TestJpaOneToManyDemo01.java
@@ -1,6 +1,8 @@
package com.knits.jpa.orm.d02.one.to.many.demo01;
import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
@@ -8,19 +10,25 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.TestPropertySource;
+import java.util.List;
+import java.util.Optional;
+
@DataJpaTest
@EntityScan("com.knits.jpa.orm.d02.one.to.many.demo01")
@EnableJpaRepositories("com.knits.jpa.orm.d02.one.to.many.demo01")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource(properties = {
- "spring.jpa.hibernate.ddl-auto=update",
- "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02"
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02-01"
})
@Slf4j
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class TestJpaOneToManyDemo01 {
@Autowired
@@ -29,12 +37,11 @@ public class TestJpaOneToManyDemo01 {
@Autowired
private ProjectRepository projectRepository;
- @Test
+ @BeforeEach
@Rollback(value = false)
+ //In Db Employee table we can see project_id
public void initDatabase(){
-
-
Project project = new Project();
project.setName("A Mock Project Name");
@@ -61,4 +68,85 @@ public void initDatabase(){
savedProject.getEmployees().forEach(emp -> log.info("Employee Found: {} ",emp.getFirstName()));
}
+
+ @Test
+ public void getProjectEmployeeList(){
+
+ Project project = projectRepository.findById(52L).get();
+
+ Assertions.assertThat(project.getEmployees().size()).isGreaterThan(0);
+ }
+
+ @Test
+ public void getListOfProjectsTest(){
+
+ List projects = projectRepository.findAll();
+
+ Assertions.assertThat(projects.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndProjectTest(){
+
+ Project project = projectRepository.findById(52L).get();
+
+ project.setName("Mock 2");
+ project.getEmployees().forEach(emp -> emp.setFirstName("Anton"));
+
+ Project projectUpdated = projectRepository.save(project);
+ Employee employeeUpdated = projectUpdated.getEmployees().get(1);
+
+ Assertions.assertThat(projectUpdated.getName()).isEqualTo("Mock 2");
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete employee if he in relationships with project
+ public void deleteEmployeeTest(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(1L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //Can't delete a project if it has employees
+ //must first delete the employees and then the project
+ public void deleteProjectTest(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+ Employee employee1 = employeeRepository.findById(2L).get();
+
+ employeeRepository.delete(employee);
+ employeeRepository.delete(employee1);
+
+ Project project = projectRepository.findById(52L).get();
+ projectRepository.delete(project);
+
+ Project project1 = null;
+
+ Optional optionalProject = projectRepository.findById(52L);
+
+ if(optionalProject.isPresent()){
+ project1 = optionalProject.get();
+ }
+
+ Assertions.assertThat(project1).isNull();
+
+ }
}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/Employee.java
new file mode 100644
index 0000000..c24a9d8
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/Employee.java
@@ -0,0 +1,19 @@
+package com.knits.jpa.orm.d02.one.to.many.demo02.linktable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/EmployeeRepository.java
new file mode 100644
index 0000000..da73648
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo02.linktable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/Project.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/Project.java
new file mode 100644
index 0000000..695ec44
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/Project.java
@@ -0,0 +1,25 @@
+package com.knits.jpa.orm.d02.one.to.many.demo02.linktable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Data
+public class Project {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+
+ @OneToMany
+ @JoinTable(name = "EMPLOYEE_PROJECT_TABLE",
+ joinColumns = {@JoinColumn(name = "PROJECT_FK")},
+ inverseJoinColumns = {@JoinColumn(name = "EMPLOYEE_FK")}
+ )
+ private List employeeList = new ArrayList<>();
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/ProjectRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/ProjectRepository.java
new file mode 100644
index 0000000..864681f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/ProjectRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo02.linktable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProjectRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/TestJpaOneToManyDemo02.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/TestJpaOneToManyDemo02.java
new file mode 100644
index 0000000..a98f889
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo02/linktable/TestJpaOneToManyDemo02.java
@@ -0,0 +1,146 @@
+package com.knits.jpa.orm.d02.one.to.many.demo02.linktable;
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d02.one.to.many.demo02.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d02.one.to.many.demo02.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02-02"
+})
+@Slf4j
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaOneToManyDemo02 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private ProjectRepository projectRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ //In DB Employee table project_id is null
+ public void initDatabase(){
+
+ Project project = new Project();
+ project.setName("A Mock Project Name");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ project.getEmployeeList().add(employee);
+ project.getEmployeeList().add(employee2);
+
+ employeeRepository.save(employee);
+ employeeRepository.save(employee2);
+ Project savedProject = projectRepository.save(project);
+
+ log.info("Employees for Project: {} ",savedProject.getName());
+ savedProject.getEmployeeList().forEach(emp -> log.info("Employee Found: {} ",emp.getFirstName()));
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getProjectWithEmployees(){
+
+ Project project = projectRepository.findById(52L).get();
+
+ Assertions.assertThat(project.getEmployeeList().size()).isGreaterThan(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfProjects(){
+
+ List projects = projectRepository.findAll();
+
+ Assertions.assertThat(projects.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndProject(){
+
+ Project project = projectRepository.findById(52L).get();
+
+ project.setName("Mock 2");
+ project.getEmployeeList().forEach(emp -> emp.setFirstName("Anton"));
+
+ Project projectUpdated = projectRepository.save(project);
+ Employee employeeUpdated = projectUpdated.getEmployeeList().get(1);
+
+ Assertions.assertThat(projectUpdated.getName()).isEqualTo("Mock 2");
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can not delete employee if he in relationships with project
+ //Have to delete employee from list and after delete employee
+ public void removeEmployeeFromProjectAndDeleteEmployee(){
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ Project project = projectRepository.findById(52L).get();
+ project.getEmployeeList().remove(employee);
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(1L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ project.getEmployeeList().forEach(emp -> log.info("Employee Found: {} ",emp.getFirstName()));
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete the project even if there is a list with employees
+ public void deleteProject(){
+
+ Project project = projectRepository.findById(52L).get();
+ projectRepository.delete(project);
+
+ Project project1 = null;
+
+ Optional optionalProject = projectRepository.findById(52L);
+
+ if(optionalProject.isPresent()){
+ project1 = optionalProject.get();
+ }
+
+ Assertions.assertThat(project1).isNull();
+
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/Employee.java
new file mode 100644
index 0000000..0332d4a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/Employee.java
@@ -0,0 +1,21 @@
+package com.knits.jpa.orm.d02.one.to.many.demo03.FKey;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Employee {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @ManyToOne
+ private Project project;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/EmployeeRepository.java
new file mode 100644
index 0000000..59e1db7
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo03.FKey;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/Project.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/Project.java
new file mode 100644
index 0000000..0ada02e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/Project.java
@@ -0,0 +1,17 @@
+package com.knits.jpa.orm.d02.one.to.many.demo03.FKey;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Project {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/ProjectRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/ProjectRepository.java
new file mode 100644
index 0000000..2ffe6f6
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/ProjectRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo03.FKey;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProjectRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/TestJpaOneToManyDemo03.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/TestJpaOneToManyDemo03.java
new file mode 100644
index 0000000..4142005
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo03/FKey/TestJpaOneToManyDemo03.java
@@ -0,0 +1,144 @@
+package com.knits.jpa.orm.d02.one.to.many.demo03.FKey;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d02.one.to.many.demo03.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d02.one.to.many.demo03.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02-03"
+})
+@Slf4j
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaOneToManyDemo03 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private ProjectRepository projectRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ //In Db Employee table we can see project_id
+ public void initDatabase(){
+
+ Project project = new Project();
+ project.setName("A Mock Project Name");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ employee.setProject(project);
+ employee2.setProject(project);
+
+ projectRepository.save(project);
+ employeeRepository.save(employee);
+ employeeRepository.save(employee2);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithProject(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getProject().getName()).isEqualTo("A Mock Project Name");
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfEmployees(){
+
+ List employees = employeeRepository.findAll();
+
+ Assertions.assertThat(employees.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndProject(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.getProject().setName("Mock 2");
+ employee.setFirstName("Anton");
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+ Assertions.assertThat(employeeUpdated.getProject().getName()).isEqualTo("Mock 2");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete employee with project reference
+ public void deleteEmployee(){
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if(optionalEmployee.isPresent()){
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //I can't delete a project if it has employees
+ public void deleteProject(){
+
+ Employee employee = employeeRepository.findById(53L).get();
+ employee.setProject(null);
+
+ Employee employee2 = employeeRepository.findById(52L).get();
+ employee2.setProject(null);
+
+ Project project = projectRepository.findById(1L).get();
+ projectRepository.delete(project);
+
+ Project project1 = null;
+
+ Optional optionalProject = projectRepository.findById(1L);
+
+ if(optionalProject.isPresent()){
+ project1 = optionalProject.get();
+ }
+
+ Assertions.assertThat(project1).isNull();
+
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/Employee.java
new file mode 100644
index 0000000..c5aa274
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/Employee.java
@@ -0,0 +1,39 @@
+package com.knits.jpa.orm.d02.one.to.many.demo04.bidirectionalJoinTable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ /*
+ By default, a bidirectional OneToMany/ManyToOne association uses a foreign
+ key column on the side which has the single-valued reference with @ManyToOne annotation.
+ We can override this default by using an intermediate join table to persist the association.
+ To achieve that we have to use @JoinTable annotation on the both sides.
+ In this case, we don't have to use 'mappedBy' element of the @OneToMany annotation.
+
+ Note that we have to use insertable/updatable=false on @ManyToOne side,
+ to avoid persisting same relationship twice from both sides. When insertable/updatable=false,
+ the column is not included in the generated SQL INSERT/UPDATE statements.
+ */
+ @ManyToOne
+ @JoinTable(name = "EMPLOYEE_PROJECT_TABLE",
+ joinColumns = {@JoinColumn(name = "EMPLOYEE_FK", insertable = false,
+ updatable = false, referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "PROJECT_FK", insertable = false,
+ updatable = false, referencedColumnName = "id")}
+ )
+ private Project project;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/EmployeeRepository.java
new file mode 100644
index 0000000..18b507f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo04.bidirectionalJoinTable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/Project.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/Project.java
new file mode 100644
index 0000000..3e6a1b4
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/Project.java
@@ -0,0 +1,34 @@
+package com.knits.jpa.orm.d02.one.to.many.demo04.bidirectionalJoinTable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Data
+public class Project {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+
+
+ /*
+ By default, a bidirectional OneToMany/ManyToOne association uses a foreign
+ key column on the side which has the single-valued reference with @ManyToOne annotation.
+ We can override this default by using an intermediate join table to persist the association.
+ To achieve that we have to use @JoinTable annotation on the both sides.
+ In this case, we don't have to use 'mappedBy' element of the @OneToMany annotation.
+ */
+ @OneToMany
+ @JoinTable(name = "EMPLOYEE_PROJECT_TABLE",
+ joinColumns = {@JoinColumn(name = "PROJECT_FK", referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "EMPLOYEE_FK", referencedColumnName = "id")}
+ )
+ private List employeeList = new ArrayList<>();
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/ProjectRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/ProjectRepository.java
new file mode 100644
index 0000000..15a76a3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/ProjectRepository.java
@@ -0,0 +1,9 @@
+package com.knits.jpa.orm.d02.one.to.many.demo04.bidirectionalJoinTable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProjectRepository extends JpaRepository {
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/TestJpaOneToManyDemo04.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/TestJpaOneToManyDemo04.java
new file mode 100644
index 0000000..6b52d58
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo04/bidirectionalJoinTable/TestJpaOneToManyDemo04.java
@@ -0,0 +1,145 @@
+package com.knits.jpa.orm.d02.one.to.many.demo04.bidirectionalJoinTable;
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d02.one.to.many.demo04.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d02.one.to.many.demo04.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02-04"
+})
+@Slf4j
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaOneToManyDemo04 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private ProjectRepository projectRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase() {
+
+ Project project = new Project();
+ project.setName("A Mock Project Name");
+
+ Employee employee = new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ project.getEmployeeList().add(employee);
+ project.getEmployeeList().add(employee2);
+
+ employeeRepository.save(employee);
+ employeeRepository.save(employee2);
+ Project savedProject = projectRepository.save(project);
+
+ log.info("Employees for Project: {} ", savedProject.getName());
+ savedProject.getEmployeeList().forEach(emp -> log.info("Employee Found: {} ", emp.getFirstName()));
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getProjectWithEmployees() {
+
+ Project project = projectRepository.findById(52L).get();
+
+ Assertions.assertThat(project.getEmployeeList().size()).isGreaterThan(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfProjects() {
+
+ List projects = projectRepository.findAll();
+
+ Assertions.assertThat(projects.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndProject() {
+
+ Project project = projectRepository.findById(52L).get();
+
+ project.setName("Mock 2");
+ project.getEmployeeList().forEach(emp -> emp.setFirstName("Anton"));
+
+ Project projectUpdated = projectRepository.save(project);
+ Employee employeeUpdated = projectUpdated.getEmployeeList().get(1);
+
+ Assertions.assertThat(projectUpdated.getName()).isEqualTo("Mock 2");
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ // can delete an employee who is on the project
+ public void deleteEmployee() {
+
+ Employee employee = employeeRepository.findById(1L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(1L);
+
+ if (optionalEmployee.isPresent()) {
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete the project even if there is a list with employees
+ //can delete both employees and project without any conflicts. Even if objects are related
+ public void deleteProject() {
+
+ Project project = projectRepository.findById(52L).get();
+ projectRepository.delete(project);
+
+ Project project1 = null;
+
+ Optional optionalProject = projectRepository.findById(52L);
+
+ if (optionalProject.isPresent()) {
+ project1 = optionalProject.get();
+ }
+
+ Assertions.assertThat(project1).isNull();
+
+ }
+
+ /*
+ can delete both workers and the project without any conflicts. Even if u objects are related
+ */
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/Employee.java
new file mode 100644
index 0000000..bd47cdf
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/Employee.java
@@ -0,0 +1,36 @@
+package com.knits.jpa.orm.d02.one.to.many.demo05.Sets;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Project project;
+
+
+ /*It's important to @Override the equals() and hashCode() method since the Author entity relies on
+ checking equality for it's helper methods...*/
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Employee )) return false;
+ return id != null && id.equals(((Employee) o).getId());
+ }
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/EmployeeRepository.java
new file mode 100644
index 0000000..2a3506e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo05.Sets;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/Project.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/Project.java
new file mode 100644
index 0000000..4df84e0
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/Project.java
@@ -0,0 +1,35 @@
+package com.knits.jpa.orm.d02.one.to.many.demo05.Sets;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+@Entity
+@Data
+public class Project {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+
+ @OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = false)
+ private Set employees = new HashSet<>();
+
+ public void addEmployee(Employee employee) {
+ employees.add(employee);
+ employee.setProject(this);
+ }
+
+ public void removeEmployee(Employee employee) {
+ employees.remove(employee);
+ employee.setProject(null);
+
+ }
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/ProjectRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/ProjectRepository.java
new file mode 100644
index 0000000..15eab7e
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/ProjectRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d02.one.to.many.demo05.Sets;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProjectRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/TestJpaOneToManyDemo05.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/TestJpaOneToManyDemo05.java
new file mode 100644
index 0000000..1a23043
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d02/one/to/many/demo05/Sets/TestJpaOneToManyDemo05.java
@@ -0,0 +1,181 @@
+package com.knits.jpa.orm.d02.one.to.many.demo05.Sets;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d02.one.to.many.demo05.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d02.one.to.many.demo05.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-02-05"
+})
+@Slf4j
+//to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaOneToManyDemo05 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private ProjectRepository projectRepository;
+
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase() {
+
+ Project project = new Project();
+ project.setName("A Mock Project Name");
+
+ Employee employee1 = new Employee();
+ employee1.setFirstName("Stefano");
+ employee1.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ //it works, but project_id in Employee table is null
+ /*project.getEmployees().add(employee);
+ project.getEmployees().add(employee2);*/
+
+ /*The helper methods addBook() and removeBook() are useful in keeping the persisted context in sync.
+ Strange things can happen when both sides of the bidirectional relationship aren't updated.
+ The database can get out of sync with the context and unexpected things can happen.
+ These methods make it easy to update both sides of the relationship...*/
+ //via helper methods in model project_id is not null
+ project.addEmployee(employee1);
+ project.addEmployee(employee2);
+
+ Project savedProject = projectRepository.save(project);
+ employeeRepository.save(employee1);
+ employeeRepository.save(employee2);
+
+ log.info("Employees for Project: {} ", savedProject.getName());
+ savedProject.getEmployees().forEach(emp -> log.info("Employee Found: {} ", emp.getFirstName()));
+
+ }
+
+ @Test
+ @Order(1)
+ @Rollback(value = false)
+ public void getProjectWithEmployees() {
+
+ Project project = projectRepository.findById(1L).get();
+
+ Assertions.assertThat(project.getEmployees().size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Order(2)
+ @Rollback(value = false)
+ public void getListOfProjects() {
+
+ List projects = projectRepository.findAll();
+
+ Assertions.assertThat(projects.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ @Order(3)
+ public void updateEmployeeAndProject() {
+
+ Project project = projectRepository.findById(1L).get();
+
+ project.setName("Mock 2");
+ project.getEmployees().forEach(emp -> emp.setFirstName("Anton"));
+
+ Project projectUpdated = projectRepository.save(project);
+ Employee employeeUpdated = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(projectUpdated.getName()).isEqualTo("Mock 2");
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ @Order(4)
+ public void deleteEmployee() {
+
+ Employee employee = employeeRepository.findById(53L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(53L);
+
+ if (optionalEmployee.isPresent()) {
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+
+ }
+
+
+ @Test
+ @Rollback(value = false)
+ @Order(5)
+ public void deleteProjectShouldNotDeleteEmployees() {
+
+ Project project = projectRepository.findById(1L).get();
+
+ Employee employee = employeeRepository.findById(52L).get();
+ Employee employee1 = employeeRepository.findById(53L).get();
+
+ project.removeEmployee(employee);
+ project.removeEmployee(employee1);
+
+ projectRepository.delete(project);
+
+ List employees = employeeRepository.findAll();
+
+ Assertions.assertThat(employees.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ @Order(6)
+ //since I have a project like parent, all children (employees) deletes with project
+ public void deleteProject() {
+
+ Project project = projectRepository.findById(1L).get();
+
+ projectRepository.delete(project);
+
+ Project project1 = null;
+
+ Optional optionalProject = projectRepository.findById(1L);
+
+ if (optionalProject.isPresent()) {
+ project1 = optionalProject.get();
+ }
+
+ Assertions.assertThat(project1).isNull();
+
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo01/TestJpaManyToManyDemo01.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo01/TestJpaManyToManyDemo01.java
index 7643b02..5cd8fc6 100644
--- a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo01/TestJpaManyToManyDemo01.java
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo01/TestJpaManyToManyDemo01.java
@@ -1,6 +1,8 @@
package com.knits.jpa.orm.d03.many.to.many.demo01;
+import com.knits.jpa.orm.d02.one.to.many.demo04.bidirectionalJoinTable.Project;
import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
@@ -31,9 +33,9 @@ public class TestJpaManyToManyDemo01 {
@Test
@Rollback(value = false)
- public void initDatabase(){
+ public void initDatabase() {
- Employee employee= new Employee();
+ Employee employee = new Employee();
employee.setFirstName("Stefano");
employee.setLastName("Fiorenza");
@@ -65,11 +67,12 @@ public void initDatabase(){
employeeRepository.save(employee2);
employeeRepository.save(employee3);
- Group savedGroup =groupRepository.save(group);
+ Group savedGroup = groupRepository.save(group);
groupRepository.save(group2);
- log.info("Employees for Group: {} ",savedGroup.getName());
- savedGroup.getEmployees().forEach(emp -> log.info("Employee Found: {} ",emp.getFirstName()));
+ log.info("Employees for Group: {} ", savedGroup.getName());
+ savedGroup.getEmployees().forEach(emp -> log.info("Employee Found: {} ", emp.getFirstName()));
}
+
}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/Employee.java
new file mode 100644
index 0000000..9efdf92
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/Employee.java
@@ -0,0 +1,29 @@
+package com.knits.jpa.orm.d03.many.to.many.demo02.linkTable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Data
+/*The entity having the collection reference is called 'source' entity',
+whereas the entity which is being referenced is called 'target entity'.
+To map many-to-many association to database tables,
+@ManyToMany annotation is used on the collection.*/
+//Source entity
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @ManyToMany
+ private List groups = new ArrayList<>(); //Group is target entity
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/EmployeeRepository.java
new file mode 100644
index 0000000..fabda30
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo02.linkTable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/Group.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/Group.java
new file mode 100644
index 0000000..7c6fce3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/Group.java
@@ -0,0 +1,19 @@
+package com.knits.jpa.orm.d03.many.to.many.demo02.linkTable;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name="\"group\"") //group is a reserved word in sql
+@Data
+//Target
+public class Group {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/GroupRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/GroupRepository.java
new file mode 100644
index 0000000..cbcee75
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/GroupRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo02.linkTable;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface GroupRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/TestJpaManyToManyDemo02.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/TestJpaManyToManyDemo02.java
new file mode 100644
index 0000000..5920e6f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo02/linkTable/TestJpaManyToManyDemo02.java
@@ -0,0 +1,163 @@
+package com.knits.jpa.orm.d03.many.to.many.demo02.linkTable;
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d03.many.to.many.demo02.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d03.many.to.many.demo02.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-03-01"
+})
+@Slf4j
+//help to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaManyToManyDemo02 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private GroupRepository groupRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase(){
+
+ Employee employee= new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ Employee employee3 = new Employee();
+ employee3.setFirstName("Maria");
+ employee3.setLastName("Bertolucci");
+
+ Group group = new Group();
+ group.setName("A Mock Group Name");
+
+ Group group2 = new Group();
+ group2.setName("Another Mock Group Name");
+
+ //emp 1 and 2 are in group1
+ employee.getGroups().add(group);
+ employee2.getGroups().add(group);
+
+ //emp 3 and 1 are in group2
+ employee3.getGroups().add(group2);
+ employee.getGroups().add(group2);
+
+ groupRepository.save(group);
+ groupRepository.save(group2);
+
+ Employee savedEmployee = employeeRepository.save(employee);
+ employeeRepository.save(employee2);
+ employeeRepository.save(employee3);
+
+ log.info("Employee: {} ",savedEmployee.getFirstName());
+ savedEmployee.getGroups().forEach(gr -> log.info("Groups Found: {} ",gr.getName()));
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithGroups() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getGroups().size()).isGreaterThan(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfGroups() {
+
+ List groups = groupRepository.findAll();
+
+ Assertions.assertThat(groups.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.setFirstName("Anton");
+ employee.getGroups().forEach(emp -> emp.setName("Group updated"));
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+ Assertions.assertThat(employeeUpdated.getGroups().get(1).getName()).isEqualTo("Group updated");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete an employee who in the group
+ public void deleteEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if (optionalEmployee.isPresent()) {
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can not delete the group/target with employees/source
+ //should remove employees from group then can delete group
+ public void removeEmployeesFromGroupThenDeleteGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+ Employee employee1 = employeeRepository.findById(53L).get();
+
+ Group group = groupRepository.findById(1L).get();
+
+ employee.getGroups().remove(group);
+ employee1.getGroups().remove(group);
+
+ groupRepository.delete(group);
+
+ Group group1 = null;
+
+ Optional optionalGroup = groupRepository.findById(1L);
+
+ if (optionalGroup.isPresent()) {
+ group1 = optionalGroup.get();
+ }
+
+ Assertions.assertThat(group1).isNull();
+
+ }
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/Employee.java
new file mode 100644
index 0000000..c260310
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/Employee.java
@@ -0,0 +1,25 @@
+package com.knits.jpa.orm.d03.many.to.many.demo03.bidirectional;
+
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @ManyToMany
+ private List groups = new ArrayList<>();
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/EmployeeRepository.java
new file mode 100644
index 0000000..1aa199d
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo03.bidirectional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/Group.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/Group.java
new file mode 100644
index 0000000..111b51c
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/Group.java
@@ -0,0 +1,25 @@
+package com.knits.jpa.orm.d03.many.to.many.demo03.bidirectional;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Table(name="\"group\"") //group is a reserved word in sql
+@Data
+public class Group {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+
+ @ManyToMany
+ private List employees = new ArrayList<>();
+
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/GroupRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/GroupRepository.java
new file mode 100644
index 0000000..fc28c2f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/GroupRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo03.bidirectional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface GroupRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/TestJpaManyToManyDemo03.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/TestJpaManyToManyDemo03.java
new file mode 100644
index 0000000..2fda88c
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo03/bidirectional/TestJpaManyToManyDemo03.java
@@ -0,0 +1,164 @@
+package com.knits.jpa.orm.d03.many.to.many.demo03.bidirectional;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d03.many.to.many.demo03.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d03.many.to.many.demo03.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-03-02"
+})
+@Slf4j
+//help to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaManyToManyDemo03 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private GroupRepository groupRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ //created two tables with FKs - employee_groups(with records) and group_employees(this dont have records)
+ public void initDatabase(){
+
+ Employee employee= new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ Employee employee3 = new Employee();
+ employee3.setFirstName("Maria");
+ employee3.setLastName("Bertolucci");
+
+ Group group = new Group();
+ group.setName("A Mock Group Name");
+
+ Group group2 = new Group();
+ group2.setName("Another Mock Group Name");
+
+ //emp 1 and 2 are in group1
+ employee.getGroups().add(group);
+ employee2.getGroups().add(group);
+
+ //emp 3 and 1 are in group2
+ employee3.getGroups().add(group2);
+ employee.getGroups().add(group2);
+
+ groupRepository.save(group);
+ groupRepository.save(group2);
+
+ Employee savedEmployee = employeeRepository.save(employee);
+ employeeRepository.save(employee2);
+ employeeRepository.save(employee3);
+
+ log.info("Employee: {} ",savedEmployee.getFirstName());
+ savedEmployee.getGroups().forEach(gr -> log.info("Groups Found: {} ",gr.getName()));
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithGroups() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getGroups().size()).isGreaterThan(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfGroups() {
+
+ List groups = groupRepository.findAll();
+
+ Assertions.assertThat(groups.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.setFirstName("Anton");
+ employee.getGroups().forEach(emp -> emp.setName("Group updated"));
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+ Assertions.assertThat(employeeUpdated.getGroups().get(1).getName()).isEqualTo("Group updated");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete an employee who in the group
+ public void deleteEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if (optionalEmployee.isPresent()) {
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can not delete the group with employees
+ //should remove employees from group then can delete group
+ public void removeEmployeesFromGroupThenDeleteGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+ Employee employee1 = employeeRepository.findById(53L).get();
+
+ Group group = groupRepository.findById(1L).get();
+
+ employee.getGroups().remove(group);
+ employee1.getGroups().remove(group);
+
+ groupRepository.delete(group);
+
+ Group group1 = null;
+
+ Optional optionalGroup = groupRepository.findById(1L);
+
+ if (optionalGroup.isPresent()) {
+ group1 = optionalGroup.get();
+ }
+
+ Assertions.assertThat(group1).isNull();
+
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/Employee.java
new file mode 100644
index 0000000..e1a757b
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/Employee.java
@@ -0,0 +1,59 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @OneToMany(mappedBy = "employee")
+ private Set registrations = new HashSet<>();
+
+ public void addRegistration(GroupRegistration groupRegistration) {
+ registrations.add(groupRegistration);
+ groupRegistration.setEmployee(this);
+ }
+
+ public void removeRegistration(GroupRegistration groupRegistration) {
+ registrations.remove(groupRegistration);
+ groupRegistration.setEmployee(null);
+ }
+
+ @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;
+ Employee other = (Employee) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/EmployeeRepository.java
new file mode 100644
index 0000000..c65092f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/Group.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/Group.java
new file mode 100644
index 0000000..08fd0f9
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/Group.java
@@ -0,0 +1,58 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Data
+@Table(name="\"group\"") //group is a reserved word in sql
+public class Group {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String name;
+
+ @OneToMany(mappedBy = "group")
+ private Set registrations = new HashSet<>();
+
+ public void addRegistration(GroupRegistration groupRegistration) {
+ registrations.add(groupRegistration);
+ groupRegistration.setGroup(this);
+ }
+
+ public void removeRegistration(GroupRegistration groupRegistration) {
+ registrations.remove(groupRegistration);
+ groupRegistration.setGroup(null);
+ }
+
+ @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;
+ Group other = (Group) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRegistration.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRegistration.java
new file mode 100644
index 0000000..f4b77e2
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRegistration.java
@@ -0,0 +1,53 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Data
+public class GroupRegistration {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name = "employee_id")
+ private Employee employee;
+
+ @ManyToOne
+ @JoinColumn(name = "group_id")
+ private Group group;
+
+ private LocalDateTime registeredAt;
+
+ @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;
+ GroupRegistration other = (GroupRegistration) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRegistrationRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRegistrationRepository.java
new file mode 100644
index 0000000..f5175ac
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRegistrationRepository.java
@@ -0,0 +1,10 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface GroupRegistrationRepository extends JpaRepository {
+
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRepository.java
new file mode 100644
index 0000000..3882e7d
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/GroupRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface GroupRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/TestJpaManyToManyDemo04.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/TestJpaManyToManyDemo04.java
new file mode 100644
index 0000000..eba9594
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo04/withNewEntity/TestJpaManyToManyDemo04.java
@@ -0,0 +1,228 @@
+package com.knits.jpa.orm.d03.many.to.many.demo04.withNewEntity;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d03.many.to.many.demo04.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d03.many.to.many.demo04.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-03-03"
+})
+@Slf4j
+//help to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaManyToManyDemo04 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private GroupRepository groupRepository;
+
+ @Autowired
+ private GroupRegistrationRepository groupRegistrationRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase(){
+
+ Employee employee= new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ Employee employee3 = new Employee();
+ employee3.setFirstName("Maria");
+ employee3.setLastName("Bertolucci");
+
+ Group group = new Group();
+ group.setName("A Mock Group Name");
+
+ Group group2 = new Group();
+ group2.setName("Another Mock Group Name");
+
+ //create registration object
+ GroupRegistration groupRegistration = new GroupRegistration();
+ groupRegistration.setRegisteredAt(LocalDateTime.now());
+
+ GroupRegistration groupRegistration2 = new GroupRegistration();
+ groupRegistration2.setRegisteredAt(LocalDateTime.now());
+
+ GroupRegistration groupRegistration3 = new GroupRegistration();
+ groupRegistration3.setRegisteredAt(LocalDateTime.now());
+
+ GroupRegistration groupRegistration4 = new GroupRegistration();
+ groupRegistration4.setRegisteredAt(LocalDateTime.now());
+
+ //Use helper methods (add and set)
+ employee.addRegistration(groupRegistration);
+ employee.addRegistration(groupRegistration2);
+ employee2.addRegistration(groupRegistration3);
+ employee3.addRegistration(groupRegistration4);
+
+ group.addRegistration(groupRegistration);
+ group2.addRegistration(groupRegistration2);
+ group.addRegistration(groupRegistration3);
+ group2.addRegistration(groupRegistration4);
+
+ //save two groups
+ groupRepository.save(group);
+ groupRepository.save(group2);
+
+ //save three employees
+ employeeRepository.save(employee);
+ Employee savedEmployee = employeeRepository.save(employee2);
+ employeeRepository.save(employee3);
+
+ //save 4 registrations
+ groupRegistrationRepository.save(groupRegistration);
+ groupRegistrationRepository.save(groupRegistration2);
+ groupRegistrationRepository.save(groupRegistration3);
+ groupRegistrationRepository.save(groupRegistration4);
+
+
+ log.info("Employee: {} ",savedEmployee.getFirstName());
+ savedEmployee.getRegistrations().forEach(reg -> log.info("Registered in group: {} ",reg.getGroup().getName()));
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getGroupRegistration() {
+
+ GroupRegistration groupRegistration = groupRegistrationRepository.findById(102L).get();
+
+ Assertions.assertThat(groupRegistration.getId()).isEqualTo(102L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getGroup() {
+
+ Group group = groupRepository.findById(1L).get();
+
+ Assertions.assertThat(group.getId()).isEqualTo(1L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getId()).isEqualTo(52L);
+ }
+
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithRegistrations() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getRegistrations().size()).isGreaterThan(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfGroups() {
+
+ List groups = groupRepository.findAll();
+
+ Assertions.assertThat(groups.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployeeAndGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.setFirstName("Anton");
+ employee.getRegistrations().forEach(groupRegistration -> groupRegistration.getGroup().setName("SuperGroup"));
+
+ Employee employeeUpdated = employeeRepository.save(employee);
+ Group groupUpdated = groupRepository.findById(1L).get();
+
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+ Assertions.assertThat(groupUpdated.getName()).isEqualTo("SuperGroup");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can not delete an employee who in the reg_group
+ //should to delete employee registrations then delete employee
+ public void deleteEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ GroupRegistration groupRegistration = groupRegistrationRepository.findById(102L).get();
+ GroupRegistration groupRegistration2 = groupRegistrationRepository.findById(103L).get();
+
+ groupRegistrationRepository.delete(groupRegistration);
+ groupRegistrationRepository.delete(groupRegistration2);
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if (optionalEmployee.isPresent()) {
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can not delete a group if its in the reg_group
+ //should to delete group registrations then delete group
+ public void deleteGroup() {
+
+ Group group = groupRepository.findById(1L).get();
+
+ GroupRegistration groupRegistration = groupRegistrationRepository.findById(102L).get();
+ GroupRegistration groupRegistration2 = groupRegistrationRepository.findById(104L).get();
+
+ groupRegistrationRepository.delete(groupRegistration);
+ groupRegistrationRepository.delete(groupRegistration2);
+
+ groupRepository.delete(group);
+
+ Group group1 = null;
+
+ Optional optionalGroup = groupRepository.findById(1L);
+
+ if (optionalGroup.isPresent()) {
+ group1 = optionalGroup.get();
+ }
+
+ Assertions.assertThat(group1).isNull();
+ }
+
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/Employee.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/Employee.java
new file mode 100644
index 0000000..6aa4d60
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/Employee.java
@@ -0,0 +1,74 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @OneToMany(
+ mappedBy = "employee",
+ cascade = CascadeType.ALL,
+ orphanRemoval = true
+ )
+ private List groups = new ArrayList<>();
+
+ public Employee() {
+ }
+
+ public Employee(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public void addGroup(Group group) {
+ EmployeeGroup employeeGroup = new EmployeeGroup(this, group);
+ groups.add(employeeGroup);
+ group.getEmployees().add(employeeGroup);
+ }
+
+ public void removeGroup(Group group) {
+ for (Iterator iterator = groups.iterator();
+ iterator.hasNext(); ) {
+ EmployeeGroup employeeGroup = iterator.next();
+
+ if (employeeGroup.getEmployee().equals(this) &&
+ employeeGroup.getGroup().equals(group)) {
+ iterator.remove();
+ employeeGroup.getGroup().getEmployees().remove(employeeGroup);
+ employeeGroup.setEmployee(null);
+ employeeGroup.setGroup(null);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ Employee employee = (Employee) o;
+ return Objects.equals(lastName, employee.lastName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(lastName);
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroup.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroup.java
new file mode 100644
index 0000000..120aa7b
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroup.java
@@ -0,0 +1,58 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.Date;
+import java.util.Objects;
+
+@Entity(name = "EmployeeGroup")
+@Table(name = "employee_group")
+@Data
+public class EmployeeGroup {
+
+ @EmbeddedId
+ private EmployeeGroupId id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @MapsId("employeeId")
+ private Employee employee;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @MapsId("groupId")
+ private Group group;
+
+ @Column(name = "created_on")
+ private Date createdOn = new Date();
+
+ private EmployeeGroup() {
+
+ }
+
+ public EmployeeGroup(Employee employee, Group group) {
+ this.employee = employee;
+ this.group = group;
+ this.id = new EmployeeGroupId(employee.getId(), group.getId());
+ }
+
+ public EmployeeGroupId getId() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ EmployeeGroup that = (EmployeeGroup) o;
+ return Objects.equals(employee, that.employee) &&
+ Objects.equals(group, that.group);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(employee, group);
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroupId.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroupId.java
new file mode 100644
index 0000000..d1d2f3f
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroupId.java
@@ -0,0 +1,47 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import lombok.Data;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import java.io.Serializable;
+import java.util.Objects;
+
+@Embeddable
+@Data
+/*You need the @Embeddable type to be Serializable
+The @Embeddable type must override the default equals and
+hashCode methods based on the two Primary Key identifier values.*/
+public class EmployeeGroupId implements Serializable {
+
+ @Column(name = "employee_id")
+ private Long employeeId;
+
+ @Column(name = "group_id")
+ private Long groupId;
+
+ private EmployeeGroupId() {}
+
+ public EmployeeGroupId(Long employeeId, Long groupId) {
+ this.employeeId = employeeId;
+ this.groupId = groupId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ EmployeeGroupId that = (EmployeeGroupId) o;
+ return Objects.equals(employeeId, that.employeeId) &&
+ Objects.equals(groupId, that.groupId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(employeeId, groupId);
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroupRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroupRepository.java
new file mode 100644
index 0000000..ea265f1
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeGroupRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeGroupRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeRepository.java
new file mode 100644
index 0000000..22567b5
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/EmployeeRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/Group.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/Group.java
new file mode 100644
index 0000000..b0927e3
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/Group.java
@@ -0,0 +1,58 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import lombok.Data;
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.annotations.NaturalId;
+import org.hibernate.annotations.NaturalIdCache;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@Entity
+@Data
+@Table(name="\"group\"") //group is a reserved word in sql
+@NaturalIdCache
+@Cache(
+ usage = CacheConcurrencyStrategy.READ_WRITE
+)
+public class Group {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
+ @SequenceGenerator(name = "sequenceGenerator")
+ private Long id;
+
+ @NaturalId
+ //business key, can not update if NaturalId
+ private String name;
+
+ @OneToMany(
+ mappedBy = "group",
+ cascade = CascadeType.ALL,
+ orphanRemoval = true
+ )
+ private List employees = new ArrayList<>();
+
+ public Group() {
+ }
+
+ public Group(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Group group = (Group) o;
+ return Objects.equals(name, group.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/GroupRepository.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/GroupRepository.java
new file mode 100644
index 0000000..1445d2b
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/GroupRepository.java
@@ -0,0 +1,8 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface GroupRepository extends JpaRepository {
+}
diff --git a/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/TestJpaManyToManyDemo05.java b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/TestJpaManyToManyDemo05.java
new file mode 100644
index 0000000..274cf7a
--- /dev/null
+++ b/S300-SBoot-JPA-ORM/src/test/java/com/knits/jpa/orm/d03/many/to/many/demo05/bestPractice/TestJpaManyToManyDemo05.java
@@ -0,0 +1,219 @@
+package com.knits.jpa.orm.d03.many.to.many.demo05.bestPractice;
+
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.TestPropertySource;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@DataJpaTest
+@EntityScan("com.knits.jpa.orm.d03.many.to.many.demo05.*")
+@EnableJpaRepositories("com.knits.jpa.orm.d03.many.to.many.demo05.*")
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@TestPropertySource(properties = {
+ "spring.jpa.hibernate.ddl-auto=create",
+ "spring.datasource.url=jdbc:postgresql://localhost:5432/JPA-ORM-03-04"
+})
+@Slf4j
+//help to clean and fill the DB before each test
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+public class TestJpaManyToManyDemo05 {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private GroupRepository groupRepository;
+
+ @Autowired
+ private EmployeeGroupRepository employeeGroupRepository;
+
+ @BeforeEach
+ @Rollback(value = false)
+ public void initDatabase() {
+
+ Employee employee = new Employee();
+ employee.setFirstName("Stefano");
+ employee.setLastName("Fiorenza");
+
+ Employee employee2 = new Employee();
+ employee2.setFirstName("Luna");
+ employee2.setLastName("Doria");
+
+ Employee employee3 = new Employee();
+ employee3.setFirstName("Maria");
+ employee3.setLastName("Bertolucci");
+
+ Group group = new Group();
+ group.setName("A Mock Group Name");
+
+ Group group2 = new Group();
+ group2.setName("Another Mock Group Name");
+
+ //save two groups
+ groupRepository.save(group);
+ groupRepository.save(group2);
+
+ //save employee
+ employeeRepository.save(employee);
+ Employee savedEmployee = employeeRepository.save(employee2);
+ employeeRepository.save(employee3);
+
+ employee.addGroup(group);
+ employee.addGroup(group2);
+ employee2.addGroup(group);
+ employee3.addGroup(group2);
+
+ log.info("Employee: {} ", savedEmployee.getFirstName());
+ savedEmployee.getGroups().forEach(reg -> log.info("Registered in group: {} ", reg.getGroup().getName()));
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getId()).isEqualTo(52L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getGroup() {
+
+ Group group = groupRepository.findById(1L).get();
+
+ Assertions.assertThat(group.getId()).isEqualTo(1L);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getEmployeeWithGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getGroups().size()).isGreaterThan(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void getListOfGroups() {
+
+ List groups = groupRepository.findAll();
+
+ Assertions.assertThat(groups.size()).isGreaterThan(0);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void addEmployeeIntoGroup() {
+
+ Employee employee = employeeRepository.findById(53L).get();
+ Group group = groupRepository.findById(2L).get();
+ employee.addGroup(group);
+
+ Assertions.assertThat(employee.getGroups().get(1).getGroup().getId()).isEqualTo(2L);
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void updateEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ employee.setFirstName("Anton");
+ employee.setLastName("Mezhenin");
+
+ Employee employeeUpdated = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employeeUpdated.getFirstName()).isEqualTo("Anton");
+ Assertions.assertThat(employeeUpdated.getLastName()).isEqualTo("Mezhenin");
+
+ }
+
+ @Test
+ @Rollback(value = false)
+ public void removeEmployeeFromGroup() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Group group = groupRepository.findById(1L).get();
+ Group group1 = groupRepository.findById(2L).get();
+
+ employee.removeGroup(group);
+ employee.removeGroup(group1);
+
+ Employee employee1 = employeeRepository.findById(52L).get();
+
+ Assertions.assertThat(employee.getGroups().size()).isEqualTo(0);
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete employee if employee without groups
+ public void deleteEmployee() {
+
+ Employee employee = employeeRepository.findById(52L).get();
+
+ Group group = groupRepository.findById(1L).get();
+ Group group1 = groupRepository.findById(2L).get();
+
+ employee.removeGroup(group);
+ employee.removeGroup(group1);
+
+ employeeRepository.delete(employee);
+
+ Employee employee1 = null;
+
+ Optional optionalEmployee = employeeRepository.findById(52L);
+
+ if (optionalEmployee.isPresent()) {
+ employee1 = optionalEmployee.get();
+ }
+
+ Assertions.assertThat(employee1).isNull();
+ }
+
+ @Test
+ @Rollback(value = false)
+ //can delete group if it is empty
+ public void deleteGroup() {
+
+ Group group = groupRepository.findById(1L).get();
+
+ Employee employee = employeeRepository.findById(53L).get();
+ Employee employee2 = employeeRepository.findById(52L).get();
+
+ employee.removeGroup(group);
+ employee2.removeGroup(group);
+
+ groupRepository.delete(group);
+
+ Group group1 = null;
+
+ Optional optionalGroup = groupRepository.findById(1L);
+
+ if (optionalGroup.isPresent()) {
+ group1 = optionalGroup.get();
+ }
+
+ Assertions.assertThat(group1).isNull();
+
+ }
+
+
+}