如何在 Hibernate 4.3.4.Final 中配置和获取会话? [英] How to configure and get session in Hibernate 4.3.4.Final?

查看:41
本文介绍了如何在 Hibernate 4.3.4.Final 中配置和获取会话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近将我的 Hibernate 版本升级到 4.3.4.Final.基于Hibernate的Contextual Sessions配置这个新版本不再基于 ThreadLocal 了. 如果我到目前为止所得到的都是正确的,我是否需要做任何事情来提高效率?如果不正确,我该怎么办?我不知道.

I recently upgraded the version of my Hibernate to 4.3.4.Final. Based on Contextual Sessions configuration of Hibernate this new version is not based on ThreadLocal anymore. If what I have got so far is correct do I need to do anything to make it more efficient? if it is incorrect what should I do? I have no clue.

请注意 文档中提到: Hibernate 提供了三种当前会话跟踪方法.基于线程"的方法不适合生产使用;它仅对诸如此类的原型设计和教程有用.

Please note it is mentioned in documentation that: Hibernate offers three methods of current session tracking. The "thread" based method is not intended for production use; it is merely useful for prototyping and tutorials such as this one.

Hibernate.cfg.xml

<hibernate-configuration>

    <session-factory>

    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/myDB</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>

    <!-- Disable the second-level cache  -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <property name="show_sql">true</property>

    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">20</property>
    <property name="hibernate.c3p0.timeout">300</property>
    <property name="hibernate.c3p0.max_statements">50</property>
    <property name="hibernate.c3p0.idle_test_period">3000</property>
        <!--        <property name="hbm2ddl.auto">update</property>-->

        <mapping class="com.myProject.entities.users" />
        ...

当前配置和代码

基于答案爆炸和 这部分文档 mu当前配置是以下:

Based on answers blew and this part of documentation mu current configuration is as following:

 public class HibernateUtil {

    private static SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
              Configuration configuration = new Configuration();
              return configuration.configure()
                                  .buildSessionFactory(
                                       new StandardServiceRegistryBuilder()  
                                          .applySettings(configuration.getProperties())
                                          .build());
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

}

代码如下

    final Session session = HibernateUtil.getSessionFactory().openSession();
    try {
        final Transaction tx = session.beginTransaction();
        try {
              ...

之前的配置和代码

public class HibernateUtil {

    private static ServiceRegistry serviceRegistry;
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal();
    private static SessionFactory sessionFactory;

    private static SessionFactory configureSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();
            serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties())
                    .build();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            return sessionFactory;
        } catch (HibernateException e) {
            System.out.append("** Exception in SessionFactory **");
            e.printStackTrace();
        }
        return sessionFactory;
    }

    static {
        try {
            sessionFactory = configureSessionFactory();
        } catch (Exception e) {
            System.err.println("%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }

    private HibernateUtil() {
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static Session getSession() throws HibernateException {
        Session session = threadLocal.get();

        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession() : null;
            threadLocal.set(session);
        }

        return session;
    }

    public static void rebuildSessionFactory() {
        try {
            sessionFactory = configureSessionFactory();
        } catch (Exception e) {
            System.err.println("%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }

    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            if (session.isOpen()) {
                session.close();
            }
        }
    }
}

访问交易和提交命令的代码

Code to access to transactions and submit commands

 final Session session = HibernateUtil.getSession();
        try {
            final Transaction tx = session.beginTransaction();
            try {

                    //Commands related to query go here

             if (!tx.wasCommitted()) {
                    tx.commit();
                }

                if (session.isOpen()) {
                    session.close();
                }

                return true;
            } catch (Exception e) {
                tx.rollback();
                return false;
            }
        } finally {
            HibernateUtil.closeSession();
        }
        return false;

推荐答案

我会放弃 TreadUtil 类,它让我想起 Spring 1.0 Hibernate 集成风格.如果您打算迁移到 Hibernate 4.

I would drop the TreadUtil class which reminds me of the Spring 1.0 Hibernate integration style. If you plan on moving to Hibernate 4.

除了你应该依赖 Hibernate 4 bootstrap机制,你的代码也存在以下问题:

Beside the fact that you should rely on Hibernate 4 bootstrap mechanism, your code also has the following problems:

  1. 会话工厂重建不同步

  1. The session factory rebuilding is not synchronized

    synchronized(HibernateUtil.class) {
    if (sessionFactory == null) {
        rebuildSessionFactory();
    }
}

  • 我不明白你为什么需要重建它,因为你从来没有将它设置为 null,会话工厂被初始化为静态块.

  • I don't see why you need to rebuild it, since you never set it to null, the session factory being initialized static block.

    如果您总是需要将您的 Hibernate 代码包装在 HibernateUtil.openSession() try/finally 块中,那么您将在混合业务逻辑和事务逻辑的同时复制大量会话管理逻辑.这打破了单一职责原则.

    If you always have to wrap your Hibernate code in the HibernateUtil.openSession() try/finally blocks, you would duplicate a lot of session management logic while mixing business logic with transaction logic. This breaks the single responsibility principle.

    如果你还是不想让HibernateUtil去,你至少可以使用类似于JDBCTemplate 在模板方法中抽象会话/事务管理,同时在 Callable 中提供业务代码,对您来说可能看起来像:

    If you still don't want to let the HibernateUtil go, you can at least use a mechanism similar to JDBCTemplate to abstract the session/transaction management in a template method, while supplying the business code in a Callable, which for you might look like:

    interface SessionCallback<T> {T doInSession(Session session);}
    
    class HibernateUtil {
    
        public T execute(SessionCallback<T> action) {
            try{
                //open session
                //open transcation
                T result = action.doInSession(sessionFactory.getCurrentSession());
                //commit tx
    
    
    
                return result;
            }
            catch(RuntimeException e) {
                //rollback tx
                throw e;
            }
            finally {
                //close session
            }
        }
    }
    
    HibernateUtil.execute(new SessionCallback<Void>() {
        public Void doInSession(Session session) {
            session.createQuery(...);
            return null;
        }
    });
    
    final customerID = ...
    
    Customer customer = HibernateUtil.execute(new SessionCallback<Customer>() {
        public Customer doInSession(Session session) {
            return (Customer) session.get(Customer.class, customerID);
            return null;
        }
    });
    

    查看您的代码表明您需要具有 session-per-request 访问习惯用法的 JDBC 资源本地事务,这意味着您需要 ThreadLocalSessionContext:

    Looking at your code indicates you want JDBC resource local transactions with the session-per-request access idiom, meaning you need the ThreadLocalSessionContext:

    hibernate.current_session_context_class=thread
    hibernate.transaction.factory_class=JDBCTransactionFactory
    

    额外

    您也可以考虑切换到 JPA,并将 Hibernate 属性移动到 persistence.xml.

    You might consider switching to JPA as well and moving the Hibernate properties to persistence.xml.

    这篇关于如何在 Hibernate 4.3.4.Final 中配置和获取会话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆