2009-10-18 6 views
5

nouveau au printemps et ici @stackoverflowSpring @Transactional fusion et persisteront question

Je construis un inventaire autonome & application de suivi des ventes (Apache Pivot/Spring/JPA/Hibernate/MySQL) pour une entreprise de distribution . Jusqu'à présent, je pense que tout est CRUD, donc je prévois d'avoir une classe de base avec tout @Transactional.

Ensuite, j'ai eu un problème avec ma méthode générique de sauvegarde. Est-ce que la méthode de persistance et de fusion de l'EntityManager de Spring a une différence? J'ai essayé de courir et j'ai appelé l'enregistrement pour l'insertion et la mise à jour et ça a bien fonctionné (je pense que le ressort actualise automatiquement l'entité chaque fois que j'appelle ma méthode de sauvegarde).

@Transactional 
public abstract class GenericDAO { 

    protected EntityManager em; 

// em [email protected]/setter 

    public void save(T t) { 
//  if (t.getId() == null) // create new 
//  { 
//   em.persist(t); 
//  } else // update 
//  { 
      em.merge(t); 
//  } 
    } 
} 

Et btw, ayant une telle configuration, je ne vais pas compromettre les performances? Comme appeler salesDAO.findAll() pour générer des rapports (qui n'a pas besoin d'être transactionnel, n'est-ce pas?).

merci !!!

Répondre

5

This SO question est une bonne discussion sur la persistance par opposition à la fusion, et la réponse acceptée l'explique plutôt bien. L'autre réponse renvoie également à un bon article de blog à ce sujet. Selon la première réponse en this other post, il semble qu'il serait possible d'appeler la fusion pour enregistrer et mettre à jour une entité, mais ce n'est pas ce que j'ai fait. Dans mes applications Spring/JPA, j'ai juste mes DAOs étendent JpaDaoSupport et utilisent le getJpaTemplate() de la façon suivante.

/** 
* Save a new Album. 
*/ 
public Album save(Album album) { 
    getJpaTemplate().persist(album); 
    return album; 
} 

/** 
* Update an existing Album. 
*/ 
public Album update(Album album) { 
    return getJpaTemplate().merge(album); 
} 
+0

Je suis l'invité le plus simple. Donc, si j'ai JpaDaoSupport et que j'en reçois une entité, les modifications seront automatiquement validées? Je pense que je vais avoir deux variantes de méthode d'enregistrement, une qui persiste et une qui appelle flush. Un commentaire à ce sujet? – thirdy

+0

Voulez-vous dire automatique comme engagé sans sauvegarde ou mise à jour? Si c'est le cas, je ne le pense pas, j'appelle simplement enregistrer sur une nouvelle entité ou mettre à jour sur une existante pour persister. Je n'ai jamais eu besoin d'appeler la méthode flush, mais mon accès à la base de données est assez simple pour une requête donnée. –

+0

Je vais devoir arrêter d'essayer le printemps pour l'instant. Juste curieux, comment les Grails améliorent-ils cela? Je n'aurai pas à rencontrer des problèmes comme ceux-ci dans Grails, n'est-ce pas? – thirdy

4

Le link à l'autre question SO Kaleb affiché ne fait un bon travail de couvrir les différences et gotchas de persister() vs fusion(). Cependant, j'ai toujours implémenté mes classes Dao avec une méthode save() qui appelle uniquement merge() pour gérer à la fois les insertions et les mises à jour, et je n'ai jamais rencontré les getchases persist() vs merge().

En ce qui concerne la performance et les méthodes transactionnelles: En utilisant @Transactional sur les méthodes qui sont en lecture seule les opérations ne seront pas vraiment l'impact des performances, bien que je préfère utiliser les annotations au niveau de la méthode que je peux facilement dire quelles méthodes sont mises à jour et qui sont des lectures. Vous pouvez le faire en définissant l'attribut readOnly sur l'annotation @Transactional.

Si vous suivez une convention de nommage dans vos méthodes (toute méthode de lecture commence toujours par getXXX), vous pouvez également utiliser la syntaxe poincut dans votre fichier de configuration Spring pour effectuer automatiquement cette différenciation:

<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <tx:attributes> 
     <tx:method name="get*" read-only="true"/> 
     <tx:method name="*"/> 
    </tx:attributes> 
    </tx:advice> 

Voir la Spring documentation on Transactions pour plus d'informations.

En outre, je place généralement les attributs @Transactional un niveau au-dessus de mes classes Dao, dans une couche de service. Les méthodes sur les classes Dao sont alors des opérations de base de données distinctes pour chaque appel de méthode, tandis que les méthodes de service peuvent effectuer une seule validation/restauration pour une série de mises à jour.

+0

merci de répondre. Je pense que je m'en tiendrai au JPA pur (je n'ai pas vraiment besoin de flexibilité) – thirdy