2

很久以前,我使用 DetachedCriteria 创建了一个类休眠实用程序来简化我在非常小的应用程序上的生活,如下所示:

import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.DetachedCriteria;

/* WARNING: This utility was projected only for applications of one operation per use per mapping!
Using it for multiple operations characterizes the anti-pattern "session-per-operation". */
public class HibernateUtil {
    private static final int SEARCH = 0;
    private static final int LIST = 1;
    private static final int SAVE = 2;
    private static final int UPDATE = 3;
    private static final int SAVE_OR_UPDATE = 4;
    private static final int DELETE = 5;
    private static final int MERGE = 6;
    private static SessionFactory SESSION_FACTORY;

    // Single session factory instantiation
    static {SESSION_FACTORY = new Configuration().configure().buildSessionFactory();}

    // Opens the session and executes only one operation on the transaction
    private static Object executeTransaction(Object object, int operation) {
        Object output = null;
        Session session = SESSION_FACTORY.openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            switch (operation) {
                case SEARCH: output = ((DetachedCriteria) object).getExecutableCriteria(session).uniqueResult(); break;
                case LIST: output = ((DetachedCriteria) object).getExecutableCriteria(session).list(); break;
                case SAVE: session.save(object); break;
                case UPDATE: session.update(object); break;
                case SAVE_OR_UPDATE: session.saveOrUpdate(object); break;
                case DELETE: session.delete(object); break;
                case MERGE: session.merge(object); break;
                default: throw new HibernateException("No operation was executed on the database.");
            }
            transaction.commit();
        } finally {
            session.close();
        }
        return output;
    }

    // Usable methods, named accordingly to the operation:
    public static Object searchCriteria(DetachedCriteria criteria) {return executeTransaction(criteria, SEARCH);}
    public static List<?> listCriteria(DetachedCriteria criteria) {return (List<?>) executeTransaction(criteria, LIST);}
    public static void save(Object object) {executeTransaction(object, SAVE);}
    public static void update(Object object) {executeTransaction(object, UPDATE);}
    public static void saveOrUpdate(Object object) {executeTransaction(object, SAVE_OR_UPDATE);}
    public static void delete(Object object) {executeTransaction(object, DELETE);}
    public static void merge(Object object) {executeTransaction(object, MERGE);}
}

这允许我通过调用与数据库进行交互HibernateUtil.searchCriteria()/listCriteria()/save()/update()/saveOrUpdate()/delete()/merge(),但由于它的会话每个操作的性质,我实际上在非常罕见的情况下(小型应用程序)使用它。

问题是,我刚刚发现我的同事们一直在更大的应用程序中使用它,运行过度使用正确的 DAO 模式。我的错。我担心可能的副作用,例如开销或过载,但我不知道我应该担心什么问题。这是否足以让我开始在他们的应用程序中重新构建 DAO?

你们中的一些更有经验的程序员或 DBA 可以在这里分享一些亮点吗?我会非常感激。

编辑

将其更改为关闭会话。我现在为避免延迟初始化错误所做的是lazy="false"在 hbm.xml 中的每个多对一映射中进行设置。

4

1 回答 1

1

我认为您应该担心的主要问题是事务完整性。我敢打赌,您会发现许多用例,其中几个安全/更新/保存或更新/删除操作应该在一个事务中,但每个都在自己的事务中完成,“感谢”这个帮助程序类。

另一个问题是使用这个助手类会强制使用两个会话工厂而不是一个,因为这个助手类使用它自己的私有会话工厂。

我会删除这个类,并使用 Spring 或 EJB 进行声明式事务管理,并使用每个事务模式的会话或视图模式中的打开会话,这两者都确保会话在某个时间关闭。

于 2012-07-01T07:38:57.803 回答