Comment puis-je mélanger Hibernate et Swing dans une bonne manière
-
28-09-2019 - |
Question
J'ai quelques questions sur l'interaction avec Hibernate:
- Dois-je utiliser openSession ou getCurrentSession (sans JTA, fil à la place)?
-
Comment puis-je mélanger les opérations de session avec l'interface graphique Swing? Est-ce bien avoir quelque chose comme le code suivant dans une classe JavaBean?
public void actionPerformed(ActionEvent event) { // session code }
-
Can I méthodes d'ajouter à mes entités qui contient des requêtes HQL ou est-ce une mauvaise pratique? Par exemple:
// 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; }
Comment puis-je faire cela d'une manière meilleure et élégante?
UPDATE Une pratique largement utilisée est de faire une classe de service / dao pour assurer un fonctionnement CRUD de notre classe d'entités. Mais pourquoi est-ce bon? Pourquoi dois-je écrire une classe pour chaque mes entités pour le gérer? Où est l'avantage réel?
MISE À JOUR 2 La classe de service est un modèle de DAO? Qu'est-ce que ça veut dire? est un modèle de DAO, est-ce que l'on appelle une « couche de service »?
La solution
Si vous voulez appuyer sur API Hibernate simple vous pouvez utiliser une couche de service parce que
- Il est conduit cas d'utilisation
- Délimiter les limites de transaction
Vous pouvez créer un AccountService, par exemple, comme
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();
}
}
Vous devez généralement un dépôt lorsque vous effectuez une action dans votre couche de service. Vous pouvez penser référentiel en tant que fournisseur de données et de stockage . ici peut voir comment je mets en œuvre mon dépôt.
Si vous voulez un maintenable et lisible HQL requête , je vous conseille de externalisez vos requêtes HQL dans un fichier xml multline et extériorisée
<?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>
GUI dans votre swing de l'événement, vous pouvez appeler votre couche de service comme
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));
}
Et ce n'est pas une bonne idée d'utiliser la persistance des actions à l'intérieur de votre entité. Si vous devez effectuer la persistance des problèmes liés à l'intérieur de votre entité, je pense qu'il vaut mieux que vous passez votre dépôt en tant que paramètre à votre entité
public class Account {
public void doSomething(AccountRepository repository) {
// code goes here
}
}
Peut-être que vous voulez voir cette discussion
je vous conseille Jetez un oeil à Java Persistence avec le livre Hibernate, chapitre 9 (travail avec des objets). ATT : lire attentivement
UPDATE
Pourquoi est bon avoir une couche de service?
D'abord
- Il est Cas d'utilisation conduit (Il dessine ce que votre application devrait faire)
Deuxièmement
- déterminer les limites de transaction
Supposons ici va votre couche de service
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();
}
}
Avis vous suffit de définir une limite de transaction au lieu de définir chacun à l'intérieur de chaque POJO. Et plus, ce qui se passe si votre règle d'affaires dans votre interface graphique swing besoin d'être utilisé à l'intérieur d'autres composants. Utiliserez-vous un Ctrl-c + Ctrl-v ???