Commit 219e73bfb97f36839fffb4d7d27cb702580b006f

Authored by Benjamin Rühl
1 parent 5a37cec9

Rework persistence docs

Showing 1 changed file with 18 additions and 26 deletions
docu/persistence.md
@@ -2,24 +2,23 @@ @@ -2,24 +2,23 @@
2 2
3 ## Which technologies are used in the persistence layer? 3 ## Which technologies are used in the persistence layer?
4 4
5 -- a **PostgreSQL** database is running as a seperate docker container 5 +- A **PostgreSQL** database is running as a seperate docker container
6 - **Adminer** is used as a web client for inspection and manipulation of the database; it is running in its own docker container 6 - **Adminer** is used as a web client for inspection and manipulation of the database; it is running in its own docker container
7 -- to enable the communication between java and the database, a database driver is required which is the **postgres jdbc driver** in our case 7 +- To enable the communication between java and the database, a database driver is required which is the **postgres JDBC driver** in our case
8 - **JPA** is the specification which is used as interface for every interaction with the database using java 8 - **JPA** is the specification which is used as interface for every interaction with the database using java
9 - **Hibernate** implements JPA and is used as the persistence provider which does the actual object-relational mapping 9 - **Hibernate** implements JPA and is used as the persistence provider which does the actual object-relational mapping
10 10
11 ## Where can the configuration files be found? 11 ## Where can the configuration files be found?
12 12
13 -- the jdbc driver can be found in `/docker/postgres/volumes`  
14 -- the connection between the JBoss server and the database is configured as a subsystem in `/docker/wildfly/standalone.xml`  
15 -- the configuration of Hibernate is located in `common/resources/META-INF/persistence.xml` 13 +- The JDBC driver can be found in [/docker/wildfly/volumes/modules/org/postgres/main](../docker/wildfly/volumes/modules/org/postgres/main/)
  14 +- The connection between the JBoss server and the database is configured as a subsystem in the [standalone.xml](../docker/wildfly/standalone.xml) file
  15 +- The configuration of Hibernate is located in the [persistence.xml](services/Common/src/main/resources/META-INF/persistence.xml) file
16 16
17 ## How to interact with persisted entities? 17 ## How to interact with persisted entities?
18 18
19 -- Data Access Objects (DAOs) are designed as an encapsulation of JPA / Hibernate  
20 - - DAO interfaces provide CRUD functionality  
21 - - DAO implementations use JPA to perform operations on the database  
22 -- The following snippet shows tha base interface for all DAOs: 19 +Data Access Objects (DAOs) are designed as an encapsulation of JPA and Hibernate and should be used to create,retrieve, modify and delete entities. DAO interfaces provide at least CRUD functionality and DAO implementations use JPA to perform the necessary operations on the database.
  20 +
  21 +The following snippet shows the base interface for all DAOs:
23 22
24 ```java 23 ```java
25 public interface GenericDAO<T extends Entity, ID extends Serializable> { 24 public interface GenericDAO<T extends Entity, ID extends Serializable> {
@@ -34,7 +33,7 @@ public interface GenericDAO&lt;T extends Entity, ID extends Serializable&gt; { @@ -34,7 +33,7 @@ public interface GenericDAO&lt;T extends Entity, ID extends Serializable&gt; {
34 } 33 }
35 ``` 34 ```
36 35
37 -- The following snippet shows a DAO interface for a specific entity having the basic CRUD functionality and optional extensions to that 36 +The following snippet shows a DAO interface for a specific entity having the basic CRUD functionality and optional extensions to that
38 37
39 ```java 38 ```java
40 public interface AppUserDAO extends GenericDAO<AppUser, Long> { 39 public interface AppUserDAO extends GenericDAO<AppUser, Long> {
@@ -44,7 +43,7 @@ public interface AppUserDAO extends GenericDAO&lt;AppUser, Long&gt; { @@ -44,7 +43,7 @@ public interface AppUserDAO extends GenericDAO&lt;AppUser, Long&gt; {
44 43
45 ## How can a DAO instance be used? 44 ## How can a DAO instance be used?
46 45
47 -- using dependency injection in a class that is managed by JBoss 46 +DAO implementations are stateless EJBs which can be used using dependency injection in a class that is managed by JBoss.
48 47
49 ```java 48 ```java
50 @Resource(lookup = "java:global/global/AppUserDAO") 49 @Resource(lookup = "java:global/global/AppUserDAO")
@@ -53,9 +52,7 @@ private AppUserDAO userDAO; @@ -53,9 +52,7 @@ private AppUserDAO userDAO;
53 52
54 ## How to create an entity? 53 ## How to create an entity?
55 54
56 -- currently a DAO is responsible for creating instances of its context entity, e.g. `AppUser newUser = userDAO.createUser()`  
57 -- direct creation of an entity like `AppUser newUser = new AppUser()` were not possible at first, but could be used now, too  
58 -- When the persistence layer was designed, direct references to the entity classes were impossible to use, because those classes were placed in the `global` module. This location changed to `common` because this solved some issues that could no be fixed otherwise, although this solution is less clean. 55 +Currently a DAO is responsible for creating instances of its context entity, e.g. `AppUser newUser = userDAO.createUser()`. Direct creation of an entity like `AppUser newUser = new AppUser()` was not possible at first, but could be used now, too. When the persistence layer was designed, direct references to the entity classes were impossible to use, because those classes were placed in the `global` module. This location changed to `common` because this solved some issues that could no be fixed otherwise, although this solution is less clean (see [Why is the persistence layer located in `common` instead of `global`?](#Why-is-the-persistence-layer-located-in-`common`-instead-of-`global`?)).
59 56
60 ```java 57 ```java
61 public interface AppUserDAO extends GenericDAO<AppUser, Long> { 58 public interface AppUserDAO extends GenericDAO<AppUser, Long> {
@@ -64,15 +61,11 @@ public interface AppUserDAO extends GenericDAO&lt;AppUser, Long&gt; { @@ -64,15 +61,11 @@ public interface AppUserDAO extends GenericDAO&lt;AppUser, Long&gt; {
64 } 61 }
65 ``` 62 ```
66 63
67 -- the entity can then be modified and updated in the database using the DAO instance 64 +The entity can then be modified and updated in the database using the DAO instance.
68 65
69 ## AppUsers have generic attributes. How can they be used? 66 ## AppUsers have generic attributes. How can they be used?
70 67
71 -- the **Entity-Attribute-Value model (EAV)** is a common pattern in relational database design which aims at structuring a database schema in rows instead of columns; please do some research to really understand it  
72 -- the pattern is implemented and used in the `AppUser` entity to give developers the ability to define attributes at runtime  
73 -- the advantage here is that attributes can be created and retrieved in `Drools` without changing the actual entity class  
74 -- the disadvantage is that a developer cannot rely on an attribute being present and having the expected data type  
75 -- the following snippet is a usage expample of the implemented pattern 68 +The **Entity-Attribute-Value model (EAV)** is a common pattern in relational database design which aims at structuring a database schema in rows instead of columns. Please do some research if you want to really understand it. The pattern is implemented and used in the `AppUser` entity to give developers the ability to define attributes at runtime. The advantage here is that attributes can be created and retrieved in `Drools` without changing the actual entity class. The disadvantage is that a developer cannot rely on an attribute being present and having the expected data type. The following snippet is a usage expample of the implemented pattern.
76 69
77 ```java 70 ```java
78 AppUser u = userDAO.createUser(); 71 AppUser u = userDAO.createUser();
@@ -84,18 +77,17 @@ u.setProperty(&quot;test_property_double&quot;, 3.65); @@ -84,18 +77,17 @@ u.setProperty(&quot;test_property_double&quot;, 3.65);
84 userDAO.saveOrUpdate(u); 77 userDAO.saveOrUpdate(u);
85 ``` 78 ```
86 79
87 -- the shown syntax is achieved using custom json serialization as a convenience method  
88 -- instead of this, the EAV structure can be build manually, too  
89 -- please note that complex data types and lists are not supported using this syntax at the moment; to add support, the custom serializers and deserializers found in `common/persistence` must be extended 80 +The shown syntax is achieved using custom json serialization as a convenience method. Instead of this, the EAV structure can be build manually, too. Please note that complex data types and lists are not supported using this syntax at the moment. To add support, the custom serializers and deserializers found in [services/Common/.../persistence](services/Common/src/main/java/de/bht/beuthbot/persistence) must be extended.
90 81
91 -## How does the implementation of the EAV pattern work internally for the AppUser entity? 82 +## How does the implementation of the EAV pattern look like?
92 83
93 ![Domain model as UML class diagram](img/persistence/domain-model.png) 84 ![Domain model as UML class diagram](img/persistence/domain-model.png)
94 85
  86 +The important part here is that the `GenericEntity` can contain a recursive structure similar to the `composite` design pattern. This way primitive types are supported as well as lists and complex data types.
  87 +
95 ## How to retrieve the generic attributes of an AppUser? 88 ## How to retrieve the generic attributes of an AppUser?
96 89
97 -- the following snippet shows the retrieval using the convenience method  
98 -- instead of this, the EAV structure can be queried an walked manually, too 90 +The following snippet shows the retrieval using the convenience method. Instead of this, the EAV structure can be queried an walked manually, too.
99 91
100 ```java 92 ```java
101 AppUser u = userDAO.findById(1); 93 AppUser u = userDAO.findById(1);