Reputation: 47280
public class GenericDao <T, PK extends Serializable> {
private final Class<T> type;
@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
public GenericDao(final Class<T> type) {
this.type = type;
}
public PK save(final T o) {
return (PK) sessionFactory.getCurrentSession().save(o);
}
// ... get,delete, etc
App context bean:
<bean id="fooDao" class="com.mycompany.dao.GenericDao">
<constructor-arg>
<value>com.mycompany.Foo</value>
</constructor-arg>
</bean>
And in service layer invoke like so :
@Autowired
private GenericDao<Foo, Integer> fooDao;
...
public doStuffIncludingSave(Foo foo)
fooDao.save(foo);
Upvotes: 3
Views: 17873
Reputation: 181
A good place to start is this Generic DAO article its from 2006 but has some good information in it. To update the generic DAO for Spring, hibernate and annotations this is what I have done. Also this newer article is quite useful as well.
All identifier is is a generic intferface to make sure the class has a I getId()
and setId(I id)
Create a Generic DAO interface
public interface GenericDao<T extends Identifier<I>, I extends Serializable> {
public T find(I id);
public void delete(T obj);
public void saveOrUpdate(T obj);
}
Create your GenericDAO Implementation
public abstract class GenericDaoImpl<T extends Identifier<I>, I extends Serializable> implements GenericDao<T, I>{
private Class<T> type;
@Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected SessionFactory getSessionFactory() {
if (sessionFactory == null)
throw new IllegalStateException("SessionFactory has not been set on DAO before usage");
return sessionFactory;
}
public Class<T> getType() {
return type;
}
public GenericDaoImpl() {
this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
@Transactional(readOnly = true)
@Override
public T find(I id) {
return (T) getSessionFactory().getCurrentSession().get(getType(), id);
}
@Transactional
@Override
public void delete(T obj) {
getSessionFactory().getCurrentSession().delete(obj);
}
@Transactional
@Override
public void saveOrUpdate(T obj) {
getSessionFactory().getCurrentSession().saveOrUpdate(obj);
}
}
Object DAO interface:
public interface SomeObjectDao extends GenericDao<SomeObject, Long>{
}
Object DAO implementation
@Repository
public class SomeObjectDaoImpl extends GenericDaoImpl<SomeObject, Long> implements SomeObjectDao {
}
now in Any class that needs it, like a service class, you can get autowiring by just adding the object class dao that you need
@Autowired
private SomeObjectDao someObjectDao;
Upvotes: 13
Reputation: 120771
Better than writing it by yourself would be using
In both it will look very similar: only the interface, no Implmentation:
public interface UserDao extends GenericDao<User, Long> {
User findByLogin(String login);
}
If you are interested in, look at the documentation.
Upvotes: 2
Reputation: 26574
It looks like you are passing the type to the dao just so you can get the correct type for the generics in the dao. Rather than do that you could use Spring's java configuration which would allow you to have a method something like:
@Bean(name="myAsdfDao")
public GenericDao<MyAsdf, MyAsdfId> getMyAsdfDao() {
return new GenericDao<MyAsdf, MyAsdfId>();
}
which would let you keep entity specific daos without having to pass the type to a constructor through xml config. This would be in an @Configuration annotated class that provides java based configuration for spring.
Upvotes: 1
Reputation: 115328
I think your solution is fine but you do not need the class parameter T
. It just limits you and does not allow to re-use the same DAO for Integers and Strings (for example).
Save method does not need this type at all.
Methods like get()
or find()
should receive generic type themselves:
public <T> T findById(Class<T> clazz, Serializable id);
public <T> List<T> listAll( Class<T> clazz );
Upvotes: 2
Reputation: 10493
The bad point of such design -- what would you do to perform some non-trivial actions? And what about actions on many object? When the number of objects used in request will reach some significant amount (say, 1000) you will face a great slowdown due to multiple db requests.
From my experience the good way it to create some class like presented GenericDao and then derive particular DAO's from it. It allows to put some useful common methods in GenericDao and implement specific methods in particular derivatives.
Upvotes: 0