Sessions and DAO Classes in Hibernate



  • Hello.

    There's a small project working with the OBD. Hibernate 4.

    By concomitantly squeezing Freumworth, creating classes of things, connecting annotations, using DAO pattern. But: In the implementation of the DAO classes in each changing OBD method, the session opened and closed directly in the method (as in this stannel reference http://javaxblog.ru/article/java-hibernate-1/ ) Example

    Session session = null;
            try {
                session = HibernateUtil.getSessionFactory().openSession();
                session.beginTransaction();
                // Здесь добавляю, обновляю или удаляю
                // ...
                session.getTransaction().commit();
            } catch (Exception e) {
                // Обрабатываю
                // rollback()
            } finally {
                // Закрываю
                if (session != null && session.isOpen()) {
                    session.close();
                }
            }
    

    But something tells me it's something, softly speaking, wrong.
    It's a bit of an internet, it's on a story. https://developer.jboss.org/wiki/GenericDataAccessObjects where it is stated that the Implementation DAO should not create a session inside, but only be referred to. If I understood correctly, the DAR of Implementation should not be concerned about the establishment of sessions.

    You could also use constructor injection. How you set the Session and what scope this Session has is of no concern to the actual DAO implementation. A DAO should not control transactions or the Session scope.

    The issue of experienced developers is interesting: Should a session be established once for all the annex and simply on the grid to send a reference to the DAOs to the classes (not to close the session), or in each method of the DAO class to establish and close the session?



  • I wish the author had time to answer his own question. Even though I'm never an experienced developer, I'll try to answer the information I found online this day.
    Many resources recommend that Hibernate be used in conjunction with Spring. I don't like this advice because there's a "true" coming in. A man learns to use a screwdriver, and he's going to learn to learn how to make a joke. Yeah, it's kind of cooler, but it won't be too much to use.

    Opening/ closing of the session.
    In the first of all, such a structure of interaction is requested: the DAO layer contains only the basic (CRUD - create, read, update, delete) interaction with the database; the business unit carries out transactions that can (and need) be combined into transactions.
    It looks like a DAO class around:

    public class ItemDAOImpl implements ItemDAO {
    
    private Session session;
    
    public ItemDAOImpl(Session session) {
        this.session = session;
    }
    
    @Override
    public Item get(long id) {
        return session.get(Item.class, id, LockMode.PESSIMISTIC_READ);
    }
    
    @Override
    public long create(Item item) {
        return (Long) session.save(item);
    }
    
    @Override
    public void update(Item item) {
        session.update(item);
    }
    
    @Override
    public Item delete(long id) {
        Item item = session.byId(Item.class).load(id);
        session.delete(item);
        return item;
    }
    

    }

    Session session Created in a business complex and transferred to a DAO designer:

    public class AdminServiceImpl extends PersonServiceImpl implements AdminService {

    SessionFactory sessionFactory;
    
    public AdminServiceImpl(SessionFactory sessionFactory){
        this.sessionFactory = sessionFactory;
    }
    
    @Override
    public long createItem(Item item) throws DBException {
        try (Session session = sessionFactory.openSession()){
            Transaction transaction = session.beginTransaction();
    
            ItemDAO dao = new ItemDAOImpl(session);
            long id = dao.create(item);
    
            transaction.commit();
    
            return id;
        } catch (HibernateException | NoResultException e) {
            throw new DBException(e);
        }
    }
    
    @Override
    public void updateItem(Item item) throws DBException {
        try (Session session = sessionFactory.openSession()){
            Transaction transaction = session.beginTransaction();
    
            ItemDAO dao = new ItemDAOImpl(session);
            dao.update(item);
    
            transaction.commit();
    
        } catch (HibernateException | NoResultException e) {
            throw new DBException(e);
        }
    }
    
    @Override
    public void deleteItem(long id) throws DBException {
        try (Session session = sessionFactory.openSession()){
            Transaction transaction = session.beginTransaction();
    
            ItemDAO dao = new ItemDAOImpl(session);
            Item item = dao.delete(id);
    
            transaction.commit();
    
        } catch (HibernateException | NoResultException | IllegalArgumentException e) {
            throw new DBException(e);
        }
    }           
    

    }

    The lack of a method is obvious - a garbage collector must be active at heavy load to free memory from DAO and service facilities. It's left behind, but it's supposed to be a service class object. AdminServiceImpl♪ In the designer, this facility receives reference to a type object SessionFactory

    Opening strategy
    In order to avoid the permanent establishment of dao and service facilities, a mechanism is needed to establish a session or to receive a current session in each of these facilities independently. And there are strategies for opening the session. Recommended http://javaoutsource.blogspot.ru/2011/03/hibernate-opensession-getcurrentsession.html to read.
    Let's say we choose a strategy. ManagedSessionContext - Each flow at a separate session. The session could then be used for the session
    Session session = sessionFactory.getCurrentSession();

    Alas, it won't work at once. To make it work, it's necessary. hibernate.cfg.xml Write
    <property name="current_session_context_class">thread</property>
    Or the second way to configuration. hibernate Add a characteristic
    configuration.setProperty("hibernate.current_session_context_class", "thread");

    Already familiar DAO-Class will look like:

    public class ItemDAOImpl implements ItemDAO {

    ItemDAOImpl() {
    }
    
    @Override
    public Item get(long id) {
        return DBService.getSessionFactory()
                .getCurrentSession()
                .get(Item.class, id, LockMode.PESSIMISTIC_READ);
    }
    
    @Override
    public long create(Item item) {
        return (Long) DBService.getSessionFactory()
                .getCurrentSession()
                .save(item);
    }
    
    @Override
    public void update(Item item) {
        DBService.getSessionFactory().getCurrentSession()
                .update(item);
    }
    
    @Override
    public Item delete(long id) {
        Session session = DBService.getSessionFactory().getCurrentSession();
        Item item = session.byId(Item.class).load(id);
        session.delete(item);
        return item;
    }
    

    }

    Here. DBService - abstract class with reference to objective SessionFactory♪ It's a function. getSessionFactory():

    public static SessionFactory getSessionFactory(){
    return sessionFactory;
    }

    And here's transferable service class:

    public class AdminServiceImpl extends PersonServiceImpl implements AdminService {

    AdminServiceImpl() {
    }
    
    @Override
    public long createItem(Item item) throws DBException {
        Transaction transaction = DBService.getTransaction();
        try {
            ItemDAO dao = DaoFactory.getItemDAO();
            long id = dao.create(item);
    
            transaction.commit();
    
            return id;
        } catch (HibernateException | NoResultException e) {
            DBService.transactionRollback(transaction);
            throw new DBException(e);
        }
    }
    
    @Override
    public void updateItem(Item item) throws DBException {
        Transaction transaction = DBService.getTransaction();
        try {
            ItemDAO dao = DaoFactory.getItemDAO();
            dao.update(item);
    
            transaction.commit();
    
        } catch (HibernateException | NoResultException e) {
            DBService.transactionRollback(transaction);
            throw new DBException(e);
        }
    }
    
    @Override
    public void deleteItem(long id) throws DBException {
        Transaction transaction = DBService.getTransaction();
        try {
            ItemDAO dao = DaoFactory.getItemDAO();
            Item item = dao.delete(id);
    
            transaction.commit();
    
        } catch (HibernateException | NoResultException | IllegalArgumentException | IllegalStateException e) {
            DBService.transactionRollback(transaction);
            throw new DBException(e);
        }
    }            
    

    }

    These are the functions used from DBService:

    public static Transaction getTransaction(){
    Session session = DBService.getSessionFactory().getCurrentSession();
    Transaction transaction = DBService.getSessionFactory().getCurrentSession().getTransaction();
    if (!transaction.isActive()) {
    transaction = session.beginTransaction();
    }
    return transaction;
    }

    public static void transactionRollback(Transaction transaction){
        if (transaction.getStatus() == TransactionStatus.ACTIVE
                || transaction.getStatus() == TransactionStatus.MARKED_ROLLBACK) {
            transaction.rollback();
        }
    }
    

    Here's the class. DaoFactory installment ItemDAO:

    public abstract class DaoFactory {
    private static ItemDAO itemDAO = new ItemDAOImpl();

    public static ItemDAO getItemDAO() {            
        return itemDAO;
    }           
    

    }

    Actually, I think that's it.
    For those who want to feel the code, there are references to github:
    ♪ https://github.com/golubtsoff/webstore/tree/d5b3799bdf7154b86aa418e3ca8d29c3c857c82d ;
    ♪ https://github.com/golubtsoff/webstore ♪




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2