Hibernate and Spring - Dao ,Services

13,152

Solution 1

If you are just starting development, look into Spring JPA. A service should be One-to-Many Repositories (DAO). But I would also not create all of that boilerplate code by hand anymore. Spring JPA eliminates the basic CRUD and search functions as well as pagination.

Here is a video that walks through all of the configuration for Spring, JPA, Hibernate, and finishes up with Spring Data JPA showing you all of the boilerplate code that is eliminated.

To use Spring Data JPA, your repository interface ends up being:

package com.mysampleapp.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.wcfgroup.model.Employee;

@Repository("employeeRepository")
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    Employee findBySsn(String ssn);
}

And then the XML configuration to use Spring Data JPA:

<jpa:repositories base-package="com.mysampleapp.repository"/>

All of the boilerplate code is now handled for you. You no longer need to create a basic repository class with find methods and basic CRUD functions. The JpaRepository interface offers a lot of nice features and you don't have do anything for the implementation.

Solution 2

It´s necessary have dao, daoImpl, service, serviceImpl for each model.

  • UserDao
  • UserDaoImpl
  • UserService
  • UserServiceImpl

You can use a generic class EntityDaoImpl anf the inteface EntityDao, like this:

EntityDao:

public interface EntityDao<E> {

void persist(E e) throws Exception;

void remove(Object id) throws Exception;

E findById(Object id) throws Exception;
}

EntityDaoImpl:

public class EntityDaoImpl<E>  implements EntityDao<E> {

@PersistenceContext(unitName="UnitPersistenceName")
protected EntityManager entityManager;

protected E instance;
private Class<E> entityClass;

@Transactional
public void persist(E e) throws HibernateException{     
    getEntityManager().persist(e);
}
    @Transactional
public void remove(Object id) throws Exception{     
    getEntityManager().remove((E)getEntityManager().find(getEntityClass(), id));
}

public E findById(Object id) throws Exception {     
    return (E)getEntityManager().find(getEntityClass(), id);    
}
    public EntityManager getEntityManager() {
    return entityManager;
}
public void setEntityManager(EntityManager entityManager) throws Exception{
    this.entityManager = entityManager;
}

    public Class<E> getEntityClass() throws Exception{      
   if (entityClass == null) {
            Type type = getClass().getGenericSuperclass();
          if (type instanceof  ParameterizedType) 
          {
              ParameterizedType paramType = (ParameterizedType) type;
              if (paramType.getActualTypeArguments().length == 2) {
                    if (paramType.getActualTypeArguments()[1] instanceof  TypeVariable) {
                       throw new IllegalArgumentException(
                          "Can't find class using reflection");
                   }
                    else {
                       entityClass = (Class<E>) paramType.getActualTypeArguments()[1];
                  }
               } else {
                  entityClass = (Class<E>) paramType.getActualTypeArguments()[0];
                }
           } else {
              throw new Exception("Can't find class using reflection");
          }
        }
       return entityClass;
   }
}

And you can use like this:

public interface UserDao extends EntityDao<User> {

}

and

public class UserDaoImpl extends EntityDaoImpl<User> implements UserDao{

}

Solution 3

No there is no need to have 30 service layers or 30 dao layers.you should specify the layers not considering the Entity wise but the business functionality wise.there can be 5 or 6 entities relevant for certain function and those should be in one layer.But still you will have to have getXById(), deleteX(x), createX(x) in those redundant layers if they are required.

Solution 4

Creating a separate service for each model is one way to do it, and I have seen real-world applications that do that, but I don't recommend it. It is overkill for the simple CRUD case and is unhelpful for the more complex cases (where you actually want a transaction to span several DAO calls). It leaves you with a lot of code that doesn't do much. The DAOs can be specified using Spring Data, the services will be boilerplate with each method wrapping a call to a DAO. Spring should help reduce boilerplate as opposed to mandating it.

If you have a totally CRUD application then you can legitimately do without services, put @Transactional on the DAOs, and call the DAO from the Controller. If the service is not pulling its weight get rid of it.

If you do have actual business logic in the application then when a user invokes something that can involve calls to different DAOs, those calls should usually take place within the same transaction so that if one thing fails everything gets rolled back. (Also creating a transaction is relatively expensive and if you have a controller making calls to different services for different entities then that will be slow.) That is where services come in handy, the service specifies the low-level use cases that the user wants to perform and allows transactional behavior to be specified.

For the CRUD case I would prefer using a tool like Grails or Play or Rails or something to writing Java with Spring MVC. Grails, for instance, will generate views and controllers for you, provide basic data access through GORM (so there are no DAOs to write), and it will let you specify services easily for the cases where you find you need them.

Share:
13,152

Related videos on Youtube

Urbanleg
Author by

Urbanleg

Updated on September 15, 2022

Comments

  • Urbanleg
    Urbanleg over 1 year

    I've been reading some tutorials and I could see that most of the MVC implementations

    are based on:

    1) a dao interface for example "IUserDao"

    2) a dao impl of that interface - "mySimpleUserDaoImpl"

    3) a service interface for persistance : "IUserService"

    4) and a impl - "UserServiceImpl"

    is this the best practice? i mean the reason i ask this question is because it seem redundant to have 30 services with getXById(), deleteX(x), createX(x) methods that are doing more or less the same.

    please take into account that I'm using spring 3 and hibernate 4, and I decided i will ask this question before i start slamming my keyboard with code

    thanks.

    • Bart
      Bart
      You can drop the I prefix for interfaces. The user shouldn't be aware it's getting an interface. Just call them UserDAO and UserService.
    • Nathan Hughes
      Nathan Hughes
      tutorials for a technology usually are not concerned with business logic so they are not good references for that. there's a similar question that might be helpful to you at stackoverflow.com/q/3688664/217324
  • bh5k
    bh5k almost 11 years
    Another thing to note about the Service layer is that is where your @Transaction should start. So if you want to rollback a transaction across multiple repositories the service tier is where you do it. That is why the Service should be One-to-Many with Repositories.
  • bh5k
    bh5k almost 11 years
    All of this code is essentially what Spring Data Jpa provides you: springsource.org/spring-data/jpa
  • bh5k
    bh5k almost 11 years
    There are actually a few errors with this code, you don't want to start your transactions in the DAO/Repository tier.