1

Because of all the problems we can meet when trying to use Hibernate in a multithreaded application (1st clue, 2nd clue, 3rd clue, etc.), I was thinking of another solution: implementing the logical part within a classic Controller, and simply call it from my thread using URL.openConnection().

In other words, instead of doing something like this:

MyThread.java

public class MyThread implements Runnable {

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

}

Anywhere.java

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

I would like to try something like that:

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();

What do you think about it? Good or bad? I haven't tried yet, but I think such a solution will prevent the common errors we can meet using Hibernate in multithreading, because the server will execute the logical part as if someone were requesting the fake page.

PS: I know there are some solutions to use Hibernate in multithreaded applications, but each time I try one, another appears, and that until the I'm-fed-up-with-it point of no return.

PS2: I'm aware that such a solution need to be secured (e.g. UID as a token).

Community
  • 1
  • 1
sp00m
  • 47,968
  • 31
  • 142
  • 252

1 Answers1

4

I don't really see what problem you're trying to solve here. Hibernate is almost always used in a multi-threaded environment. In webapps, for example, concurrent requests are handled by multiple concurrent threads, and each thread uses its own Hibernate session. And that doesn't cause any problem.

You will have problem if you share the same session among threads, or if you share a given entity among threads.

If you start your own thread, and this thread uses its own session and entities, I don't see why you would have any problem.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Actually, when I run the logical part within the main thread (the browser is then waiting for it to get the HTTP response), my code works fine. When I run it in a new thread, without changing anything to the code, I get many kinds of exceptions: `PersistentObjectException: detached entity passed to persist`, then `LazyInitializationException: failed to lazily initialize a collection`, then `HibernateException: collection is not associated with any session`, and so on and so forth. The code in question is quite complex and takes a bit of time to run, that's why I need to run it in a new thread. – sp00m May 16 '12 at 11:49
  • So don't you think it could be a good alternative? I was thinking of passing ids as `GET` parameters instead of JAVA objects stored in sessions for example. – sp00m May 16 '12 at 11:50
  • That's because you pass entities to your new thread. Pass IDs, as you would do with your solution, and everything will be fine. The new thread will use its own session to load the entities from the IDs passed to the thread, and averything will be as usual. You don't need to invoke a URL to do that. – JB Nizet May 16 '12 at 12:18
  • I tried to pass IDs instead of objects, but I still can't make it work: I get the same exceptions. In my controllers, I'm using the `@Autowired` annotation for my repositories (i.e. my dao): `@Autowired private UserRepository userRepository` (then `userRepository.save(user)` for example). When I use that same annotation within my thread, attributes don't get initialized: a `NullPointerException` is thrown when using them. What I tried, is passing the autowired attributes from my controller which calls the thread to my thread using setters. I'm not sure it's a good solution. What do you think? – sp00m May 16 '12 at 12:52
  • This is a Spring problem. If you use `new SomeService()` and expect to have the repositories injected in the service, of course it won't work. You need to either pass the autowired service to your thread, or have your thread get the service from the swing application context. – JB Nizet May 16 '12 at 13:24
  • Man, this is quite annoying! But yeah, I finally tried the solution I proposed and it does work. I agree to say that it would have been better to implement the logical part within a thread directly, but I didn't manage to do so `:'(` Thanks anyway for your great help! You deserve my `+15` `:)` – sp00m May 16 '12 at 14:19