Reputation: 45
Some time ago I started to learn java EE
. I swiftly moved to spring(mvc)+hibernate. As I was learning about databases and integration with spring+hibernate I came up with an idea.
As far as I noticed(and understand) there's a common approach to build an objects structure including configuration files, entities, dao interface and dao implementation(as we're talking just about dbs, not controllers and other applications' layers). I decided to write a generic java class and call it BasicDao
. It's a template which takes entity as a type.
This is actually working and I think it's much better than interfaces and implementations, because you need only one class for all entities(if you wanted to write separated implementations for each entity you might end up with a big amount of files).
I also wrote some template functions there so the class is very flexible(no exceptions with types passed to the db). Here's the code
package local.bb.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository(value = "basicDao")
@Transactional(propagation = Propagation.REQUIRED,readOnly = true)
public class BasicDao<ENTITY> {
private Class<ENTITY> data;
private SessionFactory sessionFactory;
public BasicDao() {
this.data = null;
}
@Transactional
public void addRecord(ENTITY t) {
this.sessionFactory.getCurrentSession().save(t);
}
@Transactional
public void removeRecord(ENTITY t) {
this.sessionFactory.getCurrentSession().delete(t);
}
@Transactional
public List<ENTITY> getAllRecords() {
return (List<ENTITY>)this.sessionFactory.getCurrentSession().createCriteria(this.data).list();
}
@Transactional
public <TYPE> ENTITY getRecordByParam(String param, TYPE value) {
return (ENTITY)this.sessionFactory.getCurrentSession().createCriteria(this.data).add(Restrictions.eq(param, value)).uniqueResult();
}
@Transactional
public <TYPE> List<ENTITY> getRecordsByParam(String param, TYPE value) {
return (List<ENTITY>)this.sessionFactory.getCurrentSession().createCriteria(this.data).add(Restrictions.like(param, value)).list();
}
// GETTERS / SETTERS
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Class<ENTITY> getData() {
return data;
}
public void setData(Class<ENTITY> data) {
this.data = data;
}
}
The question, finally, is: is it a good approach actually? Because I've never seen such code anywhere(speaking about tutorials on the Internet and books).
Upvotes: 2
Views: 855
Reputation: 11950
Spring likes interfaces since a couple of important mechanism are based on it, e.g. AOP, interceptors. So, if you decide to go without them you have to accept certain limits to Spring functionality. What's more, it will be harder to write Test-Mocks for other classes that depend on your DAOs.
If you want to save code, I suggest you lose the implementation rather than the interface. With Spring JPA you can annotate a DAO interface with as set of annotations, i.e. @Query, @Procedure, @Modifying
etc to define how the data is accessed. If you then enable JPA repositories in your application context, Spring will supply the DAO implementation for you.
More information can be found here.
Upvotes: 2
Reputation: 3935
Yes you can write generic DAO in hibernate and if it's useful and helps you to reduce substantial amount of code and makes your codebase clean then you should go for it. I have used generic DAO but only for simple CRUD operations. Here is a good read on generic persistence layer.
Upvotes: 0