2012-07-01 5 views
2

Долгое время назад я создал один-класс-гибернации-Util, чтобы облегчить мою жизнь на действительно очень небольших приложений с использованием DetachedCriteria следующим образом:Насколько опасен компактный анти-шаблон, DetachedCriteria, DAO, используемый для спящего режима?

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 поделится мной каким-то светом, здесь? Я бы очень признателен.

EDIT

Изменено его закрыть сессию. То, что я делаю сейчас, чтобы избежать ленивых ошибок инициализации, заключается в установке lazy="false" в каждом сопоставлении «один-два-один» в hbm.xml.

ответ

0

Я думаю, что главная проблема, о которой вы должны беспокоиться, - это целостность транзакций. Я бы поспорил, что вы найдете много прецедентов, когда несколько операций safe/update/saveOrUpdate/delete должны быть в одной транзакции, но каждый делается в своей собственной транзакции «благодаря» этому вспомогательному классу.

Другая проблема заключается в том, что использование этого вспомогательного класса приводит к использованию двух сессионных заводов, а не только одного, поскольку этот вспомогательный класс использует свою собственную частную сессионную фабрику.

Я бы удалил этот класс и использовал Spring или EJB, чтобы иметь декларативное управление транзакциями, и использовать сеанс для каждого шаблона транзакции или открытый сеанс в виде шаблона, который гарантирует, что сеанс закрыт в какое-то время.