Как правильно смешать Hibernate и Swing? - PullRequest
4 голосов
/ 18 июня 2010

У меня есть несколько вопросов о взаимодействии с Hibernate:

  1. Использую ли я openSession или getCurrentSession (без jta, thread вместо)?
  2. Как мне смешивать сеансовые операциис графическим интерфейсом Swing?Хорошо ли иметь что-то вроде следующего кода в классе JavaBean?

    public void actionPerformed(ActionEvent event) {
        // session code
    }
    
  3. Могу ли я добавить методы в свои сущности, содержащие запросы HQL, или это плохая практика?Например:

     // This method is in an entity MyOtherEntity.java class
     public int getDuration(){
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        int sum = (Integer) session.createQuery("select sum(e.duration) as duration from MyEntity as e where e.myOtherEntity.id=:id group by e.name").
            .setLong("id", getId());
            .uniqueResult();
        return sum;
     }
    

Как я могу сделать это лучше и элегантнее?

ОБНОВЛЕНИЕ Широко используется практикакласс обслуживания / дао для достижения операции CRUD нашего класса сущностей.Но почему это хорошо?Почему я должен написать класс для каждого моего объекта, чтобы управлять им?Где реальное преимущество?

ОБНОВЛЕНИЕ 2 Класс обслуживания является шаблоном DAO?Что это значит? Артур Рональд Ф. Д. Пример хранилища Гарсии - это шаблон DAO, это то, что называется "сервисным уровнем"?

1 Ответ

1 голос
/ 18 июня 2010

Если вы хотите полагаться на простой Hibernate API , вы можете использовать слой Service, потому что

  • Используется вариант использования
  • Разграничить границы транзакции

Таким образом, вы можете создать AccountService, например,

public static path.to.HibernateUtil.getSessionFactory;

public class AccountService {

    public void withdraw(Integer accountNumber, BigDecimal amount) throws Exception {
        /**
          * Here you set up Transaction boundaries
          */
        getSessionFactory().getCurrentSession().beginTransaction();

        // Some actions goes here

        getSessionFactory().getCurrentSession().getTransaction().commit();
    }

}

Обычно вам требуется репозиторий при выполнении какого-либо действия на уровне службы. Вы можете думать о хранилище как о поставщике данных и о хранилище . Здесь вы можете увидеть, как я реализую свой репозиторий.

Если вы хотите обслуживаемый и читаемый HQL-запрос , я советую вам экстернализовать ваши HQL-запросы в многострочном и внешнем XML-файле

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <query name="GIFT_CARDS_WITH_BUYER">
        <![CDATA[
            from 
                GiftCard c
            left join fetch 
                c.buyer
            where
                c.recipientNotificationRequested = 1
       ]]>
    </query>
    <query name="GIFT_CARDS_WITHOUT_NO_RELATIONSHIP">
        <![CDATA[
            from 
                GiftCard
        ]]>
    </query>
</hibernate-mapping>

Так что внутри вашего Swing GUI Event вы можете называть свой сервисный слой как

public void actionPerformed(ActionEvent event) {
    // Some related Swing GUI actions goes here (retrieve User input, validate data and so on...)

    accountService.withdraw(accountNumber, new BigDecimal(amount));
}

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

public class Account {

   public void doSomething(AccountRepository repository) {
       // code goes here
   }

}

Может быть, вы хотите увидеть это Тема

Советую вам взглянуть на Java Persistence с книгой Hibernate, глава 9 (Работа с объектами). ATT : внимательно прочитайте

UPDATE

Почему хорошо иметь сервисный слой?

Прежде всего

  • Это управляемый прецедент (рисует, что должно делать ваше приложение)

Второй из всех

  • Разграничивает границы транзакций

Предположим, здесь идет ваш уровень обслуживания

public class MyService {

    public void doSomething() {
        getSessionFactory().beginTransaction();

        // A POJO doing some operation

        // Other POJO doing other operation

        // Another POJO doing another operation

        getSessionFactory().getTransaction().commit();
    }

}

Обратите внимание, что вы просто определяете одну границу транзакции вместо того, чтобы определять каждую внутри каждого POJO. И еще, что случится, если ваше бизнес-правило внутри вашего Swing GUI нужно будет использовать внутри другого компонента. Будете ли вы использовать Ctrl-C + Ctrl-V ???

...