DAO and Service Layer with hibernate - java

im in trouble with implemenetation of a service layer, i think i did not understand this concept very well.
In a DAO implementation i can write all CRUD logic for a specific technology and entity (for example hibernate and User table), and in a service layer we use a DAO for all data operation for the entity in DAO (like getUser, loginUser, etc..) is this ok?
If this is ok i have a simple question, can i handle database connection (or in case of hibernate, session and transaction) within service layer, DAO implementation or neither?
Example, i have a simple GUI with one Button(load all User), and a table will contains all User. Pressing the Button will load the table with all users.
I have a HibernateDAO for User entity (UserHibernateDAO) containing all CRUD operation and a service layer, UserService, for some specific data operation with user.
ServiceLayer:
public class UserService extends AbstractServiceLayer{
private AbstractDAO dao;
public UserService(AbstractDAO dao){
this.dao=dao;
}
public List<User> loadAllUsers(){
return dao.findAll();
}
}
In actionperformed of Button:
private void buttonActionPerformed(ActionEvent evt) {
Transaction transaction=HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
List<User> users=userService.loadAllUsers();
loadTableWithUsers(users);
transaction.commit();
}
Is this implementation ok?
Session and transaction handle is in the right position or i have to put it into service layer? ..or perhaps into dao?
EDIT1:
If i have an interface UserDAO and a UserHibernateDAO that implements UserDAO, service layer has no reason to exists, isn't true?
Becouse i can have all method to manage an "USER" inside my UserDAO and UserHibernateDAO implements all this methods for hibernate technology... then i could have a UserJdbcDAO, UserMysqlDAO etc... mmm...
EDIT2:
private void buttonActionPerformed(ActionEvent evt) {
myBusinessMethod();
}
private void myBusinessMethod(){
Transaction transaction=HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
List<User> users=userService.loadAllUsers();
loadTableWithUsers(users);
//some other useful operation before close session
transaction.commit();
}
im not sure, a business method is a method like this?
Thanks all.

You are handling the transaction inside your actionPerformed() method. Its clearly defeating the purpose of DAO/Service layer
Your UserService is accepting AbstractDAO, which means some other code may pass wrong DAO implementation to your UserService that will screw things up
Now, few suggestions.
You can look into GenericDAO concept for this. That might suit your need
Most of the time we ain't need all these layers like Service, DAO and BusinessDelegate. So, question yourself are any of these really answering some of your questions. If not, get rid of them. YAGNI
Get rid of DAO completely, and treat your Hibernate API as your DAO. Handle database transaction in your business methods. You may like to read this question
[Edited]
After your edit my 3rd suggestion doesn't carry much weight. By the way, you name your DAOs as follows; UserJdbcDAO, UserMysqlDAO etc. Your 2nd name is not making much sense, as we use ORMs just to avoid DB vendor specific DAOs/queries. It might start making some sense if your UserMysqlDAO extends UserJdbcDAO.

Related

Is good practice to inject Transactional service to another transactional service in Spring?

I'm in consternation. I found posts about inject #Service class to another #Service class. But what if the both classes have #Transactional annotation? #Transactional makes a difference or maybe better practise is inject repositories?
Simple exmaple:
#Transactional
#Service
public class BBBServiceImpl implements BBBService {
private final BBBRepository bbbRepository;
// #Autowired constructor, methods etc...
}
second class:
#Transactional
#Service
public class AAAServiceImpl implements AAAService {
private final AAARepository aaaRepository;
private final BBBService bbbService;
#Autowired
public AAAServiceImpl(AAARepository aaaRepository, BBBService bbbService) {
this.aaaRepository = aaaRepository;
this.bbbService = bbbService;
}
// methods etc...
}
Or better solution is:
#Transactional
#Service
public class AAAServiceImpl implements AAAService {
private final AAARepository aaaRepository;
private final BBBRepository bbbRepository;
#Autowired
public AAAServiceImpl(AAARepository aaaRepository, BBBRepository bbbRepository) {
this.aaaRepository = aaaRepository;
this.bbbRepository= bbbRepository;
}
// methods etc...
}
In general, classes shouldn't be transactional but rather their methods. You should apply #Transactional if the item concerned needs transactionality. Sometimes this means that you'll compose multiple levels, because you can see that even individually the pieces need #Transactional. Sometimes it means that only one level in the stack needs it. You must determine based on the logical requirements of your software.
A case where it makes sense to apply #Transactional is where you have a service that coordinates shipment of orders; the updates to mark the order shipped and to write the parcel information should happen transactionally. Therefore, OrderHandlingService#shipParcel should be #Transactional, and so should any methods involving data handling.
Ideally, Service layer (Manager) represents your business logic and hence it should be annotated with #Transactional.
Service layer may call different DAOs to perform DB operations. Lets assume a situation where you have 3 DAO operations in a service method. If your 1st DAO operation failed, other two may be still passed and you will end up with an inconsistent DB state. Annotating Service layer can save you from such situations.
Also it's depends on Propagation and Isolation values as well.
Even though you want to continue with same transaction but on service B it's Propagation is Propagation.REQUIRES_NEW it will create new transaction and perform business.
Yes you can. Since you can call another service inside a service even it is transactional or not. No problem & recommended

How to use JPA/JTA in a (CDI) Bean and in a outside way [duplicate]

I'm trying to get used to how JSF works with regards to accessing data (coming from a spring background)
I'm creating a simple example that maintains a list of users, I have something like
<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
Then the "controller" has something like
#Named(value = "userListController")
#SessionScoped
public class UserListController {
#EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
And the "service" (although it seems more like a DAO) has
public class UserListService {
#PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
Is this the correct way of doing things? Is my terminology right? The "service" feels more like a DAO? And the controller feels like it's doing some of the job of the service.
Is this the correct way of doing things?
Apart from performing business logic the inefficient way in a managed bean getter method, and using a too broad managed bean scope, it looks okay. If you move the service call from the getter method to a #PostConstruct method and use either #RequestScoped or #ViewScoped instead of #SessionScoped, it will look better.
See also:
Why JSF calls getters multiple times
How to choose the right bean scope?
Is my terminology right?
It's okay. As long as you're consistent with it and the code is readable in a sensible way. Only your way of naming classes and variables is somewhat awkward (illogical and/or duplication). For instance, I personally would use users instead of userList, and use var="user" instead of var="u", and use id and name instead of userId and userName. Also, a "UserListService" sounds like it can only deal with lists of users instead of users in general. I'd rather use "UserService" so you can also use it for creating, updating and deleting users.
See also:
JSF managed bean naming conventions
The "service" feels more like a DAO?
It isn't exactly a DAO. Basically, JPA is the real DAO here. Previously, when JPA didn't exist, everyone homegrew DAO interfaces so that the service methods can keep using them even when the underlying implementation ("plain old" JDBC, or "good old" Hibernate, etc) changes. The real task of a service method is transparently managing transactions. This isn't the responsibility of the DAO.
See also:
I found JPA, or alike, don't encourage DAO pattern
DAO and JDBC relation?
When is it necessary or convenient to use Spring or EJB3 or all of them together?
And the controller feels like it's doing some of the job of the service.
I can imagine that it does that in this relatively simple setup. However, the controller is in fact part of the frontend not the backend. The service is part of the backend which should be designed in such way that it's reusable across all different frontends, such as JSF, JAX-RS, "plain" JSP+Servlet, even Swing, etc. Moreover, the frontend-specific controller (also called "backing bean" or "presenter") allows you to deal in a frontend-specific way with success and/or exceptional outcomes, such as in JSF's case displaying a faces message in case of an exception thrown from a service.
See also:
JSF Service Layer
What components are MVC in JSF MVC framework?
All in all, the correct approach would be like below:
<h:dataTable value="#{userBacking.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.name}</h:column>
</h:dataTable>
#Named
#RequestScoped // Use #ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {
private List<User> users;
#EJB
private UserService userService;
#PostConstruct
public void init() {
users = userService.listAll();
}
public List<User> getUsers() {
return users;
}
}
#Stateless
public class UserService {
#PersistenceContext
private EntityManager em;
public List<User> listAll() {
return em.createQuery("SELECT u FROM User u", User.class).getResultList();
}
}
You can find here a real world kickoff project here utilizing the canonical Java EE / JSF / CDI / EJB / JPA practices: Java EE kickoff app.
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
Passing a JSF2 managed pojo bean into EJB or putting what is required into a transfer object
Filter do not initialize EntityManager
javax.persistence.TransactionRequiredException in small facelet application
It is a DAO, well actually a repository but don't worry about that difference too much, as it is accessing the database using the persistence context.
You should create a Service class, that wraps that method and is where the transactions are invoked.
Sometimes the service classes feel unnecessary, but when you have a service method that calls many DAO methods, their use is more warranted.
I normally end up just creating the service, even if it does feel unnecessary, to ensure the patterns stay the same and the DAO is never injected directly.
This adds an extra layer of abstraction making future refactoring more flexible.

what is the difference between using #Transactional in dao layer and in service layer?

What is the difference between using #Transactional in dao layer and in service layer?
#Transactional
class UserDAO{}
or
#Transactional
class UserService{}
We can put this annotation in both the layers. So what is the difference?
if you add #Transactional annotation at Service layer and you are performing multiple operations on database, then all these operations will be in a single transaction and with that you can make sure that both the operations are commited, if any of them failed then roll back.
For example: There is a case you want to create an Employee and your business rule says that for every Employee you create, you need to create User in your database. In such case we would use Transactional annotation at service layer
#Service
public class EmployeeService {
....
#Transactional
public int createEmployee(Employee emp) {
//create Employee
employeeDao.createEmployee(emp);
User user = new User();
// some fileds of employee are used to create a User
user.setEmployeeId(emp.getEmployeeId());
....
userDao.createUser(user);
...
}
}
There is no difference at all. But best practice is use it in Service layer. Cause sometimes you need to make transaction through more than one entity. So if you declare transactions in your dao manually. And you call method from service with two methods from your daos you will have two transactions in one call. And that is something what you don't want.

How to use session variables in DAO layer?

I have a #SessionScoped ApplicationBean for storing user login info and injecting it into other managed beans successfully as told here.
I also use my Dao interfaces by #ManagedProperty annotation but I feel something wrong with my usage.
Assume that there is as StockDao that has a public method listStocks(String companyCode) and companyCode is stored in the ApplicationBean when user logins.
So my managed bean is calling the DAO layer like this
#ManagedProperty(value = "#{appBean}")
ApplicationBean appBean;
public void getStockList() {
return stockDao.listStocks(appBean.getCompanyCode());
}
This repeats everywhere where the sql needs companyCode.
I feel that it would be better if my DAO layer had known companyCode (which means injecting ApplicationBean into DAOs) and I should use my methods like below
public void getStockList() {
return stockDao.listStocks();
}
So the question is, which API design would be better and if you vote for the second, how can I inject #SessionScoped beans into DAO layer?
For me 1st approach is much cleaner ,
i dont want to tie DAO layer with the session managed bean.
I keep my general artifacts especially daos and data models packaged as a seperate Jar , without any external dependencies
This way i could use the same without any modifications be it a Web App , Stand Alone or in an EJB
This keeps your Dao independent of how/where the Company Code is fetched from
You do not use session variables in the DAO layer. Lack of business logic and user interface matters is exactly what makes it DAO: a layer responsible just for abstracting data access.
If you add session-dependent state, you will turn your DAO layer into DAAMUIS layer (the ubiquitous Data Access And Miscellaneous User Interface Stuff layer). I am not saying that DAAMUIS is wrong or evil, just that the question needs rephrasing.

designing a hibernate dao

I am using following code
TestDAO {
Session session = null;
public TestDAO() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
//...more code create,update ...
//each method starts a transcation using "tx= session.beginTransaction();"
}
1)Now should i commit the transcation using tx.commit for a fetch operation too or only for save/update operation??
2)Should i create a seperate instance of TestDAO every time i need?Or should i create a singleton class that returns a single instance of DAO everytme?Will this have a problem?
You don't need tx.commit() for fetch operation. That is only needed for any save, update or delete. Close the session after data fetching.
If your application connect to only one database then use of single DAO is better. Spring framework encourages this. You will find more details about this on the following link
Don't repeat the DAO!
Transactions should not be the responsibility of the DAO, those really need to be controlled at a higher level. A DAO should be something that does queries and updates without being aware of the bigger picture, calls to DAOs can be grouped within an object like a Spring service or EJB session bean which is responsible for deciding what needs to go together in a transaction. This makes your DAO code more reusable since it doesn't have to know as much about the context in which it's operating.
Look at how Spring does it (in the sample applications like petstore that come with Spring), or better, look at the King/Bauer Hibernate-JPA book, which has a chapter on creating DAOs.

Categories

Resources