【问题标题】:Is my DAO strategy ok?我的 DAO 策略好吗?
【发布时间】:2009-06-22 22:46:32
【问题描述】:

我正在使用休眠。问题在底部。

目前的策略

很简单。

首先,我有一个基本的Dao<T>。

public class Dao<T> {
    private Class<T> persistentClass;
    private Session session;

    public Dao(Class<T> persistentClass) {
        this.persistenClass = persistentClass;
        this.session = HibernateUtil.getCurrentSession();
    }

它作为一个基类很好,它将最常用的方法传递给它的Session。

    public T get(Serializable id) {
        @SuppressWarnings("unchecked")
        T t = (T) this.session.get(this.persistentClass, id);

        return t;
    }

    protected Criteria getCriteria() {
        return this.session.createCriteria(this.persistentClass);
    }

当需要对模型使用查询时,它会进入该模型的特定 DAO,该 DAO 继承自 Dao&lt;T&gt;。

public class DaoTask extends Dao<Task> {
    public DaoTask() {
        super(Task.class);
    }

    public List<Task> searchActiveTasks() {
        @SuppressWarnings("unchecked")
        List<Task> list = (List<Task>) this.getCriteria()
            .add(Restrictions.eq("active", true))
            .list();

        return list;
    }
}

这种方法一直很有效。

但是...

但是,今天我发现很多时候一个实例需要重新附加到Session 并且最终会发生类似于以下的一行:

new Dao<Book>(Book.class).update(book);

...我觉得这很糟糕,因为

  1. 我不喜欢指定多余的Book.class
  2. 如果出现DaoBook,此构造将过时。

所以我把Dao&lt;T&gt;变成了一个抽象类,然后继续重构旧代码。

问题

为了从代码库中删除Dao&lt;T&gt; 引用,我想到了两种方法:

  1. 为每个需要附加的类创建特定的 DAO,这将生成许多几乎为空的 DaoBooks 和排序。
  2. 创建一个拥有Dao&lt;Object&gt; 并仅公开附件方法(即save()、update() 等)的类。

我倾向于选择 #2,但我认为这种“AttacherDao”模式可能不好,所以我想听听您的意见。

#2 有什么缺点吗?另外,你觉得“当前的策略”有什么问题吗?

【问题讨论】:

    标签: java hibernate dao


    【解决方案1】:

    我们的方法是为每个持久类创建一个 DAO 对象(从 commonDao 派生)。事实上,我们为这个 DAO 类定义了接口,每个 DAO 决定打开哪些接口。

    使用以下代码,用户无法删除PersistentClass。

    interface PersistentClassDao {
        void save(PersistentClass persistentObject);    
    }
    
    Class PersistentClassDaoImpl extends CommonDao implements PersistentClassDao {
            void save(persistentObject) {
        persist(persistentObject);
    }
    

    尽管它有一些额外的开销,但这种方法有助于在公开接口之前对适当的代码进行单元测试。

    【讨论】:

    • 所以你的建议是每个“业务操作”都有一个接口,即DeletableClassDao、UpdatableClassDao等?
    • 没有。一个业务对象只有一个 DAO,而不是一个业务操作,例如BookDao 和 BookDao 将封装对 Book 对象的所有操作,并可以决定用户是否可以“保存”、“更新”和/或“删除”。
    【解决方案2】:

    我们选择了一种类似于 lud0h 的方法,但有以下变化:

    abstract class<T extends IModelObject> JdbcCrudDao<T>{
    
       void create(T dbo){}
       T findByFoo(String foo){}
       void update(T dbo){}
       void delete(T dbo){}
    
    }
    
    class BarDao extends JdbcCrudDao<Bar>{
    
    }
    

    但是,不同的是,我们通过外观选择性地公开 Dao 上的方法,并且只转发那些我们绝对必须的方法。

    class BarController implements IController{
    
        private static final BarDao dao;
        // ...
    
        void update( IBar bar ){
           dao.update(bar);
        }
    
    }
    

    所有这一切中唯一的缺点是,如果您希望将数据库键隐藏在接口类型后面(我们这样做),它需要进行一些转换,但与替代方案(数据库代码之外的数据库代码)相比,这是一个非常小的不便。道)。

    【讨论】:

    • 我认为你的简洁让我感到困惑。 JdbcCrudDao 是否实现了任何东西,或者那些真的是空的或抽象的方法? BarDao 也一样!
    【解决方案3】:

    几个问题

    1. 您是经常创建 DAO 来执行单个任务还是这些任务长期存在?
    2. 使用静态函数怎么样?显然,您的 Book 对象可以在没有 Book.class 引用的情况下绑定 DAO 函数...

    否则,我有点担心保留会话对象而不是获取当前会话的任何内容 - 拥有长期存在的会话对象不是被认为“不好”吗?我不是 DAO 的高手,所以也许我在这里遗漏了一些东西。

    【讨论】:

    • DAO 是短暂的。只要正在处理用户请求,会话就会打开。
    • DAO。 DOA 是发生坏事的时候;)
    猜你喜欢
    • 2012-11-24
    • 1970-01-01
    • 2012-12-22
    • 2011-07-26
    • 2012-06-17
    • 1970-01-01
    • 2013-07-24
    • 2010-11-23
    • 1970-01-01
    相关资源
    最近更新 更多