Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
1
Session: Pattern of the E...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
2
Objectives
Learn about:
✔...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
3
Some orientation
Consumer...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
4
ECB Pattern
Entity Contro...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
5
Services, components and ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
6
Module
Good ol' DAO &
Dom...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
7
Do you remember ...
Long,...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
8
Implementing a DAO
For im...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
9
Data Access Object (DAO)
...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
10
Domain Store
Purpose:
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
11
Domain Store
UML class d...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
12
Why bothering?
The archi...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
13
Lab
Implement DataAccess...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
14
Module
The Generic DAO
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
15
GenericDAO
✔ The EntityM...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
16
GenericDAO
UML Diagram
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
17
A common superclass
Migh...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
18
The GenericDAO class
Jus...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
19
Using Generics
… to pers...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
20
Using Generics
✔ … find ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
21
Using Generics
✔ … to de...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
22
Using Generics
✔ … to in...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
23
Lab
Implement GenericDAO...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
24
Module
The Domain-Specif...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
25
Domain-specific DAO
✔ A ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
26
Example
✔ Presumed, you ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
27
What about this?
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
28
Lab
Implement Domain-spe...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
29
Module
TransferObject &
...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
30
The Problem
✔ On can say...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
31
JPA POJOs might be the b...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
32
And now?
✔ Don't design ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
33
DTOs: SELECT NEW
✔ JPA a...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
34
DTO's: SELECT NEW
✔ The ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
35
Table View
According to ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
36
Table View
Sample view:
...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
37
Using the view
✔ … just ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
38
Table View
✔ Although se...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
39
DTOs: Builder Pattern
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
40
DTOs: Builder Pattern
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
41
DTOs: Builder Pattern
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
42
DTOs: Builder Pattern
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
43
DTOs: Apache BeanUtils /...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
44
Lab
Implement DTO using ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
45
Module
Large amounts of ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
46
Dealing with large amoun...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
47
The simplest case
✔ The ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
48
Lab
Implement Value List...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
49
Module
A key does the tr...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
50
Ids and keys
✔ Primary K...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
51
Business keys
✔ So we ca...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
52
Utilizing JPA
✔ Take int...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
53
The finder method
✔ To b...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
54
Strong references?
✔ Ref...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
55
Foreign key relationship...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
56
Foreign key relationship...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
57
„Soft“ relationships bas...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
58
„Soft“ relationships bas...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
59
Advantages/Disadvantages...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
60
Lab
Implement Business K...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
61
Module
Adding some data
...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
62
Why?
✔ Sometimes there m...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
63
Let's take a walk
@Eleme...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
64
Let's take a walk
@Embed...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
65
Let's take a walk
@Embed...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
66
Let's take a walk
Collec...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
67
Let's take a walk
Queryi...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
68
But what if ...
✔ Some s...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
69
But what if ...
The desc...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
70
But what if ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
71
But what if ...
✔ Exampl...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
72
Presentation
Dynamic dat...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
73
Module
Tips and tricks
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
74
Not patterns
✔ … just hi...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
75
Names of NamedQueries
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
76
Names of NamedQueries
✔ ...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
77
hashCode and equals
✔ No...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
78
hashCode and equals
Usin...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
79
hashCode and equals
✔ Ov...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
80
hashCode and equals
✔ Fo...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
81
SerialVersionUID
… for P...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
82
Key generation
✔ JPA sup...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
83
Generating keys
Automati...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
84
Generating keys
Generati...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
85
Generating keys
Generati...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
86
Generating keys
Generati...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
87
Wrappers for numbers
✔ I...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
88
Lab
Implement some hints...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
89
Review
Session Review:
✔...
Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt
90
Recommeded reading
✔ htt...
Nächste SlideShare
Wird geladen in …5
×
Nächste SlideShare
PGDAIT presentation v11
Weiter
Herunterladen, um offline zu lesen und im Vollbildmodus anzuzeigen.

4

Teilen

Herunterladen, um offline zu lesen

Java EE Pattern: The Entity Layer

Herunterladen, um offline zu lesen

Pattern of the Entity Layer, thx to the inspiring Book from Adam Bien, part of the lectures held at Duale Hochschule Mannheim

Ähnliche Bücher

Kostenlos mit einer 30-tägigen Testversion von Scribd

Alle anzeigen

Ähnliche Hörbücher

Kostenlos mit einer 30-tägigen Testversion von Scribd

Alle anzeigen

Java EE Pattern: The Entity Layer

  1. 1. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 1 Session: Pattern of the Entity Layer Good ol' DAO & DomainStore The GenericDAO TransferObject and DataTransferObject Large amounts of data A key does the trick Adding some data dynamically Tips & Tricks
  2. 2. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 2 Objectives Learn about: ✔ Get an idea about the challenges at the entity layer ✔ Learn how to access data in a performant manner ✔ Learn how to deal with large chunks of data
  3. 3. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 3 Some orientation Consumer Consumer Layer Integration Layer Business Process Layer Services Layer Component Layer OS Layer
  4. 4. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 4 ECB Pattern Entity Control Boundary ✔ Based upon Robustness Diagrams (http://www.agilemodeling.com/artifacts/robustnessDiagram.htm) ➢ Boundary: user interface ➢ Control: actual process or activity ➢ Entity: a concept from an enterprise context. ✔ Elements are generic enough to be mapped either to service- oriented or object-oriented architectures. Boundary Control Entity Adam Bien
  5. 5. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 5 Services, components and patterns Boundary Control Entity DAO & Domain Store Generic DAO Singleton Service Starter Dual View SOA Facade Lightweight asynchronous Facade Multichannel Facade TO & DTO Paginator Bean Locator Multichannel Facade Resource Binder Payload Extractor Aynchronous Resource Integrator Infrastructure
  6. 6. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 6 Module Good ol' DAO & Domain Store
  7. 7. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 7 Do you remember ... Long, long time ago:
  8. 8. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 8 Implementing a DAO For implementing a DAO, we have to implement the following steps. ✔ An interface which defines methods for various operations related to the domain object (here: User). ✔ Concrete classes which implement DAO interface (here: H2UserDAO) ✔ Factory/Abstract Factory class to get a reference to DAO object (here: DAOFactory) ✔ A DataSource to establish a connection
  9. 9. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 9 Data Access Object (DAO) Is DAO still needed? ✔ Adam Bien quoted: ➢ DAO pattern is actually no more interesting for general data access. ➢ JPA comes already with the EntityManager which provides already generic data access functionality. The usage cannot be simpler. ✔ Anyhow, data access is crucial, therefore there still might be some place to use it … ✔ After some discussion: I would say: it depends. It depends how complex your application really is. – Adam Bien: http://www.infoq.com/news/2007/09/jpa-dao
  10. 10. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 10 Domain Store Purpose: ✔ Pattern mainly used prior to EJB 3.0 / JPA ✔ Avoid putting persistence details in your Business Objects. ✔ Not want to use entity beans ✔ Application might be running in a web container. ✔ Object model uses inheritance and complex relationships.
  11. 11. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 11 Domain Store UML class diagram
  12. 12. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 12 Why bothering? The architecture as we know it right now has some disadvantages: ✔ Boilerplate code as you have to have DAOs for each and every domain class / persistent entity ✔ So the MDA people might wrote generators for CRUD methods (but this is proprietary and only few people might know how to maintain and enhance it) ✔ Maybe you want to take advantage of a few principles of OO like delegation and inheritance
  13. 13. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 13 Lab Implement DataAccessObject (not more than 15 min.)
  14. 14. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 14 Module The Generic DAO
  15. 15. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 15 GenericDAO ✔ The EntityManager already is an implementation of the DAO Pattern ✔ Dedicated DAOs are exception to the rule as the EntityManager can be injected into the SLSBs / SFSBs => still a lot of boilerplate code in the dedicated services (createX, createY, findByA, findByB) ✔ For many services plain CRUD methods plus sophisticated finder methods might do
  16. 16. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 16 GenericDAO UML Diagram
  17. 17. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 17 A common superclass Might be helpful ... @MappedSuperclass public abstract class BaseEntity implements Serializable { @Version private long version; @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Temporal(TemporalType.DATE) private Date creationDate; public BaseEntity() { //lazy } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public long getId() { return id; } }
  18. 18. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 18 The GenericDAO class Just a SLSB ... @Stateless(mappedName = "ejb/facade/GenericDAOService") @Remote(GenericDAO.class) public class GenericDAOBean implements GenericDAO { private static final Logger log = LoggerFactory.getLogger(GenericDAOBean.class); @PersistenceContext private EntityManager em; … // create, read, update and delete will follow
  19. 19. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 19 Using Generics … to persist or update an instance public <T extends BaseEntity> T createOrUpdateEntity(T entity) { // as we have no id yet, it must be freshly brewed if (entity.getId() == 0) { log.debug("createOrUpdateEntity::create:: {}", entity); this.em.persist(entity); } // if there is an id, we must have dealt with it before else { log.debug("createOrUpdateEntity::update:: {}", entity); this.em.merge(entity); } this.em.flush(); return entity; }
  20. 20. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 20 Using Generics ✔ … find an instance by key public <T extends BaseEntity> T findEntityById(Class<T> clazz, long id) { log.debug("findEntityById:: class= {}, id= {}", clazz, id); return this.em.find(clazz, id); }
  21. 21. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 21 Using Generics ✔ … to delete an instance public void deleteEntity(BaseEntity entity) { log.debug("deleteEntity:: {}", entity); // updating it first ... entity = (BaseEntity) this.em.merge(entity); // ... then killing it this.em.remove(entity); }
  22. 22. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 22 Using Generics ✔ … to invoke a (named) query dynamically public <T extends BaseEntity> List<T> findByNamedQuery(Class<T> clazz, String queryName, String[] paramNames, Object[] values) { TypedQuery<T> query = this.em.createNamedQuery(queryName, clazz); if (paramNames != null) { for (int i = 0; i < paramNames.length; i++) { query.setParameter(paramNames[i], values[i]); } } List<T> result = query.getResultList(); log.debug("findByNamedQuery:: result={}", result); return (List<T>) result; }
  23. 23. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 23 Lab Implement GenericDAO (not more than 15 min.)
  24. 24. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 24 Module The Domain-Specific DAO
  25. 25. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 25 Domain-specific DAO ✔ A type-safe DAO operating on a specific domain object ✔ Extends the GenericDAO with domain-specific extensions and additional functionality (e.g. specific queries with specific return types => Transfer Object) ✔ In practice, GenericDAO and Domain-specific DAO are used together
  26. 26. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 26 Example ✔ Presumed, you want to get some DataTransferObject, the domain- specific DAO is the only place you can implement it. ✔ Either you implement all other methods as well or … you think about some more sophisticated architecture. @Stateless(mappedName = "ejb/facade/UserManagementService") @Remote(UserManagementService.class) public class UserManagementServiceBean implements UserManagementService { @PersistenceContext private EntityManager em; public UserPersonDTO findUserPersonDTOByCredentials(String user, String pwd) { //public UserPersonDTO(long userId, long personId, String user, String firstname) String jpql = "SELECT NEW de.brockhaus.userMgmt.dto.UserPersonDTO( u.id, p.id, u.user, p.firstName, p.lastName) FROM User u, Person p WHERE u.user = :user AND u.password = :pwd)"; Query q = this.em.createQuery(jpql); q.setParameter("user", user); q.setParameter("pwd", pwd); return (UserPersonDTO) q.getSingleResult(); }
  27. 27. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 27 What about this?
  28. 28. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 28 Lab Implement Domain-specific DAO (not more than 15 min.)
  29. 29. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 29 Module TransferObject & DataTransferObject
  30. 30. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 30 The Problem ✔ On can say, the problem with EJB 2.1 is solved by detached entities of EJB 3.x, why to introduce an new class just to transfer data? ✔ Although Transfer Objects might provide a client- / consumer- specific view to the persistence layer and might keep the interfaces stable. ✔ In a SOA, exposing the domain layer directly to the consumer would make further extensions impossible; TO's can hide changes to some degree (for the price of an additional translation layer).
  31. 31. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 31 JPA POJOs might be the best choice when they play the role of DTOs. ✔ Loading: Web developers building on top of the EJB3 architecture tried to use objects that were not loaded eagerly, and then the middle layer developers have to to change the way data load was done. ✔ Performance: A business method using a set of POJOs had as an extra load the eagerly loaded POJOs, no matter if this business method needed them or not: if another business method was using one of the POJOs, then you have to load even if you don’t need it. This overhead can be irrelevant in unit testing, but it’s relevant in stressed systems. ✔ Robustness: Changes in the ER to OO mapping were propagated to the web layer, forcing the web development team to refactor their code to fix the problem.
  32. 32. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 32 And now? ✔ Don't design lasagna architectures (dozens of layers with only little beef) ✔ Decoupling is not a sufficient justification for using TOs (as they are in most cases just duplicates of the original) and therefore would violate the DRY principle. ✔ There are enough cases: ➢ Additional view to the domain model ➢ Abstracting von legacy data ➢ Enforcements of eager loading ✔ Store TOs in a dedicated subpackage
  33. 33. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 33 DTOs: SELECT NEW ✔ JPA allows to create objects on the fly using SELECT NEW ✔ The DTO itself (note the constructor) public class UserPersonDTO implements Serializable { private long userId; private long personId; private String user; private String firstname; private String lastname; public UserPersonDTO(long userId, long personId, String user, String firstname, String lastname) { ... Adam Bien has named this as detached DTO strategy
  34. 34. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 34 DTO's: SELECT NEW ✔ The SLSB: @Stateless(mappedName = "ejb/facade/UserManagementService") @Remote(UserManagementService.class) public class UserManagementServiceBean extends GenericServiceBean implements UserManagementService { @PersistenceContext private EntityManager em; private Logger log = LoggerFactory.getLogger(this.getClass()); public UserPersonDTO findUserPersoDTOByCredentials(String user, String pwd) { //public UserPersonDTO(long userId, long personId, String user, String firstname) String jpql = "SELECT NEW de.brockhaus.userMgmt.dto.UserPersonDTO(u.id, p.id, u.user, p.firstName, p.lastName) FROM User u, Person p WHERE u.user = :user AND u.password = :pwd)"; Query q = this.em.createQuery(jpql); q.setParameter("user", user); q.setParameter("pwd", pwd); return (UserPersonDTO) q.getSingleResult(); }
  35. 35. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 35 Table View According to Adam Bien: ✔ SQL Views can be considered either as best practice or an anti-pattern. It depends on the perspective. ✔ Sometimes, however, it is required to provide an efficient way to iterate over an excerpt or even a set of related entities, but return a different “view” to the client. This can be achieved by: ➢ fetching the entities with EntityManager and merging them together inside a Session Bean (a Service). This approach is neither fast, nor easy to maintain. Especially the merging and extraction of entity data is error-prone and can become quite complex. ➢ Another option is the execution of more complex native SQL- statements and mapping them into existing entities or TOs. ✔ For SQL queries there is no difference between views and tables, so you can easily map a JPA entity to a view transparently.
  36. 36. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 36 Table View Sample view: CREATE VIEW UserPersonDTO AS SELECT u.id, u.password, u.user, u.person_id, p.firstname, p.lastname FROM User u INNER JOIN PERSON p on u.person_id = p.id
  37. 37. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 37 Using the view ✔ … just like a normal entity @Entity @Table(name="USERPERSONDTO") public class UserPersonDTO implements Serializable { @Id @Column(name = "ID") private long userId; @Column(name="PERSON_ID") private long personId; private String user; private String firstname; private String lastname; ...
  38. 38. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 38 Table View ✔ Although seen in the light of handling large amount of data, creating a SQL view and mapping a DTO to it might be helpful in the field of DTO as well … ✔ Will be covered in detail later.
  39. 39. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 39 DTOs: Builder Pattern ✔ Abstract steps of construction of objects so that different implementations of these steps can construct different representations of objects. ✔ Separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations ✔ Joshua Bloch quoted: The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.
  40. 40. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 40 DTOs: Builder Pattern ✔ Outer class, private constructor: public class PersonUserDTO implements Serializable { private long userId; private long personId; private String user; private String firstname; private String lastname; /** * private constructor so no one can invoke * @param builder */ private PersonUserDTO(PersonUserDTOBuilder builder) { this.userId = builder.personId; this.userId = builder.userId; } }
  41. 41. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 41 DTOs: Builder Pattern ✔ Inner class /** * static inner builder class */ public static class PersonUserDTOBuilder{ private long userId; private long personId; private String user; private String firstname; private String lastname; public PersonUserDTO build(){ return new PersonUserDTO(this); } public PersonUserDTOBuilder userId(long userId){ this.userId = userId; return this; } public PersonUserDTOBuilder personId(long personId){ this.personId = personId; return this; } }
  42. 42. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 42 DTOs: Builder Pattern ✔ Building: PersonUserDTO dto = new PersonUserDTO.PersonUserDTOBuilder().personId(1).userId(1).build();
  43. 43. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 43 DTOs: Apache BeanUtils / Dozer ✔ … might be an alternative as well but are not within the scope of this training. ✔ You might check here: http://www.javaranch.com/journal/2003/07/TouringTheCommonsPart1.html
  44. 44. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 44 Lab Implement DTO using SELECT NEW (not more than 15 min.)
  45. 45. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 45 Module Large amounts of data
  46. 46. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 46 Dealing with large amounts of data When to use ✔ Displaying / iterating over a large amount of data ✔ Data can't be loaded at once at the client but has to be cached at the server
  47. 47. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 47 The simplest case ✔ The classical Value List Handler pattern is already implemented by JPA / the EntityManager. public <T extends BaseEntity> List<T> findAll(Class<T> clazz, int lowNo, int maxNo) { TypedQuery<? extends BaseEntity> query = (TypedQuery<? extends BaseEntity>) this.em.createQuery("FROM " + clazz.getSimpleName(), clazz); query.setFirstResult(lowNo); query.setMaxResults(maxNo); return (List<T>) query.getResultList(); }
  48. 48. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 48 Lab Implement Value List Handler using JPA 2.0 (not more than 15 min.)
  49. 49. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 49 Module A key does the trick
  50. 50. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 50 Ids and keys ✔ Primary Key: Uniquely identifies a row in a table => @Id annotation ✔ Surrogate Key: Primary key that has no relation to the data, usually generated => @GeneratedValue annotation ✔ Natural or Business Key: ➢ A key that combines a number of columns to uniquely define the rows of a database table. ➢ Composite keys are sometimes used because the choice of key relates in some way to the end-user business domain. Impact on hashCode() and equals()
  51. 51. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 51 Business keys ✔ So we can introduce a business key at the level of BaseEntity which: ➢ might be set to a value according to UUID pattern by default and might be set to any other business key ➢ needs to be unique: (@Column(unique = true)) ➢ introduce a generic method: findByKey(String key) /** the business key */ @Column(unique = true) private String key;
  52. 52. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 52 Utilizing JPA ✔ Take into consideration to implement a findByKey(String key) method at GenericDAO ✔ Take into consideration to set a default value according to UUID pattern: ➢ After generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%. ➢ The probability of one duplicate would be about 50% if every person on earth owns 600 million UUIDs. public BaseEntity() { this.key = UUID.randomUUID().toString(); this.creationDate = new Date(System.currentTimeMillis()); }
  53. 53. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 53 The finder method ✔ To be implemented at our GenericDAO LocalBean: public <T extends BaseEntity> T findEntityByKey(Class<T> clazz, String key) { TypedQuery<T> query = this.em.createQuery("FROM " + clazz.getSimpleName() + " AS c WHERE c.key = :key", clazz); query.setParameter("key", key); return query.getSingleResult(); }
  54. 54. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 54 Strong references? ✔ Referencing data across (functional) modules / systems Boundary Control Entity Boundary Control Entity
  55. 55. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 55 Foreign key relationships ✔ Using foreign keys using JPA: ID Key Name BAR_FK 1 One FooOne 1 2 Two FooTwo 1 3 Three FooThree 2 Foo ID Key Name BAR_FK 1 One FooOne 1 2 Two FooTwo 1 3 Three FooThree 2 Foo Bar ID Key Name 1 One BarOne 2 Two BarTwo 3 Three BarThree
  56. 56. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 56 Foreign key relationships Pretty inflexible as: ✔ You can't exchange one component for another (e.g. your Bar component vs. 3rd party Bar component / system) ✔ You can't import data easily as everything depends on the ID of Bar
  57. 57. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 57 „Soft“ relationships based on keys ✔ Providing an example, a vendor might reside at one component (e.g. SCM), products bought reside at another component (e.g. Product-Definition at ERP) ✔ Making use of @ElementCollection at „many“ side ✔ Just a normal String attribute at „one“ side
  58. 58. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 58 „Soft“ relationships based on keys ✔ References independant of business keys ID Key Name Vendor_KEY 1 One FooOne One 2 Two FooTwo One 3 Three FooThree Two Product Vendor ID Key Name 1 One AcmeOne 2 Two AcmeTwo 3 Three AcmeThree
  59. 59. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 59 Advantages/Disadvantages ✔ Pretty flexible ✔ No type safety within associations anymore ✔ Maybe some performance impact
  60. 60. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 60 Lab Implement Business Keys (not more than 15 min.)
  61. 61. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 61 Module Adding some data dynamically
  62. 62. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 62 Why? ✔ Sometimes there might be the need to enhance the datamodel at runtime (and not at compile- and deploy-time) ✔ JPA provides a lot of support, e.g. ➢ Generation of tables and constraints at deploy-time ➢ Dynamic data model due to @ElementCollection ➢ Embedded objects due to @Embeddable ➢ Criteria API for runtime queries ✔ Unfortunately sometimes even this isn't enough
  63. 63. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 63 Let's take a walk @ElementCollection ✔ Presumed a person has several email addresses: Unfortunately of just one data type @ElementCollection private List<String> emails; { emails = new ArrayList<String>(); }
  64. 64. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 64 Let's take a walk @Embedded ✔ Weapon of choice when designing compositions ✔ Embedded class will not have any primary key on it's own @Embeddable public class Address implements Serializable { private String city; private String country; private String street; private String zipCode; private String houseNo; public String getCity() { return city; } public void setCity(String city) { this.city = city; } ...
  65. 65. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 65 Let's take a walk @Embedded public class Person extends BaseEntity { ... @Embedded private Address address;
  66. 66. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 66 Let's take a walk Collection of embeddable objects ✔ Similar to a @OneToMany except the target objects are embeddables and have no Id. ✔ This allows for a @OneToMany to be defined without a inverse @ManyToOne, as the parent is responsible for storing the foreign key in the target object's table. ✔ JPA 2.0 does support collections of embeddable objects through the @ElementCollection mapping.
  67. 67. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 67 Let's take a walk Querying ✔ Embeddable objects cannot be queried directly, but they can be queried in the context of their parent. ✔ Typically it is best to select the parent, and access the embeddable from the parent. SELECT employee.period FROM Employee employee WHERE employee.period.endDate = :param
  68. 68. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 68 But what if ... ✔ Some sketch taken from ISA-95 specification for Manufacturing Execution Systems (I'm sure you can find similar in your domain)
  69. 69. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 69 But what if ... The description of these PersonProperties according to ISA-95 ✔ Several datatypes ✔ Ranges and lists of Values
  70. 70. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 70 But what if ...
  71. 71. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 71 But what if ... ✔ Example provided within the solutions ✔ This approach leads to records with lot's of null values in it ✔ Experimental!
  72. 72. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 72 Presentation Dynamic data model
  73. 73. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 73 Module Tips and tricks
  74. 74. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 74 Not patterns ✔ … just hints and best practices: ➢ Names of named queries ➢ Key generation ➢ Wrappers for numbers ➢ SerialVersionUID ➢ hashCode and equals
  75. 75. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 75 Names of NamedQueries ✔ Using a NamedQuery sometimes look like trial and error if you're not using a consistent naming strategy: ✔ ClassName.QueryName might be an option (but still you have to guess the name of the query) ✔ Using constants might be a better option @Entity @NamedQueries({ @NamedQuery(name = "User.findByCredentials", query = " FROM User AS u WHERE u.user = :user AND password = :pwd" ) } ) public class User extends BaseEntity { private static final long serialVersionUID = 4616273573516105734L; public static final String FIND_BY_CREDENTIALS = "User.findByCredentials";
  76. 76. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 76 Names of NamedQueries ✔ Invocation public User findUserByCredentials(String user, String pwd) { TypedQuery<User> q = this.em.createNamedQuery(User.FIND_BY_CREDENTIALS, User.class); q.setParameter("user", user); q.setParameter("pwd", pwd); return q.getSingleResult(); }
  77. 77. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 77 hashCode and equals ✔ Normally, most Java objects provide a built-in equals() and hashCode() based on the object's identity; so each new() object will be different from all others. ✔ But what in case of JPA: the id will be set once the object is persisted for the first time. ✔ What in the case, you put these objects to a map prior to saving it? ✔ To avoid this problem it is recommended using the "semi"-unique attributes of your persistent class to implement equals() and hashCode().
  78. 78. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 78 hashCode and equals Using Apache BeanUtils make things easier: ✔ Overwrite hashCode() in BaseEntity: @Override public int hashCode() { HashCodeBuilder hcb = new HashCodeBuilder(); hcb.append(this.key); return hcb.toHashCode(); }
  79. 79. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 79 hashCode and equals ✔ Overwrite equals() in Base Entity @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof BaseEntity)) { return false; } BaseEntity that = (BaseEntity) obj; EqualsBuilder eb = new EqualsBuilder(); eb.append(this.getKey(), that.getKey()); return eb.isEquals(); }
  80. 80. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 80 hashCode and equals ✔ For completeness overwrite toString() as well at BaseEntity: at subclass: @Override public String toString() { ToStringBuilder tsb = new ToStringBuilder(this); tsb.append("key", this.key); return tsb.toString(); } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); builder.appendSuper(super.toString()); builder.append(this.user); return builder.toString(); } de.brockhaus.userMgmt.entity.User@9a9b65[id=5,key=64d75dd7-3960-4e20-8279- 95f4a4e88eae,user=peterp]
  81. 81. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 81 SerialVersionUID … for Persistent Entities ✔ Not mandated by spec but recommended for every class implementing java.io.Serializable. ✔ From spec: If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID. ✔ Once you make use of it, change it everytime you change the class!
  82. 82. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 82 Key generation ✔ JPA supports several strategies, not all are the same (by meanings of portability): ➢ Table -the persistence provider must assign primary keys for the entity using an underlying database table to ensure uniqueness ➢ Sequence - specify the use of a database sequence to ensure uniqueness ➢ Identity - specify the use of a database identity column ➢ Auto - the persistence provider should pick an appropriate strategy for the particular database ✔ If it comes to portability (e.g. if you are about to develop a product running on several databases), Table seems to be the best option. ✔ If it comes to performance, Identity and sequence might be better.
  83. 83. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 83 Generating keys Automatic ID Generation: ✔ provider will use whatever strategy it wants to generate identifiers ✔ generation strategy for development or prototyping only ✔ getting you up'n' running more quickly when the database schema is generated ✔ Default strategy! @Id @GeneratedValue(strategy = GenerationType.AUTO) public long getId() { return id; }
  84. 84. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 84 Generating keys Generation using a table / table generator ✔ Using a table to store key values ✔ Portable amongs vendors @Id @TableGenerator( name="PersonId_Gen", table="GEN_ID", pkColumnName="GEN_OBJECT", pkColumnValue="Person", valueColumnName="GEN_ID", initialValue=10, allocationSize=1) @GeneratedValue(strategy=GenerationType.TABLE,generator="PersonId_Gen") // more simple //@GeneratedValue(strategy=GenerationType.TABLE) public long getId() { return id; }
  85. 85. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 85 Generating keys Generation using a Database Sequence ✔ Not supported by every database vendor! ✔ If not supported, choose Table strategy @Id @GeneratedValue(strategy=GenerationType.SEQUENCE) public long getId() { return id; }
  86. 86. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 86 Generating keys Generation using Database Identity ✔ Adds an identity column to the table ✔ Not supported by all database vendors @Id @GeneratedValue(strategy=GenerationType.IDENTITY) public long getId() { return id; }
  87. 87. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 87 Wrappers for numbers ✔ If you use a primitive on a nullable field JPA (at least using Hibernate in JBoss) will throw an error when it reads a null value from the database and attempts to put that value into a primitive field. ✔ You can search for days to find this error!
  88. 88. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 88 Lab Implement some hints (not more than 15 min.)
  89. 89. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 89 Review Session Review: ✔ Can you name the principles behind DAO, Generic DAO and Domain-specific DAO? ✔ How does pagination help? ✔ Why do we need to have DTOs?
  90. 90. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfältigung untersagt 90 Recommeded reading ✔ http://java.sun.com/blueprints/corej2eepatterns/ ✔ http://www.corej2eepatterns.com/Patterns2ndEd/ ✔ Adam Bien, J2EE Patterns, Addison Wesley 2002, ISBN: 3-8273-1903-X ✔ Floyd Marinescu, Ed Roman: Ejb Design Patterns: Advanced Patterns, Processes, and Idioms; Wiley & Sons, ISBN-10: 0471208310 ✔ And other ... Photo: Bundesarchiv
  • tomascejka1

    Feb. 5, 2019
  • Gudimetla

    Mar. 28, 2018
  • ericxiong75457

    Sep. 17, 2016
  • PhilippeCANCELLIER

    Oct. 28, 2015

Pattern of the Entity Layer, thx to the inspiring Book from Adam Bien, part of the lectures held at Duale Hochschule Mannheim

Aufrufe

Aufrufe insgesamt

1.303

Auf Slideshare

0

Aus Einbettungen

0

Anzahl der Einbettungen

2

Befehle

Downloads

54

Geteilt

0

Kommentare

0

Likes

4

×