Como posso misturar o hibernato e balançar de uma maneira boa
-
28-09-2019 - |
Pergunta
Tenho algumas perguntas sobre a interação com o Hibernate:
- Eu uso o OpenSession ou GetCurrentSession (sem JTA, Thread)?
Como faço para misturar operações de sessão com a GUI do swing? É bom ter algo como o código a seguir em uma aula de Javabean?
public void actionPerformed(ActionEvent event) { // session code }
Posso adicionar métodos às minhas entidades que contêm consultas HQL ou isso é uma prática ruim? Por exemplo:
// 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; }
Como posso fazer isso de uma maneira melhor e elegante?
ATUALIZARUma prática amplamente usada é fazer uma classe de serviço/DAO para alcançar a operação CRUD de nossa classe de entidades. Mas por que isso é bom? Por que tenho que escrever uma aula para cada uma das minhas entidades para gerenciá -la? Onde está a verdadeira vantagem?
Atualização 2A classe de serviço é um padrão DAO? O que isto significa?Exemplo de repositório de Arthur Ronald FD Garcia É um padrão DAO, é isso que é chamado de "camada de serviço"?
Solução
Se você quiser confiar na API de hibernação simples você pode usar uma camada de serviço porque
- É usar case orientado
- Limites da transação delimit
Então você pode criar um serviço de conta, por exemplo, como
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();
}
}
Você geralmente precisa de um repositório ao executar alguma ação dentro da camada de serviço. Você pode pensar em repositório Como provedor de dados e armazenamento. Aqui Você pode ver como eu implemento meu repositório.
Se você quiser uma consulta HQL sustentável e legível, Eu aconselho que você externalize suas consultas HQL em um arquivo XML multineado e externalizado
<?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>
Então, dentro do seu evento GUI Swing, você pode chamar sua camada de serviço como
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));
}
E não é uma boa ideia usar ações de persistência dentro de sua entidade. Se você precisar realizar problemas relacionados à persistência dentro de sua entidade, acho que é melhor você passar seu repositório como parâmetro para sua entidade
public class Account {
public void doSomething(AccountRepository repository) {
// code goes here
}
}
Talvez você queira ver isto Fio
Conselho você dar uma olhada na persistência de Java com o livro de hibernados, capítulo 9 (trabalhando com objetos). Att: Leia cuidadosamente
ATUALIZAR
Por que é bom ter uma camada de serviço?
Em primeiro lugar
- É usado no caso (ele desenha o que seu aplicativo deve fazer)
Segundo de todos
- Ele delimita os limites da transação
Suponha que aqui seja sua camada de serviço
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();
}
}
Observe que você apenas define um limite de transação em vez de definir cada um dentro de cada pojo. E mais, o que acontece se sua regra de negócios dentro de sua GUI swing precisa ser usada dentro de outro componente. Você vai usar um Ctrl-C + Ctrl-V ???