2011-09-07 4 views
3

Я разработал довольно большое приложение CRUD, используя базу данных MYSQL Database и Swing Application и javax.persistence. Мой вопрос: как лучше всего управлять моими транзакциями с учетом javax.persistence.Entitymanager? В настоящее время у меня есть один экземпляр менеджера Entity, который находится в классе Application. Он передается на все запрашивающие страницы, которые, в свою очередь, используют его для сохранения и объединения объектов. Я запускаю транзакцию при запуске приложения и фиксирую (и перезапускаю) каждый раз, когда производится изменение. Это правильно? или должен ли я иметь отдельный диспетчер Entity Manager для каждого компонента/страницы? Когда мне следует совершать? Все эти вопросы возникли сейчас, потому что я недавно начал получать исключения из этого типа: java.sql.SQLException: превышено время ожидания блокировки; попробуйте перезапустить транзакцию Код ошибки: 1205 , который заставил меня поверить, что я делаю что-то не так в моем управлении транзакциями с базами данных ....Как управлять транзакциями базы данных с использованием Entity Manager в относительно большом приложении?

Заранее благодарим за любую помощь, которую вы можете мне дать!

ответ

4

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

В общем, рекомендуемом способе управления сделкой заключается в следующем:

EntityManager em = EMF.getEM(); 
    em.getTransaction().begin(); 
    // your persist, merge code goes here 
    em.getTransaction().commit(); 
    em.close(); 

Класс EMF это один:

public class EMF { 
    private static EntityManagerFactory emf; 
    static { 
     emf = Persistence.createEntityManagerFactory("MyEMF"); 
    } 
    public static EntityManager getEM(){ 
     return emf.createEntityManager(); 
    } 
} 

Таким образом, ваша транзакция только блокирует базу данных во время ваш код продолжения выполняется. Обратите внимание, что использование класса EMF для вашего менеджера объектов создается только один раз. Это хорошо, потому что его создание является дорогостоящим. Однако, как только он создается, создание экземпляра менеджера объектов очень дешево. Это short tutorial объясняет это довольно хорошо.

+0

Большое вам спасибо! наконец-то кто-то объяснил мне этот момент ... один вопрос: почему вы делаете старую emf в вашем примере? ОК, чтобы сделать его частным членом EMF? В моем случае здание emf несколько сложнее, поэтому я предпочитаю делать это внутри функции init моего класса приложения. Я думал о следующем: открытый класс EMF { private EntityManagerFactory emf; static { emf = Persistence.createEntityManagerFactory ("MyEMF"); } public static EntityManager getEM() { return emf.createEntityManager(); } } – Vova

+0

Ну, основная причина, связанная с созданием emf static, заключается в том, что метод getEM также является статическим, и невозможно связать нестатическое поле со статическим контекстом. Поскольку я не собираюсь создавать экземпляр класса EMF, было бы гораздо разумнее сделать статический метод getEM. Если вы не хотите, чтобы emf статичное поле, вам также необходимо сделать getEM нестатичным. – joanlofe