Hi,
There is something that puzzles me about Hibernate when using it in a multi-tiered system, the components of which are geographically separate.
Imagine, for example, that I have the following tiers:
- A web server running a GUI located at Location A
- A back-end server located at Location B containing the persistence layer, exposing functionality through a web service.
The back-end server connects to a database that consists of two tables, the familiar Employee and Department (a Department having many Employees and an Employee belonging to a single Department).
Imagine now that a page is required in the GUI to display the details of a given Employee and allow his/her department to be amended. This requires two calls to the server : getEmployee and updateEmployee.
There are many, many fields in the Employee table but the GUI only requires ID, NAME, DEPT_ID.
IF the back-end server were using plain JDBC/SQL, we could envisage the following sequence of events:
1) The GUI remotely invokes the getEmployee method.
2) The back-end server issues a SQL command along the lines of "SELECT id, name, dept_id FROM employee WHERE id = ?" and returns the data in a response object.
3) The user alters the employee's Department ID to be 42 and hits "submit"
4) The GUI invokes the updateEmployee method, supplying the ID, NAME and (updated) DEPT_ID fields.
5) The back-end server issues a SQL command along the lines of "UPDATE employee SET name =?, dept_id = ? WHERE id = ?".
During these steps we have issued a
single READ to the database (to get the employee) and a
single WRITE (to update the employee).
Now, imagine that we decide to use Hibernate instead of our old JDBC DAOs. As I understanding things, we now have a number of options at the back-end.
1) Not changing the interfaces between the tiers
If we keep all the interfaces the same between the tiers, we can envisage the following sequence of events:
1) The GUI remotely invokes the getEmployee method.
2) The back-end server loads the requested Employee using Hibernate. The relevant fields are extracted and returned in the response object used in the JDBC scenario.
3) The user alters the employee's Department ID to be 42 and hits "submit"
4) The GUI invokes the updateEmployee method, supplying the ID, NAME and (updated) DEPT_ID fields.
5) The back-end server loads the Employee object using Hibernate.
6) The back-end server loads the Department object using Hibernate and attaches it to the Employee object loaded above.
7) The back-end server sets the Name property of the Employee object and persists the object.
Obviously, we have now gained a number of benefits from using Hibernate but we have incurred a performance hit. We have now issued
three READS to the database and a
single WRITE.
2) Changing the interface between tiers.
If, instead, we decide to change the interface between the tiers, we can pass detached objects between tiers, resulting in:
1) The GUI remotely invokes the getEmployee method.
2) The back-end server loads the requested Employee/Department using Hibernate. The Employee/Department are converted into DTOs and returned in full.
3) The user alters the employee's Department ID to be 42 and hits "submit"
4) The GUI invokes the updateEmployee method, supplying the entire Employee object, with the Name property updated, and the new DEPT_ID.
5) The back-end server loads the Department object using Hibernate and attaches it to the detached Employee object supplied.
7) The back-end server persists the object.
We have an advantage in this scenario because we can re-attach the Employee object supplied but we have still issued
two READS and
a single WRITE to the database. Furthermore, our network traffic has increased between the GUI and the back-end server.
So, my question is this: using Hibernate, is it possible to reduce the database access to a single READ and a single WRITE, without using SQL? Or is this simply a trade-off with the other benefits that Hibernate provides?
I appreciate that in the simple example above, the performance difference is negligible but I have seen situations where this has quickly become a problem.
I hope the example makes sense. I'd be interested to know what the consensus is on best practice.
Thanks in advance,
Simon