2010-07-13 4 views
3

Je suis nouveau à JSF et je me demande si j'ai bien compris. Disons que j'ai un simple CMS qui permet d'écrire des pages.comment éviter la duplication de code modèle avec JSF et JPA

D'abord, je définir une entité JPA appelé Page:

@Entity 
public class Page { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column 
    private Long id; 

    @Column private String title; 

    @Column private String content; 

    // getters & setters ... 

} 

Ensuite, je voudrais en vue de créer la page-s. Pour cela, il semble que j'ai besoin d'un bean page de quelque sorte. Pour l'instant je me suis occupé des choses comme ça:

@Model 
public class PageBean { 

    private Page page = new Page(); 

    public String getTitle() { 
     return page.getTitle(); 
    } 

    public void setTitle(String title) { 
     page.setTitle(title); 
    } 

    // rest of properties & getters & setters ... 

    public void save() { 
     // persist using EntityManager 
    } 
} 

Ma question est la suivante: étant donné que mon modèle d'entité JPA et le modèle que je veux utiliser dans les vues sont la plupart du temps exactement la même chose, est-il façon d'éviter d'avoir à créer un lot de getters & setters dans le PageBean? J'ai lu quelque part que vous ne devriez pas utiliser le même bean que l'entité JPA et le bean modèle JSF (parce que JSF fait des appels répétés aux getters qui peuvent affecter JPA), mais je me demande s'il n'y a pas un moyen plus simple éviter ce genre de duplication de code. Surtout quand vous avez une application avec un grand modèle et dans de nombreux cas ne nécessitent pas de spécial dans les beans de vue, il semble que cela peut devenir assez lourd.

Répondre

4

[...] étant donné que mon modèle d'entité JPA et le modèle que je veux utiliser dans les vues sont la plupart du temps exactement les mêmes, existe-t-il un moyen d'éviter de créer un lot de getters & setters dans le PageBean?

Je ne vois pas le point d'utiliser un emballage autour d'une entité et l'ajout d'une telle couche est en effet double emploi. Utilisez simplement l'entité de votre page JSF. Oui, cela introduit une sorte de couplage entre la vue et le domaine mais, en général, modifier la base de données signifie généralement ajouter ou supprimer des champs sur la vue. En d'autres termes, je n'achète pas l'argument «découplage» et j'ai écrit suffisamment de couches supplémentaires, de code de mappage, de code standard, etc. pour favoriser l'approche simple lorsque c'est possible.

je lu quelque part que vous ne devriez pas utiliser un même grain que l'entité JPA et du haricot modèle JSF (parce que JSF ne les appels répétés à getters qui peuvent affecter JPA)

Je serais intéressé si vous pourrait fournir une référence mais une classe wrapper (déléguer des appels à l'entité) ne va rien changer s'il y a un problème quelque part.

Juste au cas où, quelques ressources supplémentaires:

2

Ce n'est pas une duplication de code. Il n'y a pas d'algorithme dupliqué. La logique métier est toujours au même endroit.

Ce que fait votre bean, c'est simplement de connecter le View au domaine. C'est bien, ça fait partie du pattern MVC.

Si vous utilisiez votre entité JPA en tant que bean backing, vous briseriez le modèle MVC. Par exemple, si un jour au lieu d'afficher un plain String vous devrez ajouter un Date à ce String parce que la vue l'exige (c'est-à-dire les exigences d'interface), allez-vous écrire cette logique de vue dans la classe JPA? Cela n'a aucun sens, en mélangeant le modèle de domaine et le modèle de vue.

D'autre part, pourquoi la vue doit savoir comment le domaine est implémenté? Que faire si le format des valeurs de domaine change? (Par exemple, vous enregistrez une chaîne d'horodatage au lieu d'une classe de date dans la base de données pour des raisons de performances). Tout ce que vous auriez à faire est de simplement réécrire la méthode dans le bean backing, cela prendrait l'horodatage et l'adapterait à une Date pour que tout fonctionne comme avant. Juste un changement en dehors de la classe JPA. Si vous l'aviez dans la classe JPA, vous finiriez par conserver les deux logiques dans une seule classe (logique d'interface et logique de domaine). Et si vous vouliez développer une nouvelle vue (par exemple pour une version mobile), que se passe-t-il? Allez-vous ajouter encore plus de code à la classe JPA? Il vaudrait mieux garder le JPA tel qu'il était et créer un autre Bean (qui étend un bean commun pour les deux vues) pour la version mobile.

Si après tout cela, vous voulez toujours pas écrire les accesseurs, vous pouvez le faire

#{myBean.page.title} 

tout ce que vous avez besoin est un getPage() à l'intérieur du grain de support.

+0

Le '# {myBean.page.title}' est exactement ce qu'il faut et serait déjà suffisante réponse entière à sa posséder. La plupart des démarreurs JSF/EL ne sont pas conscients de la possibilité de "fondre" les getters et pensent donc qu'il est nécessaire d'aplatir/marteler les entités dans le bean géré. – BalusC

+0

Je sais ce qu'il voulait depuis le début. Mais je pense que vous devriez être en mesure d'approfondir une fois que vous êtes conscient de ce que vous faites et de ses implications. C'est pourquoi j'ai écrit la partie "disclaimer" avant la réponse. J'utilise beaucoup de profondeur dans les backing beans, mais quand il s'agit d'accéder aux champs dans le modèle de domaine, j'y pense deux fois. – pakore

Questions connexes