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

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.

Related

What are the advantages of using Spring JPA Specifications over direct queries

I am currently working on a project where I have to retrieve some rows from the database based on some filters (I also have to paginate them).
My solution was to make a function that generates the queries and to query the database directly (it works and it's fast)
When I presented this solution to the senior programmer he told me this is going to work but it's not a long-term solution and I should rather use Spring Specifications.
Now here comes my questions :
Why is Spring Specifications better than generating a query?
Is a query generated by Spring Specifications faster than a normal query?
Is it that big of a deal to use hard-coded queries ?
Is there a better approach to this problem ?
I have to mention that the tables in the database don't store a lot of data, the biggest one (which will be queried the least) has around 134.000 rows after 1 year since the application was launched.
The tables have indexes on the rows that we will use to filter.
A "function that generates the queries" sounds like building query strings by concatenating smaller parts based on conditions. Even presuming this is a JPQL query string and not a native SQL string that would be DB dependent, there are several problems:
you lose the IDEs help if you ever refactor your entities
not easy to modularize and reuse parts of the query generation logic (eg. if you want to extract a method that adds the same conditions to a bunch of different queries with different joins and aliases for the tables)
easy to break the syntax of the query by a typo (eg. "a=b" + "and c=d")
more difficult to debug
if your queries are native SQL then you also become dependent on a database (eg. maybe you want your integration tests to run on an in-memory DB while the production code is on a regular DB)
if in your project all the queries are generated in a way but yours is generated in a different way (without a good reason) then maintenance of the will be more difficult
JPA frameworks generate optimized queries for most common use cases, so generally speaking you'll get at least the same speed from a Specification query as you do from a native one. There are times when you need to write native SQL to further optimize a query but these are exceptional cases.
Yes, it's bad practice that makes maintenance a nightmare

Onion Architecture using JPA Entity as Domain Entity

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.

Which is better ORM (Apache Cayenne) , JDBC or SpringJDBC?

I am Working on multiple database like MSSQL server and PostgreSQL with heavy transactions and complex queries. I have searched that simple jdbc is more faster then ORM. I was thinking of using ORM because I do not want to write different query for different database for same work, and also for standardized my dao layer. I am mapping my database tables without using foreign keys and for ORM like apache cayenne I have to map tables with foreign key constraint, so I can use my Joins or any other multiple table operations. Is it good to use and ORM or simple jdbc is fine.
From your problem dscription, you already have an understanding of the tradeoffs involved. So this is really a decision that you need to make for yourself based on those tradeoffs.
My only advice here will be to take a second look at performance requirements. While ORM does introduce an overhead of creating, storing and managing objects, in all but a few cases, you can safely ignore this overhead for the sake of a better abstraction. Also when working with JDBC very often you end up writing your own code to convert ResultSet to objects, which will encounter its own overhead. So you may not end up with faster code, while forfeiting all the benefits of a clean object model and a framework that manages it.
So my own preference is to go with a better abstraction (ORM in this case), and then use the framework tools for optimizing the performance. E.g. to speed up processing of large ResultSets Cayenne provides a few techniques: result iterators, DataRow queries, paginated queries, etc.
On the other hand I would use JDBC or something like MyBatis when it is not possible to cleanly model your data as entities. E.g. when there are no natural relationships, all access happens via stored procedures, etc. Doesn't seem like your case though.

jpa specification query method

We are using the Spring Data JPA for database access. Our repositories contain basic query methods. What we want to do now is to use the Specification-Interface (criteria API) combined with complex query methods (like findByName(Specification spec)). The problem is that these two ways block each other out (since there are two where queries now). Is there any way to do this, like telling JPA to combine the two where parts with AND? The reason we want to do this is because some parts of the where query are essential for every query. They should be defined in the name of the query method. The Specification only should contain individual criterias for individual use-cases.
Or is there any other way to solve this?
Currently this is not supported. Please feel free to raise a JIRA issue if you think this would be a worthwhile enhancement.

Recommended data structure for a Data Access layer

I am building a DataAccess layer to a DB, what data structure is recommended to use to pass and return a collection?
I use a list of data access objects mapped to the db tables.
I'm not sure what language you're using, but in general, there are tradeoffs of simplicity vs extensibility.
If you return the DataSet directly, you have now coupled yourself to database specific classes. This leaves little room for extension - what if you allow access to files or to other types of data sources? But, it is also very simple. This is the recordset pattern and C#/VB provide a lot of built-in support for this. The GUI layer can access the recordset and easily manipulate the data. This works well for simple applications.
On the other hand, you can wrap the datasets in a custom object, and provide gateway methods (see the Gateway pattern http://martinfowler.com/eaaCatalog/gateway.html). This method is more complex, but provides a lot more extensibility. In a larger application when you need to separate the the business logic, data logic, and GUI logic, this is a more robust way to go.
For larger enterprise applications, you can look into using Object Relational Mapping tools (ORM). They help to automatically map java objects to database tables. They hide a lot of the painful SQL details. Frameworks such as Spring provide excellent support for ORMs.
I tend to use arrays of objects, so that I can disconnect the DAO from the business logic.
You can store the data in the DAO as a dataset, for example, and give them an easy way to add to the database before doing an update, so they can pass in information to do modification operations, and then when they want to commit the changes they can do it in one shot.
I prefer that the user can't add/modify the structure themselves, as it makes it harder to determine what must be changed in the database.
By initially returning an array they can then display what is in the database.
Then, as the presentation layer makes changes, the DAO can be updated by the controller. By having a loose coupling the entire system becomes more flexible, as you can change the DAO from a dataset to something else, and the rest of the application doesn't care.
There are two choices that are the most generic.
The first way to look at a ResultSet is as a List of Maps, where each Map represents a row in the ResultSet. The keys are the columns listed in the FROM clause; the values are the database values.
The second way to look at a ResultSet is as a Map of Lists, where each List represents a column in the ResultSet. The Map keys are the columns listed in the FROM clause; the values are the List of database values.
If you don't want to do full-blown ORM, these can carry you a long way.

Resources