开发者

How to implement updating of a table in a DB from different threads with Hibernate-based DAOs?

I have a class, let's call it UserGenerator. It contains several injected DAOs (spring singleton beans), let's say UserDao and OrganizationDao.

UserGenerator's purpose is creating users for a new organization. So, what I want to have is:

@Transactional
public void createOrganizationWithUsers(Organization org, int userCount) {
    organizationDao.persist(org);
    //run (userCount / 100) threads, let them do something like
    // userDao.persist(new User(randomParams())); 

}

The problem is that the organization is created successfully, but userDaos throw hardly-debugged exceptions and as I understand, they state that Hibernate session is closed (or, maybe, something else):

//this line (only if runs in a new thread) produces the exceptions 
//shown below (it tries to retrieve the organization by its Id)
getSession().createCriteria(getDomainEntityClass()).add(Restrictions.eq("id",id)).uniqueResult();

//Exceptions
org.hibernate.exception.JDBCConnectionException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2235)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2129)
at org.hibernate.loader.Loader.list(Loader.java:2124)
at org开发者_运维知识库.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:118)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1597)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306)
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:328)
...
Caused by: org.postgresql.util.PSQLException: An I/ error occured while sending to the backend.
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:220)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:350)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:254)
    at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
    at org.hibernate.loader.Loader.getResultSet(Loader.java:1812)
    at org.hibernate.loader.Loader.doQuery(Loader.java:697)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
    at org.hibernate.loader.Loader.doList(Loader.java:2232)
    ... 28 more
Caused by: java.net.SocketException: Socket closed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:135)
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:104)
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73)
    at org.postgresql.core.PGStream.ReceiveChar(PGStream.java:259)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1182)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:194)
    ... 36 more

What is the correct way to do this task?

P.S. I know that the design is far from perfect, but I just curious how to achieve the goal even if it worth to redesign the system and avoid the problem.


The problem may be related to the following:

  • Hibernate Sessions are not thread-safe
  • Spring-managed transactions are thread-bound

So, I guess each thread should start its own transaction (e.g. with TransactionTemplate) and obtain its own Session via SessionFactory.getCurrentSession(). But note that in this case the whole operation would be not transactional.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜