[英]Generic DAO with Hibernate and Spring, is their a better way than this?
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上下文bean:
<bean id="fooDao" class="com.mycompany.dao.GenericDao">
<constructor-arg>
<value>com.mycompany.Foo</value>
</constructor-arg>
</bean>
并在服务层调用如下:
@Autowired
private GenericDao<Foo, Integer> fooDao;
...
public doStuffIncludingSave(Foo foo)
fooDao.save(foo);
一个好的起点是这篇Generic DAO文章,它来自2006年,但它有一些很好的信息。 要更新Spring的常规DAO,hibernate和注释,这就是我所做的。 这篇新文章也很有用。
所有标识符都是一个通用的接口,以确保该类具有I getId()
和setId(I id)
创建通用DAO接口
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);
}
创建GenericDAO实施
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);
}
}
对象DAO接口:
public interface SomeObjectDao extends GenericDao<SomeObject, Long>{
}
对象DAO实现
@Repository
public class SomeObjectDaoImpl extends GenericDaoImpl<SomeObject, Long> implements SomeObjectDao {
}
现在在需要它的任何类中,就像服务类一样,你可以通过添加你需要的对象类dao来获得自动装配
@Autowired
private SomeObjectDao someObjectDao;
我认为您的解决方案很好,但您不需要类参数T
它只是限制你,并且不允许为整数和字符串重复使用相同的DAO(例如)。
Save方法根本不需要这种类型。
像get()
或find()
应该自己接收泛型类型:
public <T> T findById(Class<T> clazz, Serializable id);
public <T> List<T> listAll( Class<T> clazz );
比自己写的更好用
在两者中它看起来都非常相似:只有界面,没有Implmentation:
public interface UserDao extends GenericDao<User, Long> {
User findByLogin(String login);
}
如果您有兴趣,请查看文档。
看起来你正在将类型传递给dao,这样你就可以为dao中的泛型获得正确的类型。 您可以使用Spring的java配置 ,而不是这样做,这将允许您使用类似的方法:
@Bean(name="myAsdfDao")
public GenericDao<MyAsdf, MyAsdfId> getMyAsdfDao() {
return new GenericDao<MyAsdf, MyAsdfId>();
}
这将让你保持实体特定的daos,而不必通过xml配置将类型传递给构造函数。 这将在一个@Configuration注释类中,为spring提供基于java的配置。
这种设计的不好之处 - 你会做些什么来执行一些非平凡的行动? 对许多对象的行为怎么样? 当请求中使用的对象数量达到一定数量(例如1000)时,由于多个数据库请求,您将面临极大的减速。
根据我的经验,创建一些类的好方法就像GenericDao一样,然后从中派生出特定的DAO。 它允许在GenericDao中放入一些有用的常用方法,并在特定的衍生物中实现特定的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.