Reputation: 3510
I have an application that has the following java files:
Services:
AccountService.java
UserService.java
MessageService.java
DAOs:
AccountDAO.java
UserDAO.java
MessageDAO.java
Tables:
ACCOUNTS
USERS
MESSAGES
In MessageService.java
, I have a function newMessage()
that has to query data from all the 3 tables.
(1) According to Spring's decoupling standards, this is how the calls should be made:
AccountDAO.java -- ACCOUNTS
/
MessageService.java -- MessageDAO.java -- MESSAGES
\
UserDAO.java -- USERS
But the problem is, this approach makes 3 DB calls.
(2) For better Performance, I would do:
MessageService.java -- MessageDAO.java -- Join ACCOUNTS, MESSAGES and USERS
But this way, it's tightly coupled and if there's a change in USERS table, I'll have to change MessageDAO.java (and all other DAOs that I have, that use the USERS table) too. That is really bad, since (in the non-hypothetical) we have a LOT of DAOs
Which approach is considered a better practice? Or is there another approach that I'm missing?
Upvotes: 3
Views: 1395
Reputation:
Whichever method you follow, it's always about finding a sweet spot between decoupling and performance. It holds with even the selection of number of layers, etc.
So I guess as @mattb recommended, it's completely fine to join tables in a DAO if it makes sense in the particular context
Upvotes: 1
Reputation: 2939
Doing this as 3 separate queries might impact correctness if the data might change between one query and the next. Don't let (your idea of) Spring's guidelines make you write code that gets the wrong results.
It sounds like a join in SQL is the right approach.
Upvotes: 2
Reputation: 226
The alternative is to use an ORM such as Hibernate, mapping each of your tables to an entity. Then define the logical relationships between those entities. For example, a 1:M relationship between users and messages. As your tables change, your mappings will need to change, but your SQL won't (because Hibernate will generate it).
For most relationships, Hibernate is very good at creating joins to retrieve related entities in one query. You can control whether this happens; I recommend using lazy loads as a default for most relationships, and switching to eager loads as-needed.
Upvotes: 4
Reputation: 140061
According to Spring's decoupling standards, this is how the calls should be made
This is false. There are no "decoupling standards" with Spring. Please find me a reference in the Spring documentation that tells you how you must structure your persistence layer code.
Typically, you would have one DAO for each "entity" that your application wants to operate on, but it would be foolish to take this pattern to the extreme of deconstructing a query that joins multiple tables together into three distinct queries.
If you need to have a newMessage()
method that joins some tables together in a query, choose which DAO that makes the most sense in - probably the MessageDAO
and write the query/method in the way that makes sense.
But there is no rule saying that you must have distinct queries for each entity and that one DAO class is not allowed to make queries that touch the tables of other entities. This is too extreme and has no benefit.
If one the other hand you are worried about the maintainability of having multiple data layer classes that are aware of all of your tables, then look into an ORM solution as parsifal mentioned to alleviate some of this work.
Upvotes: 4