2013-11-22 4 views
10

Я знаю, что сеансы не являются потокобезопасными. Мой первый вопрос: безопасно ли передать объект другому потоку, выполнить некоторую работу, затем передать его обратно в исходный поток и обновить.Hibernate session thread security

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

} 

Мой второй вопрос: безопасно ли новое создание объекта в одном потоке и сохранять его в другом?

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

Редактировать Я забыл упомянуть, что сущности специально сконфигурированы для загрузки нетерпеливого

+0

Второй пример небезопасен - я думаю, вы также получите исключение, потому что сеанс, который вы используете в вашем DAO, связан с другим потоком, чем ваш Job. Что касается первого, то я не уверен. – isnot2bad

+0

Как я его реализовал, MyDao.merge() по существу является 'sessionFactory.getCurrentSession.merge (entity);' Поэтому он использует сеанс, привязанный к потоку, который его вызывает. – Floegipoky

+0

Почему вы заинтересованы в создании собственных тем? – Lion

ответ

6
  1. No. Объекта прикрепляются к сессии и содержат прокси, связанное с сессией (в целях ленивая загрузка). Таким образом, это будет использовать сеанс из нескольких потоков. Поскольку сеанс не является потокобезопасным, это не очень хорошая идея.

  2. В то время как сущность временно (т. Е. Вы только что создали ее с новым), она не привязана к сеансу, Hibernate не знает об этом, а сущность - простой старый объект Java. Так что никаких проблем с этим. У меня нет всех деталей вашего DAO. Если метод вашего DAO должен быть вызван как часть существующей транзакции, это не сработает, поскольку транзакция привязана к текущему потоку.

+0

Прошу прощения, я забыл упомянуть, что все загружается с нетерпением. границы транзакций не должны быть проблемой, поэтому я думаю, что ваш ответ на 2 применим. Ожидает ли загрузка вашего ответа на 1? – Floegipoky

+0

Объявление 2: Не зависит от того, какой поток использовался для создания сеанса и для начала транзакции? – isnot2bad

+0

Если вы можете гарантировать, что сеанс никогда не будет использоваться, я не понимаю, почему это не сработает, но такую ​​гарантию трудно обеспечить (на данный момент и на будущее). Было бы гораздо безопаснее скопировать состояние, которое вам нужно, на какой-то другой объект и передать этот объект. Или перезагрузить объект по идентификатору в разреженном потоке. –