After reading some pages from DDD, I read about Repository pattern, then used it in an application successfully (I really liked it); then I noticed that EntityManager is generic-repository-like, but while I was reading about Repository I saw many examples on the web explaining how to impliment Repository pattern, and JPA was a simple Repository implementation between many implementations, like this website: http://www.lestard.eu/2015/generic_repository_part1/
The developer demonstrated in-memory implementations of Repository pattern, and in the second part : http://www.lestard.eu/2015/generic_repository_part2/, showed JPA implementation of repository pattern.
So here my question: while JPA is already like a generic repository, can we extend JPA to use in-memory, web services (e.g: REST CRUD) and entity persisting -- as JPA stands for Java PERSISITENCE API, (I wrote it in capital letters to show that it means a general persistence mechanism) -- as it seems that current JPA is tightly coupled with databases, but its name refer to a general use.
Technically it's possible but I would prefer not to do this and don't have any links to specific implementation standard (like Java JPA). I prefer to hide all of implementation details inside my Repository impl.
Moreover, I definitely don't like idea to put any persisting (like #Entity) or conversion (like #XmlRootElement from JAXB or #JsonProperty) annotations inside my domain objects.
The reason is the simple: if in the future you will change Java JPA to smth new like Java New JPA you'll have to change you domain objects for this too. But it contradicts whole DDD idea.
Related
In our project we use classes generated by eclipse hibernate plugin for persistence.
The generated classes have following structure.
MyClass extends BaseMyClass //POJO's, that are refenced in the hbm
files
MyClassDAO extends BaseMyClassDAO //DAO objects that use hibernate
session objects to provide CRUD API's for working with DB
My question is, would it violate Uncle Bobs clean architecture if we use the POJO classes used in the mapping files as the Entities in the innermost layer.
The hibernate specific DAO classes would belong in this case to the outermost layer and UseCases layer would communicate with this layer via providing an interface to be implemented.
Uncle Bob comments on this during a lecture in Norway while presenting this slide:
Uncle Bob says:
There is no Hibernate above the line. If you are using Hibernate it goes below the line. The application does not know that you are using that framework. It goes below the line. And Hibernate is a lovely tool. It's very good for gathering data out of the database and turning it into data structures. Very nice! But you don't want your application to know that you are using it. You put all that stuff below the line.
Robert C Martin - Clean Architecture, NDC 2012 (53:53 - 54:18)
Thus if you are using Hibernate annotations on the entities, you mix your domain objects with details of the database layer.
Some developers argue that annotations are not so strong dependencies, because if they are not available at runtime they just do not exist. That's true, but you also have to consider other principles.
If you put Hibernate annotations on your entities, the entity classes now have two different reasons to change: the domain logic and the database mapping.
This is a violation of the single responsibility principle. Therefore database mappings will affect your domain objects.
I guess there is a lot of confusion, because of the overloaded term entity. When Uncle Bob talks about entities he means domain. In Hibernate entity means database record.
That's why I usually distinguish them by using the term "domain entity" or "database entity".
According to Uncle Bob, the entity layer should know nothing about the database.
What about the JPA annotations then? Don't they violate the architecture proposed by the author? If they do, how to use the entities with JPA?
In a non-ORM world, a clean architecture would (or could) involve having DAO interfaces, with DAO implementations knowing how to retrieve the data from a database (or any other source), and convert and return it as a domain object. An upper layer would then use the DAOs (through the interfaces) to retrieve those objects.
This would allow you to for example create different DAO implementations for different databases, and you could change databases without bothering the rest of the software.
In a JPA/ORM world you can bypass a lot of that if you choose. You can use entity classes as domain objects, create the entity classes in a database agnostic way (i.e. not using any database specific NativeQueries for example). Now that your entities are database agnostic, you can just use NamedQueries in your service layer instead of creating DAOs.
In the end you need to have some layer which knows about the database, but in JPA's case it doesn't even hold true. Your entities are Java objects and it's the JPA implementation layer that is responsible for converting them to and from the database.
In conclusion: there are very few universal truths in software development and you can talk to a dozen uncles and hear a dozen versions of essentially the same "story".
I am trying to rewrite a bunch of DAOs here is the setting:
only plain JDBC (no JPA, ORM whatsoever)
no interfaces used
lots of checks before inserting an object
Business objects are strongly linked
My main question is:
How do I persist/retrieve a business object that is composed of multiple other objects?
e.g. does my CustomerDAO know the AddressDAO and retrieve the csutomers adresses from there?
only plain JDBC (no JPA, ORM whatsoever)
Business objects are strongly linked
Not sure why you don't want to use JPA while you want your business objects to be linked, but at least you should use Spring JDBC template that would relieve you from some boilerplate code.
Regarding the other constraints, I would do it as follows:
I would still employ interfaces to define the DAO methods and implement them in a Spring JDBC template backed DAOImpl. Use the DAO everywhere and inject the DAOImpl.
My DAOs will be simply one-to-one mapping to the underlying tables and each DAO wouldn't know about the existence of other DAOs.
My Manager layer will have all the business logic that runs validation checks and prepares the set of objects that need to be persisted, calls the appropriate DAO and appropriate method (CREATE/UPDATE/DELETE) to persist the objects.
Again, the Manager layer will follow the interface-based implementation and the view layer would have manager types injected with the ManagerImpls.
My two cents!
You may Consider Using JOOQ. It is not JPA, but it may easily be used as an alternative solution. It is lightweight enough. It also provides provides a reverse engineer tool, where it builds your Database entities as DAO objects.
I have embed JOOQ in a relevant situation, where the application was fairly engineered designed. I didn't use its DAO functionality, rather than using it as a higher layer to avoid messing with JDBC Layer.
Cheers!
Composite entities are a layer above DAO's. If you want to remove ALL coupling, domain objects persisted by DAOs should be flat without relationships. See Core J2EE patterns CompositeEntity.
Also, it's a good idea not to introduce coupling inbetween the DAO's by putting finders for one in the other. E.g.:
AddressDAO.findForCustomerId(id);
is inferior to using a third DAO to manage the relationship. I.E:
CustomerAddressRelDAO.findAddressForCustomer(id);
If you use a relationship DAO neither address nor customer are dependent on (or aware of) each other.
I'm trying to find a nice and elegant way to query database content based on DDD "specifications".
In domain driven design, a specification is used to check if some object, also known as the candidate, is compliant to a (domain specific) requirement. For example, the specification 'IsTaskDone' goes like:
class IsTaskDone extends Specification<Task> {
boolean isSatisfiedBy(Task candidate) {
return candidate.isDone();
}
}
The above specification can be used for many purposes, e.g. it can be used to validate if a task has been completed, or to filter all completed tasks from a collection. However, I want to re-use this, nice, domain related specification to query on the database.
Of course, the easiest solution would be to retrieve all entities of our desired type from the database, and filter that list in-memory by looping and removing non-matching entities. But clearly that would not be optimal for performance, especially when the entity count in our db increases.
Proposal
So my idea is to create a 'ConversionManager' that translates my specification into a persistence technique specific criteria, think of the JPA predicate class. The services looks as follows:
public interface JpaSpecificationConversionManager {
<T> Predicate getPredicateFor(Specification<T> specification, Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb);
JpaSpecificationConversionManager registerConverter(JpaSpecificationConverter<?, ?> converter);
}
By using our manager, the users can register their own conversion logic, isolating the domain related specification from persistence specific logic. To minimize the configuration of our manager, I want to use annotations on my converter classes, allowing the manager to automatically register those converters.
JPA repository implementations could then use my manager, via dependency injection, to offer a find by specification method. Providing a find by specification should drastically reduce the number of methods on our repository interface.
In theory, this all sounds decent, but I feel like I'm missing something critical. What do you guys think of my proposal, does it comply to the DDD way of thinking? Or is there already a framework that does something identical to what I just described?
Hades is a Repository framework as a wrapper for JPA. It is DDD friendly. It supports DDD Specifications out of the box. I also suggest you look at this article from InfoQ.
I actually read that article, but hades specifications require you to include JPA logic in your
specification. Specifications are domain specific and should be kept separate from any type of
persistence logic.
What about JPA annotations man...? Do you think your domain objects should be kept seperate from JPA annotations ?
I think the solution provided by Hades (which is now known as "spring-data-jpa") is a better solution than the one provided in Evans book : Eric Evans shows an example where a "Specification" calls a "Repository" which itself calls the "Specification" ! I really wondered how client code would only go through the specification, and not use the repository directly. The solution provided by Hades/Spring-data-jpa is a good one to me, it's ok to put JPA in domain logic, because JPA is designed to go in the domain layer.
EDIT : I forgot to mention Eric Evans implements a "double dispatch", it's not a silly circular dependecy between specification and repository, but as mentioned above, it doesn't prevent any developper to bypass the specification implementation.
In the .NET world, that is covered by LINQ. I know of no Java equivalent.
I'm hesitating between two designs of a database project using Hibernate.
Design #1.
(1) Create a general data provider interface, including a set of DAO interfaces and general data container classes. It hides the underneath implementation. A data provider implementation could access data in database, or an XML file, or a service, or something else. The user of a data provider does not to know about it.
(2) Create a database library with Hibernate. This library implements the data provider interface in (1).
The bad thing about Design #1 is that in order to hide the implementation details, I need to create two sets of data container classes. One in the general data provider interface - let's call them DPI-Objects, the other set is used in the database library, exclusively for entity/attribute mapping in Hibernate - let's call them H-Objects. In the DAO implementation, I need to read data from database to create H-Objects (via Hibernate) and then convert H-Objects into DPI-Objects.
Design #2.
Do not create a general data provider interface. Expose H-Objects directly to components that use the database lib. So the user of the database library needs to be aware of Hibernate.
I like design #1 more, but I don't want to create two sets of data container classes. Is that the right way to hide H-Objects and other Hibernate implementation details from the user who uses the database-based data provider?
Are there any drawbacks of Design #2? I will not implement other data provider in the new future, so should I just forget about the data provider interface and use Design #2?
What do you think about this? Thanks for your time!
Hibernate Domain objects are simple POJO so you won't have to create separate DPI-objects, H-Object themselves can be used directly. In DAO you can control whether they come from hibernate or anything else.
I highly recommend reading Chapter 4 "Hitting the database" of Spring in Action, 3rd edition, even if you aren't using Spring in your application. Although my second recommendation would be to use Spring :-)
The DAO pattern is a great way to keep database and ORM logic isolated in the DAO implementation, and you only need one set of entity objects. You can make that happen without Spring, it just takes more work managing your sessions and transactions.
If I understand your post, this is sort of a middle-ground between Design 1 and Design 2. The H-Objects (the entities that Hibernates loads and persists) don't need any Hibernate specific code in them at all. That makes them perfectly acceptable to be used as your DPI-Objects.
I've had arguments with folks in the past who complain that the use of JPA or Hibernate Annotations exposes Hibernate specifics through the DAO interface. I personally take a more pragmatic view, since annotations are just metadata, and don't directly affect the operation of your entity classes.
If you do feel that the annotations expose too much, then you can go old school and use Hibernate Mappings instead. Then your H-Objects are 100% Hibernate free :-)
I recommend design #2. Simply construct domain objects, and let hibernate look after them. Don't write separate classes that are persisted.
Hibernate tries to hide most of the persistence business from you. You may need to add a few small annotations to your entities to help it along. But certainly don't make separate classes.
You may need some very small DAO classes. For example, if you have a Person entity, it would be fairly common practice to have a PersonDAO object that saves a person. Having said that, the code inside the DAO will be very simple, so for a really small project, it may not be worth it. For a large project, it's probably worth keeping your persistence code separate from your business logic, in case you want to use a different persistence technology later.