I am new to Hibernate so my question could be seen as a very straight forward one, also I will try not to be too generic (as I am always told off because of that), although as with all architectural question it is hard to avoid that... I never know where to ask these questions.
I have setup a webapp using Spring + Hibernate. My architecture uses a series of Controllers which make use of Services that ultimately call DAO methods to obtain my domain objects.
I also have a GenericDAO which implements all the basic data access methods (findAll, findById, save, delete, update...) which I extend for my concrete Dao so I only have to implement specific data access methods.
So a request to view all users will have this flow: the proper controller is called through request mapping, which feeds the view with the result from calling userService.getAllUsers()
which at the same time makes a call to userDao.findAll()
.
This is all nice and I think I'm doing it properly enough.
My question relates to relationships among domain objects, so let's say users have accounts and for one view I want to show the user's details plus his list of accounts.
I never found out what's the best way to gather the accounts object list. Should I mark the relationship as Eager? Should I make a call like this:
user.accountList = accountService.findAccountsByUser(userId);
if that's the case then what's the point of specifying the relationship in the first place? Or maybe I am missing some other way here?
What happens with Many to Many relationships? Am I forced to create a domain object called UserAccount (assuming an account can be associated to several users) that maps the relations between the two?
1 Answer 1
You can also control the "eager/lazy" fetching at query time. From the docs:
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-joins
A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections.
I think the more specific question you want to ask here is: how do I avoid loading too many objects (more than necessary for a given situation) but at the same time, when I do want to load them all, how do I avoid the dredded N+1 select issue
A rule of the thumb can be the following: what's the most often used fashion to get X data for my application? Do I mostly need it with its sub-entities populated or do I only seldom need those as well. This rule should guide you into setting eager/lazy fetching on the association. Then for those non-standard cases where you need data in a fashion different from the declared eager or lazy relationship-level annotation, you can override it using the above mentioned query-level fetch join.
A good way to double check all this is to debug Hibernate at the generated SQL level. For example this can quickly show you if a certain (single) Hibernate query becomes a series of (N+1) selects when getting translated to SQL. Here's a good article on how to configure this:
-
It's been a while since I asked this question and I'm way over my initial doubts, but your question is comprehensive enough, and summarizes what I ended up doing by following "my guts". Have an upvote, sir.M Rajoy– M Rajoy2014年01月28日 22:20:20 +00:00Commented Jan 28, 2014 at 22:20
-
your *answer is what I meantM Rajoy– M Rajoy2014年01月29日 09:30:52 +00:00Commented Jan 29, 2014 at 9:30
ISession
. There's a case to be made for strongly-typed repositories (testability) but isn't your "DAO" pretty much a useless wrapper around the session? ORMs replace DAOs. And it seems a lot of your concerns are essentially around the limitations imposed by this unnecessary layer in between.