JSON проблема с отображением: возможен не-потокобезопасный доступ к сеансу - PullRequest
1 голос
/ 11 апреля 2020

Я столкнулся с проблемой из-за неизвестной мне проблемы. Может, вы сталкивались с этой проблемой?

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"])

У меня есть стандартный ответ API pojo. Который я возвращаю каждый раз с ResponseEntity. Все работает нормально, но иногда я получаю эту ошибку выше. Я не знаю, почему произошла эта ошибка.

Я получил приведенный ниже журнал из консоли

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

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

Глядя на код по ссылке, которой вы поделились в комментарии, я думаю, что

@Async
@Transactional

- опасная вещь. Я бы предложил вам извлечь метод для выполнения транзакций и попробовать то, что я имею в виду:

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

interface SomeThingElse{
  @Transactional
  void doTransaction();
}

Я все еще не уверен, что это поможет вам. Но это то, что вы можете попробовать.

Я бы также предложил использовать readonly транзакции для получения данных и не иметь единой транзакции для всех целей.

Этот блог объясняет, почему не стоит использовать эти две аннотации вместе в классе или на интерфейсе

1 голос
/ 11 апреля 2020

Я думаю, что вы пытаетесь разделить один и тот же сеанс Hibernate в нескольких потоках. Это незаконно.

Сеансы Hibernate не являются поточно-ориентированными, тогда как Hibernate SessionFactory является поточно-ориентированным.

Итак, создайте отдельный слой DAO. Создайте отдельный объект сеанса и поделитесь им с классами DAO.

Получить сеанс для однопоточной операции с БД и закрыть сеанс в этом потоке.

Например:

@Repository
public class DAO {

    @Autowired
    private SessionFactory sessionFactory;

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

}

Теперь я посмотрел ваш github код.

Я видел код Exe c. java

@Service
public interface Exec {

    @Async
    @Transactional
    public void run();
}

Это неверно.

Обновлено:

public interface Exec {

    public void run();
}

Обновите 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);
    }
}

Создать слой DAO:

Предположим, 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(); 
        }
    }
...