Hibernate/JPA manyTomany with extra column

Publié le 25/05/2012, par Jean-Baptiste Cazaux dans Java, Tutoriel, Valtech | 2 Commentaires

Récemment j’ai refait un peu de JPA/Hibernate et j’ai eu besoin de mapper une relation many-to-many qui nécessite de stocker une information supplémentaire. Pour être concret, j’ai un objet Recette, un objet Ingredient et je souhaite associer une recette à un ingrédient. Ce qui est particulier dans mon cas c’est que j’ai envie de d’enregistrer en plus la quantité de cet ingrédient qui est utilisé dans ma recette de cuisine.

Rien de bien extraordinaire jusque là et je me souvenais avoir déjà géré ce genre de cas. Oui mais voilà, après quelques recherches sur les forums je n’ai trouvé aucune solution clé en main qui ne nécessite pas de parcourir les dizaines de commentaires et de les tester un à un.

Voici la solution que j’ai retenue, je suis bien sur ouvert à toute proposition permettant d’améliorer mon code ! Je ne présenterai ici que les mappings, je vous propose de retrouver l’intégralité des cas d’utilisations sur mon github (avec les Tests Unitaires et surtout le debug hibernate pour voir les requêtes qui passent).

L’idée générale est de découper le many to many en deux relations many-to-one/one-to-many avec l’utilsation d’un objet d’association qui va porter l’information que l’on souhaite rajouter (ici la quantité).

NB: je me sers de lombok pour générer les getter, setter et equals/hashcode de mes classes.

La classe Recipe:

package fr.valtech.many2many.domain;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
 
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
 
@Entity
@Table(name = "recipe")
@EqualsAndHashCode(of = { "id", "title" }, callSuper = false)
public class Recipe extends AbstractEntity {
 
  @Id
  @Column(name = "recipe_id")
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Getter
  @Setter
  private Integer id;
 
  @Getter
  @Setter
  private String title;
 
  @Getter
  @Setter
  @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.recipe", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set ingredients = new HashSet();
 
  public void addIngredient(RecipeIngredient i) {
    i.setRecipe(this);
    ingredients.add(i);
  }
}

La classe Ingredient:

package fr.valtech.many2many.domain;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
 
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
 
@Entity
@EqualsAndHashCode(of = { "id", "label" }, callSuper = false)
public class Ingredient extends AbstractEntity {
 
    @Id
    @Column(name = "ingredient_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Getter
    @Setter
    private Integer id;
 
    @Getter
    @Setter
    private String label;
 
}

La classe RecipeIngredient qui fait l’association:

package fr.valtech.many2many.domain;
 
import java.io.Serializable;
 
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;
 
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
 
@Entity
@Table(name = "recipe_ingredient")
@AssociationOverrides({
        @AssociationOverride(name = "pk.recipe", joinColumns = @JoinColumn(name = "recipe_id", insertable = false, updatable = false)),
        @AssociationOverride(name = "pk.ingredient", joinColumns = @JoinColumn(name = "ingredient_id", insertable = false, updatable = false)) })
@EqualsAndHashCode(of = { "pk", "amount" }, callSuper = false)
public class RecipeIngredient implements Serializable {
 
    @Getter
    @Setter
    @Column(nullable = false)
    private String amount;
 
    @Getter
    @Setter
    @EmbeddedId
    private RecipeIngredientId pk = new RecipeIngredientId();
 
    @Transient
    public Recipe getRecipe() {
        return getPk().getRecipe();
    }
 
    public void setRecipe(Recipe recipe) {
        getPk().setRecipe(recipe);
    }
 
    @Transient
    public Ingredient getIngredient() {
        return getPk().getIngredient();
    }
 
    public void setIngredient(Ingredient ingredient) {
        getPk().setIngredient(ingredient);
    }
 
    public RecipeIngredient() {
    }
 
    public RecipeIngredient(Ingredient ingredient, String amount) {
        setIngredient(ingredient);
        this.amount = amount;
    }
 
}

Et enfin la composite primary key de la classe d’association:

package fr.valtech.many2many.domain;
 
import java.io.Serializable;
 
import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
 
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
 
@Embeddable
@EqualsAndHashCode(of = { "recipe", "ingredient" }, callSuper = false)
public class RecipeIngredientId implements Serializable {
 
    @Getter
    @Setter
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Recipe recipe;
 
    @Getter
    @Setter
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Ingredient ingredient;
 
}

Les “astuces” que j’ai mis un moment à comprendre sont:

  • dans la classe RecipeIngredientId il faut absolument mettre les relations en LAZY pour éviter un stackOverFlow;
  • dans la classe Recipe, la relation OneToMany doit absolument comporter le orphanRemoval = true, sinon la mise à jour et la suppression des RecipeIngredient se passent mal !

Bon tout n’est pas parfait et il faut gérer quelques trucs “à la main”.
Il faut nécessairement persister en base explicitement l’ingrédient que l’on veut utiliser dans une recette que l’on souhaite elle-même persister.

    /**
     * Parcourt l'ensemble des ingrédient pour voir si ils existe déjà en base ou non.
     * @param recipe
     */
    private void reatachIngredients(Recipe recipe) {
 
        for (Iterator it = recipe.getRecipeIngredients()
                .iterator(); it.hasNext();) {
            RecipeIngredient ri = it.next();
            Ingredient ingredient = ri.getIngredient();
            if (ingredient.getId() != null && ingredient.getId() != 0) {
                Ingredient reference = getEntityManager().getReference(
                        Ingredient.class, ingredient.getId());
                ri.setIngredient(reference);
            } else {
                getEntityManager().persist(ingredient);
            }
        }
    }

Il faut écrire une requête JPQL pour récupérer la Recette dans son intégralité, si on veut par exemple la serialiser après (certaines relations avaient été mises en LAZY, notamment sur la PK).

        Query q = getEntityManager().createQuery(
                "select r from Recipe as r "
                        + "left join fetch r.recipeIngredients as ri "
                        + "left join fetch ri.pk as pk "
                        + "left join fetch pk.ingredient "
                        + "where r.id = :recipeId");
 
        q.setParameter("recipeId", recipeId);
 
        Recipe recipe = null;
        try {
            recipe = (Recipe) q.getSingleResult();
        } catch (NoResultException nre) {
            getLogger().info("no result found");
            return null;
        }

Le code complet ici: https://github.com/jbcazaux/many2many


Duchess France fête ses 2 ans

Publié le 21/05/2012, par Claude Falguiere dans Événements, Java | Ajouter un commentaire

Le 30 Mai, Duchess France fêtera ses 2 ans avec une soirée Trivial Java pour finir une année bien remplie. Au programme des jeux, des cadeaux, des connaissances techniques et beaucoup de bonne humeur.

La soirée aura lieu à l’ECE dans le 15ième. Vous pouvez vous inscrire via le nouveau site de Duchess France http://www.duchess-france.org/2eme-anniversaire-de-duchess-france/ .

Après avoir offert nos locaux l’année dernière, nous avons une fois de plus l’honneur de sponsoriser cet événement sympathique en offrant un modeste buffet.

Venez nous battre au questionnaire java, si vous l’osez ;-)


Venue de Bertrand Meyer le 9 Mai 2012

Publié le 21/05/2012, par Jocelyn Batton dans Valtech | 1 Commentaire

Comme indiqué lors du dernier post “Fréquence Valtech”, Valtech a eu le plaisir d’accueillir Bertrand Meyer, créateur du langage Eiffel dans son auditorium à Paris rue de Grenelle pour une conférence en soirée.

Pendants près de deux heures, plus de 100 personnes ont eu la chance de voir présentés les sujets suivants :

  • Types Abstraits de Données (ADT)
  • Héritage multiple
  • Conception par Contrats
  • Parallélisme
  • Tests automatiques
  • Cycle de vie logiciel

…et de terminer par des questions pendant une demi-heure.

Qualité technique, vécu historique et humour furent les maîtres mots de cette soirée au succès indéniable.

On ressortira tout de même frustré de cette présentation tant les concepts puissants mis en lumière auraient mérité chacun au moins l’ensemble de la soirée.

Mais il eut été alors impossible de présenter la méthodologie prônée par Eiffel dans sa globalité, indispensable à la compréhension de la démarche initiée par Bertrand Meyer.

Fort de ce constat, la mise en place d’évènements sur des domaines plus spécifiques, analysés avec bien plus de profondeur est à l’étude. Cette soirée ne devrait être qu’une mise en bouche…

La dynamique créée par cette soirée, a donné naissance au “Groupe des Eiffelistes Francophones” dont le rôle sera de promouvoir l’utilisation du langage/méthode dans les pays francophones. Il est accessible via cette adresse. Une de ses premières tâches sera la création d’un tutoriel pour débuter en Eiffel.


Fréquence Valtech n°6 : Interview de Bertrand Meyer

Publié le 21/05/2012, par Grégory Paul dans Événements, Fréquence Valtech, Valtech | 2 Commentaires

Dans ce 6ème épisode du podcast Fréquence Valtech, Jocelyn Batton et Eric Le Merdy ont l’honneur d’interviewer Bertrand Meyer, créateur du langage Eiffel et auteur du livre référence “Conception et programmation orientées objet” peu avant sa conférence en soirée à l’auditorium de Valtech le 9 Mai 2012.

Vous pouvez télécharger ce podcast au format ogg ou mp3 ou encore vous abonner via le flux rss dédié.

Voici les ressources évoquées pendant le podcast :

  • Origines du langage Eiffel
  • Types Abstraits de Données (ADT)
  • Commandes et Requêtes
  • Conception par Contrats
  • Place et différentes natures des tests dans le cycle de vie logiciel
  • Héritage multiple (notion de renommage de méthodes, surcharge)
  • Agents et MVC
  • Programmation concurrente

N’hésitez pas à nous faire part de vos retours par email à l’adresse <podcast-at-valtech.fr> ou alors via les commentaires ci-dessous.

Le thème musical provient de podcastthemes.


La puissance de Drupal en Entreprise – 25 mai à Paris – Valtech y sera, et vous ?

Publié le 16/05/2012, par Olivier Rodrigues dans Événements, Intégration, Valtech | Ajouter un commentaire

Valtech a le plaisir de vous inviter à l’événement de lancement d’Acquia en France le 25 mai à Paris.

Rejoignez-nous sur le stand Valtech et découvrez comment le CMS Drupal permet aux entreprises et aux administrationsd’innover et gagner en flexibilité afin de répondre aux exigences croissantes des clients.

Au programme
  • Vision et Futur de Drupal
  • Étude de cas client
  • Bonnes pratiques
  • Acquia France
  • Débat et session de questions-réponses


Valtech y sera, et vous ?

Avec le support d’Acquia, Valtech vous accompagne dans la mise en place de plateformes digitales riches et évolutive de Drupal afin de gérer l’ensemble de vos site Web et la diffusion multi-canale de vos contenus.

Inscription & Accès :
  • Lieu : Hôtel Baltimore, Paris (Plan)
  • Date : 25 mai 2012
  • Horaire : 09:00 – 14:30
  • Inscription : via le site web

 


Retrouvez les consultants de Valtech à Agile France 2012 – 24 & 25 mai à Paris

Publié le 14/05/2012, par Olivier Rodrigues dans Agile, Événements, Valtech | Ajouter un commentaire

La conférence incontournable de la communauté Agile

La conférence Agile France revient encore cette année le 24 & 25 mai à Paris, l’occasion de rencontrer des Agilistes de tous niveaux, partager vos expériences avec des professionnels de votre secteur.

Le programme est très complet : Agile, Scrum, User Experience et aussi outils, code et techniques de programmation.

Au cours des deux jours, retrouvez nos consultants Valtech lors des sessions suivantes :

Jeudi 24 mai

Pierrick Revol, Coach Agile, Valtech 9h30 : Large Scale Scrum: Assurez la polycompétence dans vos équipes

Notre expérience de coaching agile sur un projet impliquant plus de cent personnes nous a permis d’identifier que la polycompétence est un facteur clé de succès à cette échelle.Nous avons donc travaillé avec les équipes Scrum pour lever les principaux freins à la polycompétence et mieux expliciter son fonctionnement. Cette session partage avec vous les fruits de ce travail.
Objectifs et bénéfices de la session pour les participants
Comprendre les enjeux de la polycompétence dans une équipe Scrum et pourquoi c’est un facteur clé de succès dans un projet de transformation Agile à grande échelle. Reconnaître les freins usuels et trouver des pistes pour les lever.
Etienne Charignon, Consultant senior, Valtech 10h30 : Scrum Solo

La méthode Scrum est conçue pour organiser un travail d’équipe (de 2 à 7 personne environ). Qu’en est-il sur un projet avec un développeur unique ? Qu’en reste-t-il ? Est-ce toujours pertinent ? Je vous propose de vous présenter un retour d’expérience de l’application de Scrum sur un projet de développement en java ou je suis intervenu “en solo”. Je peux supposer que cette pratique pourrait tendre à se développer avec la multiplication des applications pour mobile qui ne réclame pas l’intervention d’une équipe.
Cette présentation sera l’occasion d’insister une fois de plus sur le fait que “l’équipe” ne se limite pas à une population de développeur.
Cette présentation a déjà été jouée une fois (en version réduite sous la forme d’un Quicky) à Scrum Day 2012
Thomas Bonset, Consultant-développeur agile, Valtech 11h30 : De Scrum vers Kanban, ou comment gérer de manière agile une équipe transverse.

Un REX de ma mission actuelle, au sein d’une équipe chargée de gérer, de faire évoluer et d’administrer l’usine logicielle (avec maven, intégration continue, qualité de code et tout le toutim) d’une grande banque.
Dans un premier temps je disserterai sur l’intérêt d’une telle équipe :
Pourquoi la présence d’une équipe “UL” ? Pourquoi imposer et encadrer au lieu de laisser les MOE “s’autogérer”?
Dans un deuxieme temps je disserterai sur la gestion agile d’une telle équipe :
Pourquoi l’agilité ? Les écueils à y appliquer Scrum, et la mise en place (réussie) de Kanban.
Je me baserai sur les deux articles que j’ai posté sur le blog Valtech.
Jean-Claude Grosjean, Coach Agile, praticien Agile UX et formateur, Valtech 16h00 : AgileUX (User Experience): Prototypage Agile, Workshops & Sketching

Diversité, Apprentissage, montée en compétences et partage de connaissance sont les clés de voute d’une Agilité, qui encourage toujours plus de Collaboration et de Feedback.
Le design d’interface de qualité est aujourd’hui un élément différenciant. Dans un contexte agile, cette activité va donner de la valeur, faire gagner du temps, booster la créativité et l’innovation. Entre opportunités et nécessité, elle sera néanmoins menée sans excès, au plus juste, avant tout dans un esprit collaboratif et Agile pour au final n’en être que plus riche !
Jean-Claude Grosjean, Coach Agile, praticien Agile UX et formateur, Valtech 16h30 : Petits Outils de Facilitation à l’usage des Honnêtes Gens

FACILITER, cela consiste à aider un groupe, une ou des personnes, à apprendre, explorer, trouver des solutions, atteindre un consensus… Souvent négligée, la facilitation est pourtant une vraie discipline, désormais au cœur de nos activités en Entreprise.
C’est dans un mode Show & Tell et sous forme de pattern (Problème, contexte, solution) que je vous invite à découvrir ces petits outils & techniques de facilitation si simples mais terriblement efficaces au quotidien. Vos retours d’expérience sur les techniques présentées seront encouragées.
Vous connaissez tous le ROTI ou le Vote à 5 doigts, vous en découvrirez d’autres…

Vendredi 25 mai

Etienne Charignon, Consultant senior, Valtech 11h30 : Retour d’expérience : Agile contre Cycle en V : Le match

En 2011, nous avons eu l’occasion de réaliser le rêve de tout agiliste. Un client a fait réaliser deux fois le même site web, un en mode agile, l’autre en mode “classique”. A votre avis qui a gagné ?
Je vous présenterai le contexte de cette expérience à première vue étonnante et nous regarderons en détail les différences et leurs conséquences.
Jusqu’à présent, j’ai toujours pensé qu’entre agile et cycle en V il “n’y avait pas photo”… Bon, maintenant en plus j’ai la photo !

 

Sat Philora, Consultant AgileUX et Coach Agile, Valtech 14h30 : Les yeux ouverts : agilité + tests utilisateurs

Je vais vous parler des tests utilisateurs dans un contexte Agile.
Il s’agit des pratiques simples, faciles à mettre en place, qui vous permettront de tester vos applications avec des utilisateurs, afin de:
* trouver des points défaillants en terme d’ergonomie
* mieux comprendre la façon dont l’utilisateur perçoit l’application
* trouver des idées pour de nouvelles fonctionnalités
Ce feedback nous permet de livrer une application toujours plus facile à utiliser, et plus adaptée aux besoins des utilisateurs.

Les inscriptions sont encore ouvertes. Venez améliorer vos connaissances à l’événement Agile de l’année !


Retrouvez Ewane Prevotat-Deiller, Consultante ergonome, chez Valtech lors du Flupa UX DAY le 11 mai à Paris

Publié le 4/05/2012, par Olivier Rodrigues dans Agile, Événements, Valtech | Ajouter un commentaire

Le rendez-vous incontournable pour les professionnels de l’usabilité

Le FLUPA UX-Day aura lieu le vendredi 11 mai à Paris autour de thèmes actuels, tels que : l’expérience utilisateur (UX), l’ergonomie des smartphones et des tablettes tactiles, la conception ergonomique et l’agilité, l’émergence de la gestural interaction, la persuasion technologique …

Venez écouter les keynotes speakers en plénière, partager vos expériences avec des professionnels de votre secteur et retrouver notre experte Valtech lors de la conférence :

Au programme (8h30 – 18h15) :

L’ergonome produit des storyboards pour qui, pourquoi… Comment les optimiser et assoir les besoins de tous les acteurs d’un projet digital ?

Inscription & Accès :

 


Optimiser l’engagement client – Séminaire le 5 juin à Paris

Publié le 3/05/2012, par Olivier Rodrigues dans Événements, Mobile, Valtech | Ajouter un commentaire

Bannière Séminaire Sitecore

 

Aujourd’hui beaucoup d’entreprises se sentent dépassées par l’augmentation rapide de choix de canaux et de médias, notamment avec l’émergence des smartphones, tablettes et des réseaux sociaux. Seule une véritable conversation, cohérente et continue au travers des différents canaux, permet de garder l’intérêt pour la marque et ses produits.

Un partenariat Valtech / Sitecore

Ce séminaire a pour objectif de vous proposer des retours d’expériences tangibles sur la base de projets réalisés par des professionnels du marketing digital.

Au programme (8h30 – 12h00) :

  • L’engagement client dans une stratégie de marketing digital ?
  • Sitecore “Customer Engagement Platform”
  • Table Ronde : Comment optimiser l’engagement client ?
    Avec les témoignages de dirigeants de grands groupes.

Inscription & Accès :

  • Lieu : Valtech, 103 rue de Grenelle, 75007, Paris (Plan)
  • Date : 5 juin 2012
  • Horaire : 08:30 – 12:00
  • Inscription : via le site web

 

Les équipes de Valtech et Sitecore seront heureuse de vous accueillir pour cette matinée d’échanges.