10

I know that sessions are not thread safe. My first question: is it safe to pass an entity to another thread, do some work to it, then pass it back to the original thread and update.

public class Example1 {
    MyDao dao;
    ...
    public void doWork() {
        MyEntity entity = dao.getEntity();
        Runnable job = new Job(entity);
        Thread t = new Thread(job);
        t.run();
        t.join();
        dao.merge(entity);
    }

}

My second question: is it safe to new up an entity in one thread and save it in another?

public class Example2 {
    MyDao dao;
    ...
    public void doWork() {
        MyEntity entity = new Entity();
        new Thread(new Job(dao, entity)).run();
    }
}

public class Job implements Runnable {
    private MyDao dao;
    private MyEntity entity;
    ...
    @Override
    public void run() {
        dao.save(entity);
    }
}

Edit I forgot to mention that the entities are specifically configured for eager loading

Floegipoky
  • 3,087
  • 1
  • 31
  • 47
  • The second example is not safe for sure - I think you'll also get an exception cause the session you're using in your DAO is bound to another thread than your Job. Concerning the first I'm not sure. – isnot2bad Nov 22 '13 at 16:49
  • The way I implemented it, MyDao.merge() is essentially `sessionFactory.getCurrentSession.merge(entity);` So it uses the session bound to the thread that calls it. – Floegipoky Nov 22 '13 at 16:54
  • Why are you interested in creating your own threads? – Lion Nov 22 '13 at 16:57
  • I'm "outsourcing" to other threads because the work is easily parallelizable and the bottleneck for each individual task is network latency. The real version of this uses a thread pool – Floegipoky Nov 22 '13 at 17:02

1 Answers1

8
  1. No. The entity is attached to the session and contains proxies linked to the session (in order to lazy-load themselves). Doing that would thus use the session from multiple threads. Since the session is not thread-safe, this is not a good idea.

  2. While the entity is transient (i.e. you've just created it with new), it's not attached to the session, Hibernate doesn't know about it, and the entity is a plain old Java object. So no problem doing that.I don't have all the details of your DAO though. If the method of your DAO is supposed to be invoked as part of an existing transaction, that won't work, since the transaction is tied to the current thread.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I'm sorry, I forgot to mention that everything is loading eagerly. transaction boundaries shouldn't be an issue, so I think your answer to 2 applies. Does eager loading change your answer to 1? – Floegipoky Nov 22 '13 at 16:58
  • Ad 2: Doesn't it depend on which thread was used to create the session and to start the transaction? – isnot2bad Nov 22 '13 at 17:00
  • If you can guarantee that the session will never be used, I don't see why it wouldn't work, but such a guarantee is hard to provide (for now and for the future). It would be much safer to copy the state you need to some other object and pass this object. Or to reload the entity by ID in the spawed thread. – JB Nizet Nov 22 '13 at 17:02
  • @isnot2bad: yes, precisely. If the DAO method invoked in the spawned thread gets a new session, starts a transaction, saves the entity, commits the transaction and closes the session, the fact that the transient entity comes from another thread doesn't matter. If the DAO is supposed to save the entity and if that save is supposed to be part of a transaction created by the first thread, that won't work. – JB Nizet Nov 22 '13 at 17:04
  • @JBNizet ok. I assumed that the DAO got its session at construction time. But you're right - we don't know exactly... – isnot2bad Nov 22 '13 at 17:08
  • I'm lucky enough to be able to make that guarantee for this project. The second approach is what I'm doing now, but the session cache is making things unnecessarily complicated. @isnot2bad The entire transaction will run in the same session, and it will be the one bound to the correct thread – Floegipoky Nov 22 '13 at 17:09