IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

Persistance des donn�es Java Discussion :

Spring : manyToMany bidirectionnel, les donn�es mapp�s d'un cot� est � null


Sujet :

Persistance des donn�es Java

  1. #1
    Membre habitu�
    Homme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    D�cembre 2022
    Messages
    10
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 54
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es
    Secteur : A�ronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : D�cembre 2022
    Messages : 10
    Par d�faut Spring : manyToMany bidirectionnel, les donn�es mapp�s d'un cot� est � null
    Spring 2.5.6

    Bonjour,

    J'ai mis en place manyToMany bidirectionnel, seulement un seul cot� r�cup�re les donn�es mapp�s.

    /profils
    j'ai bien des fonctionnalit�s dans profil
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
            {
                "id": 1,                          // profil
                "code": "CODEP1",
                "label": "defautP1",
                "description": "description defautP1",
                "fonctionnalites": [
                    {
                        "id": 3,                  // fonctionnalité
                        "code": "codeF3",
                        "label": "labelF3",
                        "description": "descriptionF3",
                        "profils": null
                    },
                    {
                        "id": 1,                  // fonctionnalité
                        "code": "codeF1",
                        "label": "labelF1",
                        "description": "descriptionF1",
                        "profils": null
                    }
                ]
            },

    /fonctionnalites

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    [
            {
                "id": 1,               // fonctionnalités
                "code": "codeF1",
                "label": "labelF1",
                "description": "descriptionF1",
                "profils": null      // est toujours à NULL
                                         // il doit y avoir profil dont id = 1
            },
    Profil
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    @Entity
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    @Table(name = "t_profil")
    public class Profil {
     
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_profil")
        @SequenceGenerator(name = "seq_profil", sequenceName = "seq_profil", allocationSize = 1)
        Long id;
     
        @Column(name = "code")
        String code;
     
        @Column(name = "label")
        String label;
     
        @Column(name = "description")
        String description;    
     
        @ManyToMany(cascade =  {
                CascadeType.ALL,
            }, fetch = FetchType.LAZY)
        @JoinTable(
                name = "t_profils_fonctionnalites",
                joinColumns = { @JoinColumn(name = "profil_id") },
                inverseJoinColumns = { @JoinColumn(name = "fonctionnalite_id") }
        )
        public Set<Fonctionnalite> fonctionnalites; 
    }
    Fonctionnalit�
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    @Entity
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    @Table(name = "t_fonctionnalite")
    public class Fonctionnalite {
     
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_fonctionnalite")
        @SequenceGenerator(name = "seq_fonctionnalite", sequenceName = "seq_fonctionnalite", allocationSize = 1)
        Long id;
     
        @Column(name = "code")
        String code;
     
        @Column(name = "label")
        String label;
     
        @Column(name = "description")
        String description;    
     
        //@JsonIgnore    
        @ManyToMany(mappedBy = "fonctionnalites", fetch = FetchType.LAZY, cascade =  { CascadeType.ALL, })
        Set<Profil> profils; 
    }
    j'ai essay� pour profil et fonctionnalit� le mode : FetchType.EAGER, m�me r�sultat !


    controller
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    fonctionnaliteDao.findAll(spec, pageable);
    j'ai aussi essay� (en mode LAZY) :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    fonctionnaliteDao.findAll(spec, pageable);
    fonctionnalitePage.getContent().forEach(f -> f.getProfils());

  2. #2
    Membre tr�s actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par d�faut
    Plusieurs remarques...

    D�j�, j'�viterais l'Entit� (le POJO Hibernate) dans le controller. Je passerai par une DTO qui r�duirait les donn�es que l'on veut communiquer � l'ext�rieure.

    Deuxi�mement, je me poserais plus s�rieusement la question du EAGER/LAZY car elle est effectivement fondamentale.

    EAGER, �a veut dire que je demande � Hibernate de charger ce qui est li� � l'entit�. Donc �ventuellement de faire des requ�te en plus.

    LAZY, �a veut dire que je demande � Hibernate d'�tre faignant. De charger � la demande. Si c'est LAZY, hibernate ne le fera pas.

    Cette question est fondamentale car elle a des r�percussions sur les performances.

    Par d�faut, la d�fensive c'est de mettre LAZY.


    On peut rendre un LAZY EAGER avec du JPQL (comme SELECT user FROM User user INNER JOIN FECTH user.roles) avec ici roles LAZY.

    Je vais donner un exemple de mon projet (m�me si ici, il n'y a pas ManyToMany, mais le principe reste le m�me).

    https://bitbucket.org/philippegibaul...r40k/src/main/

    Dans mon projet, j'ai des factions et des camps.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
     
    package com.calculateur.warhammer.entity.entity;
     
    import java.util.Set;
     
    import javax.persistence.EmbeddedId;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.ForeignKey;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.ManyToOne;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    import javax.validation.constraints.NotNull;
    import com.calculateur.warhammer.entity.pk.FactionPK;
     
    /**
     * Entité pour les faction en BDD
     * 
     * @author phili
     *
     */
    @Entity
    @Table(name = "FACTION")
    public class FactionEntity extends AbstractEntityAvecLibelle<FactionPK> {
     
    	@EmbeddedId
    	@NotNull(message = "faction.pk.null")
    	private FactionPK id;
     
    	@ManyToOne(fetch = FetchType.EAGER)
    	@JoinColumn(name = "ID_CAMP",foreignKey = @ForeignKey(name = "FK_CAMP"),insertable = false, updatable = false,nullable = false)
    	@NotNull(message = "faction.camp.null")
    	private CampEntity camp;
     
    	@OneToMany(fetch = FetchType.LAZY,mappedBy = "faction")
    	private Set<SousFactionEntity> sousFactions;
     
    	@ManyToMany(fetch = FetchType.LAZY)
    	@JoinTable(name = "ASSOCIATION_FACTION_REGLE_FACTION",
    		joinColumns = {
    				@JoinColumn(name = "ID_CAMP",foreignKey = @ForeignKey(name = "FK_CAMP_ASSOCIATION_ASSOCIATION_FACTION_REGLE_FACTION"),insertable = false, updatable = false),
    				@JoinColumn(name = "ID_FACTION",foreignKey = @ForeignKey(name = "FK_FACTION_ASSOCIATION_ASSOCIATION_FACTION_REGLE_FACTION"),insertable = false, updatable = false)
    		},
    		inverseJoinColumns = @JoinColumn(name = "ID_REGLE_FACTION",foreignKey = @ForeignKey(name = "FK_REGLE_FACTION_ASSOCIATION_ASSOCIATION_FACTION_REGLE_FACTION"))
    			)
    	private Set<RegleFactionEntity> regles;
     
    	@JoinTable(name = "ASSOCIATION_FACTION_AURA",
    			joinColumns = {
    					@JoinColumn(name = "ID_CAMP",foreignKey = @ForeignKey(name = "FK_CAMP_ASSOCIATION_ASSOCIATION_FACTION_AURA"),insertable = false, updatable = false),
    					@JoinColumn(name = "ID_FACTION",foreignKey = @ForeignKey(name = "FK_FACTION_ASSOCIATION_ASSOCIATION_FACTION_AURA"),insertable = false, updatable = false)
    			},
    			inverseJoinColumns = @JoinColumn(name = "ID_AURA",foreignKey = @ForeignKey(name = "FK_REGLE_FACTION_ASSOCIATION_ASSOCIATION_FACTION_AURA"))
    				)
    	@ManyToMany(fetch = FetchType.LAZY)
    	private Set<AuraEntity> auras;
     
    	@Override
    	public FactionPK getId() {
    		return id;
    	}
     
    	@Override
    	public void setId(FactionPK id) {
    		this.id = id;
    	}
     
    	public CampEntity getCamp() {
    		return camp;
    	}
     
    	public void setCamp(CampEntity camp) {
    		this.camp = camp;
    	}
     
    	public Set<SousFactionEntity> getSousFactions() {
    		return sousFactions;
    	}
     
    	public void setSousFactions(Set<SousFactionEntity> sousFactions) {
    		this.sousFactions = sousFactions;
    	}
     
    	public Set<RegleFactionEntity> getRegles() {
    		return regles;
    	}
     
    	public void setRegles(Set<RegleFactionEntity> regles) {
    		this.regles = regles;
    	}
     
    	public Set<AuraEntity> getAuras() {
    		return auras;
    	}
     
    	public void setAuras(Set<AuraEntity> auras) {
    		this.auras = auras;
    	}
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    package com.calculateur.warhammer.entity.entity;
     
    import java.util.Set;
     
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    import javax.validation.constraints.NotNull;
     
     
    @Entity
    @Table(name = "CAMP")
    public class CampEntity extends AbstractEntityAvecLibelle<Integer>{
     
    	@Id
    	@Column(name = "ID_CAMP",nullable = false)
    	@NotNull(message = "id.null")
    	private Integer id;
     
    	@OneToMany(mappedBy = "camp",fetch = FetchType.LAZY)
    	private Set<FactionEntity> factions;
     
    	@Override
    	public Integer getId() {
    		return id;
    	}
     
    	@Override
    	public void setId(Integer id) {
    		this.id = id;
    	}
     
    	public Set<FactionEntity> getFactions() {
    		return factions;
    	}
     
    	public void setFactions(Set<FactionEntity> factions) {
    		this.factions = factions;
    	}
    }
    Mon service donnant � l'ext�rieur les Camps ne donne que ce qui est propre aux camps. Et idem pour la faction.

    Donc, tout est LAZY.

    Pour donner � l'ext�rieur, via des Services REST, je passe par des DTO:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    package com.calculateur.warhammer.dto;
     
    public class CampDTO extends AbstractLibelleDTO {
     
     
     
    	/**
             * 
             */
    	private static final long serialVersionUID = 1L;
     
    	private static final String RESOURCES_TRADUCTION = "com.calculateur.warhammer.dto.camp.camp";
     
    	@Override
    	public String getResourceBudleAsString() {
    		return RESOURCES_TRADUCTION;
    	}
     
    	@Override
    	public String toString() {
    		StringBuilder sb = new StringBuilder("Camp : [id = ");
    		sb.append(getId());
    		sb.append(", nom = ");
    		if(getLibelle() != null) {
    			sb.append(getLibelle());
    		}else {
    			sb.append(getNom());
    		}
    		sb.append("]");
    		return sb.toString();
    	}
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    package com.calculateur.warhammer.dto;
     
    public class FactionDTO extends AbstractLibelleDTO{
     
    	/**
             * 
             */
    	private static final long serialVersionUID = 1L;
     
    	private static final String RESOURCES = "com.calculateur.warhammer.dto.faction.faction";
     
    	@Override
    	public String getResourceBudleAsString() {
    		return RESOURCES;
    	}
     
    	@Override
    	public String toString() {
    		StringBuilder sb = new StringBuilder("Faction : [id = ");
    		sb.append(getId());
    		sb.append(", nom = ");
    		if(getLibelle() != null) {
    			sb.append(getLibelle());
    		}else {
    			sb.append(getNom());
    		}
    		sb.append("]");
    		return sb.toString();
    	}
    }
    Ma DTO est sp�ciale, coome mon appli est internationale, je traduis selon une cl� de traduction (en BDD):
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    package com.calculateur.warhammer.dto;
     
    import java.util.Locale;
     
    import com.calculateur.warhammer.base.dto.ILibelleDTO;
     
    public abstract class AbstractLibelleDTO implements ILibelleDTO{
     
    	/**
             * 
             */
    	private static final long serialVersionUID = 1L;
     
    	private Integer id;
    	private String nom;
    	private String cleTraduction;
    	private String libelle;
     
    	@Override
    	public void traduireLibelles(Locale locale) {
    		libelle = getResourceBundle(locale).getString(getCleTraduction());
    	}
     
    	@Override
    	public Integer getId() {
    		return id;
    	}
     
    	@Override
    	public void setId(Integer id) {
    		this.id = id;
    	}
     
    	@Override
    	public String getNom() {
    		return nom;
    	}
     
    	@Override
    	public void setNom(String nom) {
    		this.nom = nom;
    	}
     
    	@Override
    	public String getCleTraduction() {
    		return cleTraduction;
    	}
     
    	@Override
    	public void setCleTraduction(String cleTraduction) {
    		this.cleTraduction = cleTraduction;
    	}
     
    	@Override
    	public String getLibelle() {
    		return libelle;
    	}
     
    	public void setLibelle(String libelle) {
    		this.libelle = libelle;
    	}
    }
    Je n'ai plus qu'� mapper (chez moi, dans un sens seulement):
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    package com.calculateur.warhammer.service.mapping;
     
    import javax.inject.Named;
     
    import com.calculateur.warhammer.dto.CampDTO;
    import com.calculateur.warhammer.entity.entity.CampEntity;
     
     
    @Named(value = "campMapping")
    public class CampMapping extends AbstractMappingPourLibelle<Integer, CampEntity, CampDTO>{
     
    	@Override
    	protected CampDTO getNewInstanceDTO() {
    		return new CampDTO();
    	}
     
    	@Override
    	protected Integer getIdAsInteger(Integer id) {
    		return id;
    	}
     
    	@Override
    	protected void autreMappingEntityVersDTO(CampEntity entity, CampDTO dto) {
    		//Rien
    	}
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    package com.calculateur.warhammer.service.mapping;
     
    import java.io.Serializable;
     
    import com.calculateur.warhammer.base.dto.ILibelleDTO;
    import com.calculateur.warhammer.base.entity.IEntityAvecLibelle;
    import com.calculateur.warhammer.base.mapping.IMappingEntityVersDTO;
     
    /**
     * Template Methode pour les classes ayant des libellé (et description aussi)
     * @author phili
     *
     * @param <I> Id entité
     * @param <E> Entité
     * @param <D> DTO
     */
    public abstract class AbstractMappingPourLibelle<I extends Serializable,E extends IEntityAvecLibelle<I>,D extends ILibelleDTO> implements IMappingEntityVersDTO<E, D>{
     
    	@Override
    	public D mapEntityVersDTO(E entity) {
    		D dto = null;
    		if(entity != null) {
    			dto = getNewInstanceDTO();
    			dto.setId(getIdAsInteger(entity.getId()));
    			dto.setNom(entity.getNom());
    			dto.setCleTraduction(entity.getCleTraduction());
    			autreMappingEntityVersDTO(entity, dto);
    		}
    		return dto;
    	}
     
     
    	/**
             * 
             * @return Nouvelle instance DTO
             */
    	protected abstract D getNewInstanceDTO();
     
    	/**
             * 
             * @param id Id DTO
             * @return L'identifiant pour la DTO
             */
    	protected abstract Integer getIdAsInteger(I id);
     
    	/**
             * Autre mapping de l'entité vers la DTO
             * @param entity Une entité
             * @param dto une DTO
             */
    	protected abstract void autreMappingEntityVersDTO(E entity, D dto);
    }
    A noter que comme je n'aime pas me r�p�ter, j'utilise le Design Pattern Template Methode.

    A not� que la DTO permet de diff�rentier l'entit�. Ce n'est pas le m�me r�le.

    Dans ton cas, je garderai l'entit� que je s�parerai de la DTO, c'est � dire je garderai l'entit� pour mapper � la BDD, j'enl�verai toute la logique JSON de l'entit�, et selon ce que je veux sortir et donner � l'utilisateur, je ferai 1 ou plusieurs DTO.

    Cordialement.

  3. #3
    Membre tr�s actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par d�faut
    J'ai de fait oubli� que l'on passe par des services, qui donnent des DTO.

  4. #4
    Membre habitu�
    Homme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    D�cembre 2022
    Messages
    10
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 54
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es
    Secteur : A�ronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : D�cembre 2022
    Messages : 10
    Par d�faut
    merci philippe pour tous ces renseignements
    je vais �tudier tes conseils

    merci encore !

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. R�ponses: 6
    Dernier message: 08/12/2022, 06h02
  2. R�ponses: 6
    Dernier message: 25/05/2018, 12h26
  3. R�ponses: 1
    Dernier message: 19/04/2017, 16h06
  4. extraire toutes les donn�es d'une table (cot� serveur)
    Par stoner2008 dans le forum Servlets/JSP
    R�ponses: 0
    Dernier message: 13/06/2014, 12h40
  5. trier les donn�es dans le cache ??
    Par psyco2604 dans le forum XSL/XSLT/XPATH
    R�ponses: 31
    Dernier message: 10/06/2003, 10h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo