Search code examples
javahibernatespringservice-layer

service layer are bound to DB tecnology in a spring application


my question is: Are your service layer bound to tecnology you use?

For example, if you using hibernate, you put into your service layer some hql-queries or criteria-queries that are only hibernate features or you call simply DAO(and dao has hibernate implementation, and maybe jdbc implementation etc..) ?

I have some trouble to build an efficent layered architecture for my software.

EDIT This is a simple service...i think it's a service... without bound to tecnlogy i using (hibernate)

@Repository
public class PersonHibernateDAO implements PersonDAO {

    @Autowired
    SessionFactory sessionFactory;

    ... dao crud operations(implementation of PersonDAO interface) using sessionfactory ...

    //and some hibernate features methods
    public Person findByCriteria(Criterion criterion){
        // code
    }
}

@Service
public class PersonService {

    @Autowired
    private PersonDAO personDao;

    @Autowired
    private AccessDAO accessDao;

    @Transactional
    public boolean hasPermission(String username, String accessCode){
        Person p=personDao.findByUsername(username);
        Access a=accessDao.findByCode(accessCode);
        ... etc ...
    }
}

And this is a service with use Dao implementation

@Service
public class PersonService {

    @Autowired
    private PersonDAO personDao;

    @Autowired
    private AccessDAO accessDao;

    @Transactional
    public boolean hasPermission(String username, String password){
        Person p=((PersonHibernateDao)personDao).findByCriteria(Restrictions.eq("username", username);
        ... etc ...
    }
}

Wich of these two approach is right?


EDIT2

So, to summarize what I understood:

// BASE DAO INTERFACE
public interface DAOInterface<EntityClass, IDType extends Serializable> {
    EntityClass get(IDType id);
    EntityClass findById(IDType id);
    EntityClass save(EntityClass entity);
    EntityClass update(EntityClass entity);
    void delete(EntityClass entity);
}

// AN HIBERNATE IMPLEMENTATION
public abstract class HibernateDAO<EntityClass, IDType extends Serializable> implements DAOInterface<EntityClass, IDType> {

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory){
        this.sessionFactory=sessionFactory;
    }

    public void getSessionFactory(){
        return this.sessionFactory;
    }

    // Implements all DAOInterface method using sessionFactory

}

// PERSON DAO INTERFACE
public interface PersonDAO extends DAOInterface<Person, Long>{

    Person findByName(String name, String surname);
    List<Person> getInAgeRange(int year1, int year2);
}

// PERSON HIBERNATE DAO IMPLEMENTATION
public PersonHDAO extends HibernateDAO<Person, Long> implements PersonDAO{

    // Implements the methods of PersonDAO interface using sessionFactory
}

@Service
public class PersonService {

    //spring inject the correct DAO by its xml config(in this case PersonHDAO
    @Autowired
    private PersonDAO personDAO; 

    // spring manage the transaction
    @Transactional
    public List<Person> getInAgeRange(int year1, int year2){
        return personDAO.getInAgeRange(year1, year2);
    }

}

// NOW... HOW USE IT
//let's assume i have a button, pressing it a table will be populated with all persons in age range
private void actionPerfom(ActionEvent e){
    List<Person> list=personService.getInAgeRange(age1Spinner.getValue(), age2Spinner.getValue());
    //Load a table with list
}

Sorry for this wall of text, maybe can be useful for others i hope, im go in the right direction? My service layer need an interface? Is all corectly layered? I need a control layer too?

Thanks.


Solution

  • My suggestion:

    for larger projects, use a dedicated, interface based DAO layer. Don't let your service layer know anything about the underlying persistence technology. Use Hibernate / JPA / JDBC / JDO / whatever only in the DAO layer.

    for smaller projects it may be okay to have a service layer only (especially given the fact that both Hibernate Session and JPA EntityManager expose most standard DAO behavior out of the box.

    Basic rule of thumb: if you're making a technology change, make sure you only need to change one layer of your application

    Update: here's a sample DAO interface. Your service layer would only code against this interface, and the implementation would do the session / entityManager / jdbc calls without the service layer needing to know.

    public interface CustomerDao extends CommonDao<Customer>{
        Customer getCustomerByEmail(String emailAddress);
        List<Customer> getCustomersWithinAgeRange(int lowerBound, int upperBound);
    }
    

    The key: in your service layer, specify your dependencies interface-based, i.e.

    private CustomerDao customerDao;
    public void setCustomerDao(CustomerDao customerDao){
        this.customerDao = customerDao;
    }
    

    instead of

    // this is horrible, it ties the service layer to implementation
    // details of the dao layer
    private HibernateCustomerDaoImpl customerDao;
    public void setCustomerDao(HibernateCustomerDaoImpl customerDao){
        this.customerDao = customerDao;
    }