簡體   English   中英

使用Hibernate和Spring的通用DAO是他們比這更好的方法嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM