简体   繁体   English

Java“主”应用程序中的工作单元

[英]unit of work in a java 'main' application

I am doing this in each and every DAL method: 我在每个DAL方法中都这样做:

 public static Product GetProductByPartNumber(String partNumber)
    {
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();

         session.beginTransaction();


         Product product = (Product)session.createCriteria(Product.class)
                                    .add(Restrictions.eq("partNumber", partNumber))
                                    .uniqueResult();
         session.getTransaction().commit();



         return product;
    }

This is causing problems, giving me 'session is closed' errors because of lazy loading etc. 这会导致问题,由于延迟加载等原因,给我“会话已关闭”错误。

How can I have getCurrentSession to not get a new session? 如何让getCurrentSession不能获得新会话?

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            Configuration configuration = new Configuration().configure();

            //configuration.addClass(hsspider.Model.AMCategory.class);

            return configuration.buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }


}



 <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

I am guessing that is the problem, that the call to getCurrentSession is not getting the current session right? 我猜这是问题所在,对getCurrentSession的调用未正确获取当前会话?

Or does calling transaction.commit(); 还是调用transaction.commit(); kill the session? 杀死会议? Should I just use flush? 我应该只使用冲洗吗?

Did you look at the Transaction javadoc that I'm quoting below? 您是否看过下面引用的Transaction javadoc?

Allows the application to define units of work, while maintaining abstraction from the underlying transaction implementation (eg. JTA, JDBC). 允许应用程序定义工作单元,同时保持对基础事务实现(例如JTA,JDBC)的抽象。

A transaction is associated with a Session and is usually instantiated by a call to Session.beginTransaction() . 事务与Session相关联,通常通过调用Session.beginTransaction()实例化。 A single session might span multiple transactions since the notion of a session (a conversation between the application and the datastore) is of coarser granularity than the notion of a transaction. 单个会话可能跨越多个事务,因为会话(应用程序和数据存储之间的会话)的概念比事务的概念具有更粗糙的粒度。 However, it is intended that there be at most one uncommitted Transaction associated with a particular Session at any time. 但是,意图是在任何时候最多有一个与特定Session关联的未提交Transaction

And, about Transaction#commit() : 并且,关于Transaction#commit()

Flush the associated Session and end the unit of work (unless we are in FlushMode.NEVER . This method will commit the underlying transaction if and only if the underlying transaction was initiated by this object. 刷新关联的Session并结束工作单元(除非我们处于FlushMode.NEVER 。除非且仅当基础事务由该对象启动时,此方法才会提交基础事务。

This should answer your question: commit() doesn't kill the session (that can span multiple transaction as we saw). 这应该回答您的问题: commit()不会终止会话(如我们所见,它可以跨越多个事务)。

Another good idea would be to put a breakpoint and to look at the internal details (you may need to tell your IDE where to find Hibernate sources for this). 另一个好主意是放置一个断点并查看内部细节(您可能需要告诉IDE在哪里可以找到Hibernate源代码)。

I also suggest to check Pluggable Session management in Hibernate 3.1 and the more recent Sessions and transactions (especially Transaction demarcation with plain JDBC ). 我还建议检查Hibernate 3.1中的可插入会话管理以及最新的会话和事务 (尤其是使用纯JDBC的事务划分 )。

It could be that you use the ThreadLocalSessionContex . 可能是您使用了ThreadLocalSessionContex The interesting part of that javadoc is: 该javadoc有趣的部分是:

it was decided to have this default impl actually generate a session upon first request and then clean it up after the Transaction associated with that session is committed/rolled-back 决定让此默认隐式实际上在第一次请求时生成一个会话,然后在提交/回退与该会话关联的事务之后将其清除

The best way to deal with this is to move your transaction boundaries to incorporate the entire process; 解决此问题的最佳方法是移动交易边界以合并整个流程。 that is, not only getting the Product but also doing whatever you want with it. 也就是说,不仅获得产品,而且可以随心所欲地使用它。

You can change the behavior of ThreadLocalSessionContext by subclassing it and re-implementing isAutoCloseEnabled() and other methods. 您可以通过子类化ThreadLocalSessionContext并重新实现isAutoCloseEnabled()和其他方法来更改ThreadLocalSessionContext的行为。 You'd have to find a way to signal closing of the session though. 不过,您必须找到一种方法来通知会话已关闭。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM