Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JPA и транзакции, Где делать commit() ? 
:(
    Опции темы
Asal
Дата 21.8.2008, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 288
Регистрация: 26.12.2006
Где: Минск

Репутация: 4
Всего: 7



Возник вопрос аналогичный вопросу из сереала.
где же открывать транзакцию и делать commiy() ?

Принцип почти такой же как и у Infinite из сереала.

Сначало инициализируется класс Controller
Код

contextLoader = new ContextLoader();
WebApplicationContext context = contextLoader.initWebApplicationContext(servletContextEvent.getServletContext());
controller = Controller.getInstance();
controller.init(context);

В классе Controller инициализурую менеджеров
Код

  public void init(WebApplicationContext context) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("JetscartUnit");
    entityManager = emf.createEntityManager();

    registry = (Registry) context.getBean(Registry.BEAN_NAME);
    initManagers();
  }
  public void initManagers() {
    Collection<Manager> c = registry.getManagers().values();
    for (Manager m : c) {
      m.init();
    }
  }

В Registry хранятся менеджеры
Код

package my.shop.core;

import java.util.HashMap;

public class Registry {
  public static final String BEAN_NAME = "registry";

  private HashMap<String, Manager> managers = new HashMap<String, Manager>();

  public Manager getManager(String name) {
    return managers.get(name);
  }

  public HashMap<String, Manager> getManagers() {
    return managers;
  }

  public void setManagers(HashMap<String, Manager> managers) {
    this.managers = managers;
  }

  public void clear() {
    managers.clear();
  }
}

А уже в менеджерах выполню функции insert/update/delete
Код

package my.shop.user;

import my.shop.core.ResultStatus;
import my.shop.core.BasicManager;
import my.shop.core.Manager;

import javax.persistence.Query;
import javax.persistence.NoResultException;


public class UserManager extends BasicManager implements Manager {
  public static final String BEAN_NAME = "usersManager";

  public UserManager() {
    super();
  }

  public void init() {
    System.out.println("UserManager Init()");
    super.init();
  }

  public void destroy() {
    super.destroy();
  }

  public UserEntity login(String username, String password) throws NoResultException {
    Query query = entityManager.createNamedQuery("loginUser");
    query.setParameter("username", username);
    query.setParameter("password", password);
    return (UserEntity) query.getSingleResult();
  }

  public ResultStatus insert(UserEntity user) {
    entityManager.getTransaction().begin();
    Query query = entityManager.createNamedQuery("containsUser");
    query.setParameter("username", user.getUsername());
    if (!query.getResultList().isEmpty() || entityManager.contains(user)) {
      System.out.println("user exist");
      return ResultStatus.newErrorResult();
    }
    entityManager.persist(user);
    entityManager.getTransaction().commit();
    return ResultStatus.newOkResult();
  }

  public ResultStatus update(UserEntity user) {
    entityManager.getTransaction().begin();
    entityManager.flush();
    entityManager.refresh(user);
    entityManager.getTransaction().commit();
    return ResultStatus.newOkResult();
  }
  public ResultStatus delete(UserEntity user) {
    entityManager.getTransaction().begin();
    entityManager.flush();
    entityManager.remove(user);
    entityManager.getTransaction().commit();
    return ResultStatus.newOkResult();
  }
}

Друзья помогите решить задачу.
Где открывать транзакцию?

Исходный код во вложении.

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  src.zip 5,07 Kb


--------------------
PM MAIL ICQ   Вверх
ivg
Дата 21.8.2008, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 32
Всего: 81



Цитата(Asal @  21.8.2008,  17:37 Найти цитируемый пост)
Где открывать транзакцию?
 Какую транзакцию? Строки 35, 43, 48, 51, 55, 58 последнего листинга (класс UserManager)? Не? Не то? Тогда что?

PM MAIL   Вверх
mbasil
Дата 21.8.2008, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 9
Всего: 13



О чем  вопрос? Вы уже и открываете, и закрываете следующими вызовами:
Код

entityManager.getTransaction().begin();
...
entityManager.getTransaction().commit();


По сути у Вас каждая транзакция состоит из одной операции в одном методе.

Это сообщение отредактировал(а) mbasil - 21.8.2008, 19:33
PM MAIL   Вверх
Asal
Дата 21.8.2008, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 288
Регистрация: 26.12.2006
Где: Минск

Репутация: 4
Всего: 7



Цитата(ivg @  21.8.2008,  18:48 Найти цитируемый пост)
Какую транзакцию? Строки 35, 43, 48, 51, 55, 58 последнего листинга (класс UserManager)? Не? Не то? Тогда что?

Тем кто читал сериал я думаю будет более или менее понятно о чем речь.
А для тех кто не читал попытаюсь объяснить.

Допустим на страничке мы пытаемся изменить данные юзера, делаем запрос.
В классе UserController обрабатываем этот запрос
Код

  public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
    UserManager userManager = (UserManager) com.jetscart.core.Controller.getInstance().getRegistry().getManager(UserManager.BEAN_NAME);
    UserEntity user = new UserEntity();
//... что-то делаем
    System.out.println("insert user");
    userManager.update(user);
    return new ModelAndView();
  }

В классе UserManager обновляем в базе
Код

  public ResultStatus update(UserEntity user) {
    entityManager.getTransaction().begin();
    entityManager.flush();
    entityManager.refresh(user);
    entityManager.getTransaction().commit();
    return ResultStatus.newOkResult();
  }

Если приходит только один запрос, то все нормально, но когда одну запись о юзере пытаются поменять сразу двое (и более),
возникает проблема... И начинают сыпаться разного рода ошибки
например
Код

21.08.2008 19:46:10 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet test threw exception
java.lang.IllegalStateException: Transaction already active
    at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:35)
    at com.jetscart.user.UserManager.update(UserManager.java:55)
    at com.jetscart.user.UserController.handleRequest(UserController.java:25)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

Вот и вопрос где, как, когда открывать транзакции, делать commit и т.д.

P.S.
здесь мне посоветовали почитать книгу Мартина Фаулера "Архитектура корпоративных программных приложений"
Там по-моему глава есть про Web приложения.


--------------------
PM MAIL ICQ   Вверх
ivg
Дата 21.8.2008, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 32
Всего: 81



Проблема не в транзакциях, а в расшареном между потоками javax.persistence.EntityManager
Цитата

A EntityManagerFactory is an expensive-to-create, threadsafe object intended to be shared by all application threads. It is created once, usually on application startup.

An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process, a single unit of work, and then discarded. An EntityManager will not obtain a JDBC Connection (or a Datasource) unless it is needed, so you may safely open and close an EntityManager even if you are not sure that data access will be needed to serve a particular request. (This becomes important as soon as you are implementing some of the following patterns using request interception.)
 Отсюда Ссылка для Hibernate, возможно для других провайдеров JPA это не так, надо смотреть спецификацию.

Это сообщение отредактировал(а) ivg - 21.8.2008, 20:23
PM MAIL   Вверх
Asal
Дата 22.8.2008, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 288
Регистрация: 26.12.2006
Где: Минск

Репутация: 4
Всего: 7



Может кто-то посоветует framework для работы с транзакциями ?


--------------------
PM MAIL ICQ   Вверх
alexadr
Дата 22.8.2008, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 25.9.2006

Репутация: нет
Всего: 4



Я бы предложил оборачивать все действия с персистентными объектами, - сессионными бинами, при этом у соответствующих методов достаточно будет указать параметр(Аннотацию) для тразкации. А EntityManager получать в бине с помощью dependency injection.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0716 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.