简体   繁体   English

JSON 映射问题:可能对 session 进行非线程安全访问

[英]JSON mapping problem: possible non-threadsafe access to the session

I am facing a problem due which is unknown to me, can you one have faced this problem?我面临一个我不知道的问题,你能遇到这个问题吗?

JSON mapping problem: <package>ApiResponse["data"]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: possible non-threadsafe access to the session (through reference chain: <package>.ApiResponse["data"])

I have a standard API response pojo.我有一个标准的 API 响应 pojo。 Which I return every time with ResponseEntity.我每次都用 ResponseEntity 返回。 Everything is working fine, but sometimes I got that above error.一切正常,但有时我得到了上述错误。 I don't why this error occurred.我不知道为什么会发生这个错误。

I got the below log from console我从控制台获得了以下日志

an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: possible non-threadsafe access to the session

org.hibernate.AssertionFailure: possible non-threadsafe access to the session

I think you are trying to share same Hibernate session within multiple threads.我认为您正在尝试在多个线程中共享相同的 Hibernate session 。 That's illegal.那是违法的。

Hibernate Sessions are not thread-safe whereas Hibernate SessionFactory is thread-safe. Hibernate 会话不是线程安全的,而 Hibernate SessionFactory 是线程安全的。

So, make a separate DAO layer.因此,制作一个单独的 DAO 层。 Create single sessionfactory object and share it among the DAO classes.创建单个 sessionfactory object 并在 DAO 类之间共享。

Get a session for a single-threaded DB operation and close the session in that thread.为单线程数据库操作获取 session 并关闭该线程中的 session。

For example:例如:

@Repository
public class DAO {

    @Autowired
    private SessionFactory sessionFactory;

    public class performDBOperation(Object obj) {
      Session session = sessionFactory.currentSession();
      session.save(obj);
      session.close(); 
    }

}

Now, I have looked at your github code.现在,我查看了您的 github 代码。

I saw the code Exec.java我看到了代码 Exec.java

@Service
public interface Exec {

    @Async
    @Transactional
    public void run();
}

This is incorrect.这是不正确的。

Updated:更新:

public interface Exec {

    public void run();
}

Update ExecImpl to this:将 ExecImpl 更新为此:

@Service
public class ExecImpl implements Exec {

    @Autowired
    private ExecDAO execDAO;

    @Override
    @Async
    @Transactional
    public void run() {
       // example : create an object to save it.
       Object object = ...; 
       execDAO.saveItem(object);
    }
}

Create DAO layer:创建 DAO 层:

Suppose ExecDAO interface and implementation ExecDAOImpl :假设ExecDAO接口和实现ExecDAOImpl

 public interface ExecDAO {

        public void saveItem(Object obj);

        // keep here abstract method to perform DB operation 
 }

    @Repository
    public class ExecDAOImpl implements ExecDAO {

        @Autowired
        private SessionFactory sessionFactory;

        @Override
        public void saveItem(Object obj) {
          Session session = sessionFactory.currentSession();
          session.save(obj);
          session.close(); 
        }
    }

Looking at the code at the link you shared in the comment, I think that查看您在评论中共享的链接中的代码,我认为

@Async
@Transactional

is a dangerous thing.是一件危险的事情。 I would suggest you to extract a method to do the transactions and try what I mean is that,我建议您提取一种方法来进行交易并尝试我的意思是,

interface ExecImpl{
  @Async
  void run(){
     someThingElse.doTransaction();
  }
}

interface SomeThingElse{
  @Transactional
  void doTransaction();
}

I am still not convinced this will help you.我仍然不相信这会对你有所帮助。 But this is something you can try.但这是你可以尝试的。

I would also suggest to use readonly transactions for getting data and not have a single transaction for all purposes.我还建议使用readonly事务来获取数据,而不是为所有目的使用单个事务。

This blog explains why its not good to use these two annotations together whether on a class or on an interface此博客解释了为什么在 class 或接口上同时使用这两个注释不好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM