#java #multithreading #hibernate-entitymanager
#Ява #многопоточность #режим гибернации-entitymanager
Вопрос:
Я создаю приложение для нескольких клиентских и 1 серверного сокета, каждый клиентский сокет работает с потоком. Когда клиент связывается с другим клиентом и что-то делает, оба отправляют запрос на сервер для обновления текущего пользователя, и каждый поток, ответственный за каждого клиента, будет обновляться в базу данных по UserService
классам одновременно. Это приведет к тому, что транзакция получит ошибку.
public class UserService { EntityManagerFactory entityManagerFactory; @PersistenceContext EntityManager entityManager; EntityTransaction transaction; public UserService() { // turn off entityManagerFactory = Persistence.createEntityManagerFactory("default"); entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); } public void updateUser(User user) { try { transaction.begin(); entityManager.merge(user); transaction.commit(); } catch (Exception e) { e.printStackTrace(); } } }
ПРИМЕЧАНИЕ: класс потока, управляющий сокетом, который я объявил статическим UserService
, если я не использую статический класс, я получаю следующую ошибку [SQLITE_BUSY] The database file is locked (database is locked)
public class EchoThread extends Thread { protected Socket socket; BufferedReader in; BufferedWriter out; private static UserService userService = new UserService();; public EchoThread(Socket clientSocket) { this.socket = clientSocket; } public void run() { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); line = in.readLine(); // do something with current user userService.updateUser(user); } }
Ошибка
javax.persistence.RollbackException: Error while committing the transaction at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:81) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104) at Services.UserService.updateUser(UserService.java:25) at Utils.EchoThread.run(EchoThread.java:284) Caused by: java.lang.NullPointerException: Cannot invoke "java.util.Map$Entry.getValue()" because "me" is null ERROR: HHH000099: 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 nonthreadsafe access to session
Как я могу его обновить
Комментарии:
1. Диспетчер сущностей не является потокобезопасным. Каждая нить нуждается в своей собственной.
2. Спасибо, в каждом потоке мне нужно создавать новый
UserService
класс вместо статического класса, верно ?3. если я не использую статический класс, я получаю следующую ошибку [SQLITE_BUSY] Файл базы данных заблокирован (база данных заблокирована)
4. Вам нужно поделиться
EntityManagerFactory
своим .