【问题标题】:Work around Hibernate's errors in multithreaded applications解决多线程应用程序中 Hibernate 的错误
【发布时间】:2013-12-06 14:36:26
【问题描述】:

由于尝试在多线程应用程序中使用 Hibernate 时可能遇到的所有问题(1st clue2nd clue3rd clue 等),我正在考虑另一种解决方案:在经典 Controller,然后只需使用 URL.openConnection() 从我的线程中调用它。

换句话说,而不是做这样的事情:

MyThread.java

public class MyThread implements Runnable {

    @Override
    public void run() {
        // do some great stuff with Hibernate
    }

}

Anywhere.java

new Thread(new MyThread()).start();

我想尝试这样的事情:

MyController.java

@Controller
public class MyController {

    @RequestMapping(value = "myUrl", method = RequestMethod.GET)
    public void myMethod() {
        // do some great stuff with Hibernate
    }

}

MyThread.java

public class MyThread implements Runnable {

    @Override
    public void run() {
        // simple call the above mapped url
    }

}

Anywhere.java

new Thread(new MyThread()).start();

你怎么看?是好是坏?我还没有尝试过,但我认为这样的解决方案可以防止我们在多线程中使用 Hibernate 时遇到的常见错误,因为服务器将执行逻辑部分,就好像有人在请求 fake 页面一样。

PS:我知道有一些解决方案可以在多线程应用程序中使用 Hibernate,但每次我尝试一个时,都会出现另一个,直到 我受够了- with-it 不归路。

PS2:我知道需要保护这样的解决方案(例如,将 UID 作为令牌)。

【问题讨论】:

    标签: java multithreading hibernate spring-mvc


    【解决方案1】:

    我真的不明白你想在这里解决什么问题。 Hibernate 几乎总是在多线程环境中使用。例如,在 webapps 中,并发请求由多个并发线程处理,每个线程使用自己的 Hibernate 会话。这不会造成任何问题。

    如果您在线程之间共享同一个会话,或者如果您在线程之间共享给定实体,则会遇到问题。

    如果您启动自己的线程,并且该线程使用自己的会话和实体,我不明白您为什么会有任何问题。

    【讨论】:

    • 实际上,当我在主线程中运行逻辑部分时(浏览器正在等待它获取 HTTP 响应),我的代码工作正常。当我在一个新线程中运行它而不对代码进行任何更改时,我会遇到多种异常:PersistentObjectException: detached entity passed to persist,然后是LazyInitializationException: failed to lazily initialize a collection,然后是HibernateException: collection is not associated with any session,等等。有问题的代码非常复杂,需要一些时间才能运行,这就是为什么我需要在新线程中运行它。
    • 那么您不认为它可能是一个不错的选择吗?例如,我正在考虑将 id 作为 GET 参数而不是存储在会话中的 JAVA 对象传递。
    • 那是因为你将实体传递给你的新线程。传递 ID,就像您对解决方案所做的那样,一切都会好起来的。新线程将使用自己的会话从传递给线程的 ID 中加载实体,并且一切都将照常进行。您不需要调用 URL 来执行此操作。
    • 我尝试传递 ID 而不是对象,但我仍然无法使其工作:我得到了相同的异常。在我的控制器中,我为我的存储库(即我的 dao)使用了 @Autowired 注释:@Autowired private UserRepository userRepository(然后是 userRepository.save(user) 例如)。当我在线程中使用相同的注释时,属性不会被初始化:使用它们时会抛出 NullPointerException。我尝试的是从我的控制器传递自动装配的属性,该控制器使用设置器调用线程到我的线程。我不确定这是一个好的解决方案。你怎么看?
    • 这是一个 Spring 问题。如果您使用new SomeService() 并希望将存储库注入到服务中,那当然是行不通的。您需要将自动装配的服务传递给您的线程,或者让您的线程从 Swing 应用程序上下文中获取服务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    相关资源
    最近更新 更多