Onion Architecture using JPA Entity as Domain Entity - spring

I've been struggling to choose to work with JPA entities as separated classes than domain entities in a single bounded context. I've faced the following choices
Use separated domain classes for Aggregate roots/Aggregates..etc with domain repositories to wrap Spring JPA repositories and use converters to map JPA entities <> Domain Entities with only required data
Lazy loading is about to be given away unless in mappers/converters are handling this inside domain repositories but this is overkill.
When saving objects, there might be related Aggregate roots (one to many relationship) which later in complex logic, I had to extremly take care of the state of the Domain entity to pass it to the domain repository and either fill it with all related data or simply map it (another method in the converter) with out relationship data (cascading not applied on JPA persisting)
A lot of duplicated code to avoid such situations even for very simple use cases
Or Use JPA entities as my domain entities and so far there are multiple examples/opinions of this like
https://github.com/citerus/dddsample-core/tree/Spring_Annotations_Autowire
http://www.javamagazine.mozaicreader.com/MayJune2018/Twitter#&pageSet=50&page=0
Should JPA entities and DDD entities be the same classes?
DDD, domain entities/VO and JPA
How to implement DDD using Spring Crud/Jpa Repository
On the other hand, there are opinions like this
Is it a good practice to use JPA entities as domain models?
My question, on the long run, from experience
What would cost more effort & time ?
Are both approaches are acceptable as practices ?
What are the pros and cons of both ?

What would cost more effort & time ?
Decoupling almost always does. It's trade-off !
Are both approaches are acceptable as practices ?
Yes. I see there are many conflicted opinions on both approaches but really, they're just opinions. Both are applied and cost.
What are the pros and cons of both ?
Using JPA entities as domain entities approach really 1- reduces the time cost notionally. 2- Also lets you use lazy loading with relationships avoiding more code in application service, that if you're not following referencing other aggregates by id instead which also is opinion based but really costs the lazy loading of JPA.
One down side to this approach is unit testing as I see it. Unit test should not depend on starting up container, database...etc. Should purely test business logic. But that's not optimally possible with such frameworks. See this answer for example
JPA Entity must be unit tested and how?
Using JPA as separated entities in the infrastructure with wrapper repositories will make unit tests easier to mock data and test purely the domain (business rules) with comfort. It will reversely to the previous pros, cost you the mapping effort and time, too much duplicated code for mapping, wrapping repositories..etc. It brings the headache (and this should be a pro) of caring what is the state of your domain entity because mapping of nulls to JPA entity will effect the relationships mapping to your persistence source, and you REALLY SHOULD CARE for the state of your domain entity.
Also automatic lazy loading of ORM will not be used and done easily. Either
1- You put a reference to other aggregates as member in your aggregate root (Breaking the aggregate ID reference rule) and handle that in the mappers
2- You get from repository only wanted data of aggregate root with other aggregate's ID as reference members. This is done by well defined queries in the repository implementation so, this is a lot of writing & customizing queries. Avoiding using default ones which returns full JPA entities with ready lazy loading related references.

Related

Is it plausible to uswe spring-data-jdbc in a scenario where the DB-schema differs from the domain-model

I'm considering using spring-data-jdbc for a project.
But i don't have any control over the DB-schema.
My domain model can be populated by the existing tables, but they differ in many ways.
Examples:
A specific aggregate in my model consists of nested Value-Objects. The corresponding table only features flat columns, so the nested Value-Objects would have to be mapped manually.
One the other hand, there are aggregates that don't have many nested Value-Objects, but the corresponding tables are organized according to a star-schema, so the values are distributed over many tables (instead of a single one).
I guess this prevents me from using many of the Quality-Of-Life features (like Query-Derivation and Mapping).
Do I actually get anything significant out of spring-data-jdbc in comparison to using a plain JdbcTemplate in this scenario?
The scenario you describe would make me tend towards plain JdbcTemplate.
But I would consider using the Aggregate approach Spring Data JDBC does:
Load complete aggregates
Reference between aggregates using ids, or something like an AggregateReference
And if you have an aggregate that actually can be mapped using Spring Data JDBC you can still do that.

Spring Boot Rest API + JPA

I have a CRUD based application, which uses Spring Boot REST Services and JPA. For JPA we have POJO objects mapped to RBMS - PostgreSQL.
Some of my pages require data to be fetched using joins of multiple POJO objects. I just wanted to know what is a good architectural practice to do the same. Following are some of the options i have been informed of, but not sure what are the pros and cons of each especially for a large data volume application.
Use Transient Variables in POJOs and use JPA joins
Use additional Spring View Objects to combine POJOs
Write native/HQL to join tables/POJOs
Any insight would be helpful. If any more details required from me, would be glad to provide.
I think it's better to go with Entity Mappings.
This will enable you to easily fetch the parent and its nested entities using either JPA methods or using hibernate.
You can also specify the fetch type to actually control the behaviour of this fetch.
In case, you are looking for any complex joins or fetch patterns, Entity Graphs and HQL will be very useful.

Which entities do I need to create Spring Data repositories for?

In "getting started" examples of Spring Data JPA, we create an interface which extends CrudRepository. However it handles only one Entity:
import org.springframework.data.repository.CrudRepository;
interface MyEntityRepository extends CrudRepository<MyEntity, Long> {
// methods...
}
In a real world application, there are many Entities (tables) and we need to do CRUD operations for them. What is the correct way to use Spring Data JPA repositories with multiple (related or unrelated) Entities?
Do I have to create interfaces for each Entities and Autowire them one by one (Which sounds very crazy idea for now)?
Spring Data use the concept of repositories as defined in Domain Driven Design. Repositories basically represent a collection of aggregate roots, which in turn are some of your entities, that you'll access and which enforce business constraints on others. E.g. if you have an Order consisting of LineItems, the Order'd be the aggregate root as it controls the lifecycle of the LineItems etc. Hence you'd define a repository for the Order but not for the LineItem. So it's by far not all entities that you'd create repositories for. It's basically an important part in your domain modeling to decide which entities become aggregate roots.
Another aspect is that repositories are usually backed by a persistence mechanism and that you don't want to code your business logic directly to the persistence API to keep it testable without having to deal with the persistence API. That means, a repository will contain query methods that basically represent a subset of all aggregate roots in the collection and are backed by a store-specific query implementation. This can only be achieved in a by-aggregate-root fashion.
The third and final aspect is that repositories help you to restrict access to persistence operations more easily as you can use e.g. the package scope to force clients to even use a dedicated service and basically hide all persistence operation for a certain domain object in a certain package. With a generic persistence API like the EntityManager you lose control over who actually reads what from any point in the system as it can just persist each and every type in the persistence context.
To summarize things: repositories represent a collection of aggregates and allow access to dedicated subsets of that collection. Spring Data makes creating these as easy as possible with the alternatives being architecturally less desirable (see reasoning above) or more cumbersome (if they had to be implemented manually. For which entities you create repositories depends on how you model your domain, which of them are aggregate roots.
You are correct. For each entity you want to use Spring Data with, you need to create an interface that extends one of the repository interfaces and then autowire that interface into your classes. You only need one of these per entity you wish to perform crud/query operations on. If there is an entity contained within another entity that is created/managed via a cascade relationship, you don't need to explicitly create a repository for that entity.
To your point, it may seem slightly verbose to have to create an interface and autowire it for each entity, but that's the way Spring Data was designed and is what enables it to automatically generate data access code for you. You obviously wouldn't have to do that if you wanted to write your own data layer.

Should there be a abstraction layer between database and model?

What I see a lot is that people use a Object Relational Mapper (ORM) for doing SQL stuff when working in a MVC environment. But if i really have complex queries I would like to write this whole query myself. What is the best practice for this kind of situation?
Having a Abstraction Layer between your model and the database with the complex queries
Still using the model with creating specific methodes that handle the queries
Or is there any other way that might be better? please tell me :)
Consider the Single Responsibility Principle. Specifically, the question would be...
"If I put data access logic in my model, what will that mean when I need to change something?"
Any time you need to change business logic, you're also changing the objects which maintain data access logic. So the data access logic also needs to be re-tested. Conversely, any time you need to change data access logic, you're also changing the objects which maintain business logic. So the business logic also needs to be re-tested.
As the logic expands, this becomes more difficult very quickly.
The idea behind the Single Responsibility Principle is to separate the dependencies of different roles which can enact changes to the application. (Keep in mind that "roles" doesn't map 1-to-1 with "people." One person may have multiple roles, but it's still important to separate those roles.) It's a matter of simpler support. If you want to make a change to a database query (say, for performance reasons) which shouldn't have any visible affect on anything else in the system, then there's no reason to be changing objects which contain business logic.
1. Having a Abstraction Layer between your model and the database with the complex queries
Yes, you should have a persistence abstraction that sits between storage (database or any other data source) and you business logic. Your business logic should not depend on "where", "how" and even "if" the data is actually stored.
Basically, your code should (at least - try to) adhere to SOLID principles, but as #david already pointed out: you are already violating the first on on that list.
Also, you should consider using a service layer which would be responsible for dealing with interaction between implementation of domain model and your persistence abstraction (doesn't matter whether you are using custom written data mappers or some 3rd party ORM).
In the article (more like excerpt, actually) the "MVC model" is actually all three concentric circles together. Domain model is not code. It actually is trm that describs the accumulated knowledge about the project. Most of domain model gets turned into pieces of code. Those pieces are referred to as domain objects.
2. Still using the model with creating specific methodes that handle the queries
This would imply implementation of active record. It is useful, but mostly misused pattern, for cases when your objects have no (or almost none) business logic. Basically - you should use active record only if all you need are glorified setter an getters, that talk to database.
Active record pattern is a very good choice when you need to quickly prototype something, but it should not be used, when you are attempting to implement fully realized model layer.
ORM's in general do not specifically have any drawbacks versus using direct SQL to fetch data from the database. ORM's as the name implies help in keeping your Relational model (designed using your SQL DDL's or using JPA annotations) and OO model in sync and help them integrate well together.
When using a ORM, you can write your queries in JPQL which is Object oriented SQL. So instead of writing queries that manipulate tables, you are writing queries that manipulate objects. You use the relationships between these objects to get your desired result. Now I understand that sometimes its easier to just write Native SQL, so the JPA specification allows you to run native sql! This just returns you list of "Generic Objects" which you can organize any way you like. When you choose to go this route and actually pick a JPA provider, like Hibernate, these providers have extended functionalities. So if you do have complex relationships you can use libraries like Hibernate Criteria Builder to help you create queries for those complex relationships.
So, if building a large MVC application, it would generally be a good idea to have this abstraction layer in the middle - handling all these relationships. It makes it easier on you the developer to just look at the big picture and the business side of the application.
Imho, no. I think, even the ORM layer adds often more complexity as needed. The databases have very good and sophisticated mechanisms for high-level data manipulation. Triggers, views, constraints, complex keying-indexing, (sub)transactions, stored procedures, and procedural extensions of the query language were normally much more as enough for everything.
The ORMs can't give, because of their structural barriers, a real interface to this feature set.
And the common practice is that the applications use practically only a nosql record service from all of this, and implement in an unneeded "middleware" which were the mission of the database.
Which I see really interesting, if the feature set of the databases got some OO-like interface (see "sql abstract types"), and the client-side logic went in the application (see "REST"). This practically eliminated the need of the middle layer.

Ditching ActiveRecord and NHibernate -- how to rearchitect?

I have an MVC3 NHibernate/ActiveRecord project. The project is going okay, and I'm getting a bit of use out of my model objects (mostly one giant hierarchy of three or four classes).
My application is analytics based; I store hierarchial data, and later slice it up, display it in graphs, etc. so the actual relationship is not that complicated.
So far, I haven't benefited much from ORM; it makes querying easy (ActiveRecord), but I frequently need less information than full objects, and I need to write "hard" queries through complex and multiple selects and iterations over collections -- raw SQL would be much faster and cleaner.
So I'm thinking about ditching ORM in this case, and going back to raw SQL. But I'm not sure how to rearchitect my solution. How should I handle the database tier?
Should I still have one class per model, with static methods to query for objects? Or should I have one class representing the DB?
Should I write my own layer under ActiveRecord (or my own ActiveRecord-like implementation) to keep the existing code more or less sound?
Should I combine ORM methods (like Save/Delete) into my model classes or not?
Should I change my table structure (one table per class with all of the fields)?
Any advice would be appreciated. I'm trying to figure out the best architecture and design to go with.
Many, including myself, think the ActiveRecord pattern is an anti-pattern mainly because it breaks the SRP and doesn't allow POCO objects (tightly coupling your domain to a particular ORM).
In saying that, you can't beat an ORM for simple CRUD stuff, so I would keep some kind of ORM around for that kind of work. Just re-architect your application to use POCO objects and some kind or repository pattern with your ORM implementation specifics in another project.
As for your "hard" queries, I would consider creating one class per view using a tiny ORM (like Dapper, PetaPoco, or Massive), to query the objects with your own raw sql.

Resources