Java 如何手动打开休眠会话?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/884423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:39:39  来源:igfitidea点击:

How do I manually open a hibernate session?

javahibernatespringlazy-loading

提问by Stefan Kendall

I have a rather large project involving spring and hibernate. Right now, I'm backing certain objects out of hibernate and into memory, and I've hit a sort of snag. I have the following setup.

我有一个相当大的项目,涉及 spring 和 hibernate。现在,我正在将某些对象从休眠状态转移到内存中,但我遇到了一些障碍。我有以下设置。

Class A contains a number of primitives and a class B. B contains primitives and a class C, which was previously lazy-loaded.

类 A 包含许多原语和一个类 B。B 包含原语和一个类 C,它以前是延迟加载的

Now I have this

现在我有这个

Service call 1:
1.) create object of class A
2.) get object of class B
3.) set B in A
4.) add A to memory

服务调用 1:
1.) 创建类 A 的对象
2.) 获取类 B 的对象
3.) 在 A 中设置 B
4.) 将 A 添加到内存

Service call 2:
1.) get A from memory
2.) get B from A
3.) get C from B
4.) operate on C

服务调用 2:
1.) 从内存中获取 A
2.) 从 A 中获取 B
3.) 从 B 中获取 C
4.) 对 C 进行操作

Because C is lazy loaded, it relied on a hibernate session existing to lazily load itself from B with hibernate, at least I believe this to be so. Now, however, I need to lazy load withoutmodifying the DAO to return an ID, and there exists no currenthibernate session to hiHyman into with OpenSessionInView. What's the best way to go about solving this problem, given the limitations? The only solutions I've found rely on unsuitable code change or an existing session, so I think that I could perhaps manually open a hibernate session. How would I go about doing this? Alternatively, is there a better solution to this problem?

因为 C 是延迟加载的,所以它依赖于一个存在的休眠会话来使用休眠从 B 延迟加载自己,至少我相信是这样。但是,现在我需要在修改 DAO 的情况下延迟加载以返回 ID,并且当前不存在可以使用 OpenSessionInView 劫持的休眠会话。考虑到局限性,解决此问题的最佳方法是什么?我发现的唯一解决方案依赖于不合适的代码更改或现有会话,因此我认为我也许可以手动打开休眠会话。我该怎么做呢?或者,有没有更好的解决方案来解决这个问题?

采纳答案by Brian Yarger

If you can get a reference to your configured SessionFactory, you should be able to just call openSession() on it.

如果您可以获得对已配置的 SessionFactory 的引用,则您应该能够在其上调用 openSession()。

回答by James McMahon

As a best practice, you'll want to use a session factory. Here is the one Netbeans generates.

作为最佳实践,您需要使用会话工厂。这是 Netbeans 生成的一个。

public class HibernateUtil {

    private static final SessionFactory sessionFactory;
    private static final Configuration configuration = new Configuration().configure();

    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml) 
            // config file.
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception. 
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Once you have this, you can use this code for a transaction

拥有此代码后,您可以使用此代码进行交易

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
//Do something
session.getTransaction().commit();

Note that opening a transaction will open a session. I believe under pure Hibernate (unlike JPA) you need a transaction to do anything, even reads.

请注意,打开交易将打开一个会话。我相信在纯 Hibernate(与 JPA 不同)下,您需要一个事务来做任何事情,甚至读取。

At the end of the program you want to make sure you do this

在程序结束时,您要确保这样做

HibernateUtil.getSessionFactory().close();

For a more sophisticated solution, you may want to look into automatic session/transaction management with Spring or EJB. Which will handle the session behind the scenes once configured properly.

对于更复杂的解决方案,您可能希望使用 Spring 或 EJB 研究自动会话/事务管理。一旦配置正确,它将在后台处理会话。

EDIT:
Just re-read your question and your point about IDs. I believe the sessionfactory approach will work for your purposes, unless you are doing a multiple threaded application. This is because, by default, Hibernate sessions and the ORM objects linked to that session are associated to one thread only. Let me know if I am wrong about this.

编辑:
只需重新阅读您的问题和关于 ID 的观点。我相信 sessionfactory 方法将适用于您的目的,除非您正在执行多线程应用程序。这是因为,默认情况下,Hibernate 会话和链接到该会话的 ORM 对象仅与一个线程相关联。如果我错了,请告诉我。

回答by Paul Morie

Are you using HibernateTemplateand HibernateDaoSupportto implement your DAOs? If so, this is why your objects are disconnected. But, you should be able to use the OpenSessionInViewInterceptorin that case. Have you done anything to verify that you won't be able to use the interceptor?

您是否正在使用HibernateTemplateHibernateDaoSupport实施您的 DAO?如果是这样,这就是您的对象断开连接的原因。但是,OpenSessionInViewInterceptor在这种情况下,您应该可以使用。你有没有做任何事情来验证你将无法使用拦截器?

Also, if you choose to open a new Session, the object in memory will not be associated with the new Session. You'll need to reattach the object to the session in order for the lazy loading to work.

此外,如果您选择打开一个新的Session,内存中的对象将不会与新的Session. 您需要将对象重新附加到会话,以便延迟加载工作。

回答by Jherico

If you know your B objects might have their C's referenced, you should be retrieving the B's in such a way as to pre-fetch the C's. For instance the HQL

如果您知道您的 B 对象可能引用了它们的 C,那么您应该以预取 C 的方式检索 B。例如 HQL

from B as b where b.id = :ID

becomes

变成

from B as b left join fetch b.c where b.id = :ID

回答by Deepak Nigam

Simply use Session session = new Configuration().configure().buildSessionFactory().getCurrentSession(); Or Session session = new Configuration().configure().buildSessionFactory().getOpenSession();

只需使用 Session session = new Configuration().configure().buildSessionFactory().getCurrentSession(); 或者 Session session = new Configuration().configure().buildSessionFactory().getOpenSession();