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.

Java EE Pattern: The Entity Layer

1.233 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Software
  • Loggen Sie sich ein, um Kommentare anzuzeigen.

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

×