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

Hibernate Java Discussion :

[Hibernate 3.4] Relation père-fils : Effacement d'un des fils


Sujet :

Hibernate Java

  1. #1
    Membre du Club
    Inscrit en
    Mai 2003
    Messages
    71
    Détails du profil
    Informations forums :
    Inscription : Mai 2003
    Messages : 71
    Points : 52
    Points
    52
    Par défaut [Hibernate 3.4] Relation père-fils : Effacement d'un des fils
    Bonjour à tous,

    je désire gérer une relation Père-Fils, en enlevant un des fils.
    Quelque chose comme ça :
    monPere.getFils(); // 2 fils :
    // hypothese : monFils1 est evidemment un des 2 fils de monPere
    monPere.getFils().remove(monFils1);
    monPereDAO.save(monPere);
    // ici, en base, il n'y a plus que le Pere et un seul de ces fils

    Voici ce que j'ai base :
    T_PERE
    ID : INTEGER /**cle primaire, non null*/
    NAME : VARCHAR

    T_FILS
    ID : INTEGER /**cle primaire, non null*/
    PERE_ID : INTEGER /**Cle etrangere vers T_PERE, non null */
    NAME : VARCHAR

    et en code Java :
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    @Entity
    @Table(name = "T_PERE")
    public class Pere implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	/** The id. */
    	@Id
    	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pere_seq")
    	@SequenceGenerator(name = "pere_seq", allocationSize = 10, sequenceName = "SEQ_PERE_ID")
    	private Long id;
     
    	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    	@JoinColumn(name = "PERE_ID")
    	private Set<Fils> fils = new HashSet<Fils>();
     
    	public Long getId() {
    		return id;
    	}
     
    	public void setId(Long id) {
    		this.id = id;
    	}
     
    	public void setFils(Set<Fils> fils) {
    		this.fils = fils;
     
    		for (Fils aFils : this.filss) {
    			aFils .setPere(this);
    		}
    	}
     
    	public Set<Fils> getFils() {
    		return fils;
    	}
     
     
    	// ---------------------------------------------------------
     
    	public void addFils(Fils aFils) {
    		if (fils == null) {
    			fils = new HashSet<Fils>();
    		}
    		fils.add(aFils);
    		aFils.setPere(this);
    	}
     
     
    	public boolean remove(Fils aFils) {
    		// aFils.setPere(null);
    		return fils.remove(aFils);
    	}
    }
     
    @Entity
    @Table(name = "T_FILS")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Fils implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	/** The id. */
    	@Id
    	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fils_seq")
    	@SequenceGenerator(name = "fils_seq", allocationSize = 10, sequenceName = "SEQ_FILS_ID")
    	private Long id;
     
    	@ManyToOne(fetch = FetchType.LAZY)
    	@JoinColumn(name = "PERE_ID", nullable = false)
    	private Pere pere;
     
    	public Long getId() {
    		return id;
    	}
     
    	public void setId(Long id) {
    		this.id = id;
    	}
     
    	public Pere getPere() {
    		if (pere instanceof HibernateProxy) {
    			Object r = ((HibernateProxy) pere).getHibernateLazyInitializer().getImplementation();
    			return (Pere) r;
    		} else {
    			return pere;
    		}
    	}
     
    	public void setPere(Pere pere) {
    		this.pere = pere;
    	}
     
     
    	// -----------------------------------------------------------
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + ((id == null) ? 0 : id.hashCode());
    		return result;
    	}
     
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Fils other = (Fils) obj;
    		if (id == null) {
    			if (other.id != null)
    				return false;
    		} else if (!id.equals(other.id)) {
    			return false;
    		}
    		return true;
    	}
    }
    Le code "DAO" est du type suivant :
    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
    @Repository
    public class PereDAO {
    	public static Logger LOGGER = Logger.getLogger(PereDAO.class);
     
    	@PersistenceContext
    	protected EntityManager em;
     
    	/**
             * Private constructor used to prevent from instantiation.
             * 
             * Use DAOFactory.
             */
    	private PereDAO() {
    		super();
    	}
     
    	public Class<Pere> getModelClass() {
    		return Pere.class;
    	}
     
    	public Pere getById(Long id) throws DAOException {
    		try {
    			return em.find(getModelClass(), id);
    		} catch (Exception e) {
    			logger.error("Error while getting by id: " + id + " on " + getModelClass(), e);
    			throw new DAOException(e);
    		}
    	}
     
    	@SuppressWarnings("unchecked")
    	public List<Pere> findAll() throws DAOException {
    		try {
    			String q = "SELECT e FROM " + getModelClass().getSimpleName() + " e";
    			Query query = em.createQuery(q);
    			return (List<Pere>) query.getResultList();
    		} catch (Exception e) {
    			logger.error("Error while fetching all on " + getModelClass(), e);
    			throw new DAOException(e);
    		}
    	}
     
    	public void save(Pere object) throws DAOException {
    		try {
    			if (em.contains(object)) {
    				em.merge(object);
    			} else {
    				em.persist(object);
    			}
     
    			em.flush();
    		} catch (Exception e) {
    			logger.error("Error while saving: " + object + " on " + getModelClass(), e);
    			throw new DAOException(e);
    		}
    	}
     
    	public void merge(Pere object) throws DAOException {
    		try {
    			em.merge(object);
    		} catch (Exception e) {
    			logger.error("Error while saving: " + object + " on " + getModelClass(), e);
    			throw new DAOException(e);
    		}
    	}
     
    	public void flush() throws DAOException {
    		try {
    			em.flush();
    		} catch (Exception e) {
    			logger.error("Error while flushing on: " + getModelClass(), e);
    			throw new DAOException(e);
    		}
    	}
     
    	public void delete(E object) throws DAOException {
    		try {
    			object = em.merge(object);
    			em.remove(object);
    		} catch (Exception e) {
    			logger.error("Error while deleting: " + object + " on " + getModelClass(), e);
    			throw new DAOException(e);
    		}
    	}
    }
    Dans ma classe de test, j'essaye de recupérer le père, puis d'enlever ses 2 fils, puis d'effacer le pere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    			Assert.assertEquals(2, monPere.getFils().size()); // ça passe
    			Set<Fils> allFils = new HashSet<Fils>(
    					monPere.getFils());
    			for (Fils monFils : allFils) {
    				monPere.remove(monFils);
    				// filsDAO.delete(monFils);
    			}
    			pereDao.delete(pere);
    Toutefois, à l'exécution, j'ai quand même l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
    // ... 
    Caused by: java.sql.BatchUpdateException: ORA-01407: impossible de mettre à jour ("BASE_OWNER"."T_FILS"."PERE_ID") avec NULL
    J'ai la même erreur, y compris quand j'essaye d'effacer le fils directement avant d'effacer le père (cf code de test, en dé-commentant le code "filsDAO.delete(monFils)".

    Question : Que faut il modifier pour que je puisse effacer un ou tous les fils d'un père ? Idem si je veux effacer directement toute l'arborescence (pere + fils) ?

    Merci d'avance pour vos éclaircissements et vos idées de débugage.

    Cordialement,

  2. #2
    Membre actif
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2006
    Messages
    288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 288
    Points : 261
    Points
    261
    Par défaut
    Je sais que ça devrait marcher car c'est la bonne procédure. Supprimer d'abord les fils puis le père.
    Et même la suppression du père directement ne devrait pas poser problème car tu as la cascade à all.
    Vérifie ton paramétrage dans ta transaction ou au niveau de la database essaie de mettre auto commit à true.
    Merci de lire les règles du forum et surtout celle là Message clair et précis.
    Evitons les ctrl c ctrl v => Ne sortons pas les codes de leur contexte sinon ça ne marche pas.

  3. #3
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Est-ce que ta colonne PERE_ID est nullable ?

    Ce n'est pas une bonne chose de mettre l'auto commit à true.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Consultant OpenERP /J2EE
    Inscrit en
    Février 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Consultant OpenERP /J2EE
    Secteur : Finance

    Informations forums :
    Inscription : Février 2009
    Messages : 19
    Points : 20
    Points
    20
    Par défaut
    Bonjour;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for (Fils monFils : allFils) {
    			monPere.remove(monFils);
    			// filsDAO.delete(monFils);
    			}
    			pereDao.delete(pere);
    n'effacera pas monFils de la base de données, il enlèvera seulement le lien vers monPere(et causera une violation de contrainte NOT NULL, dans ce cas). Vous devez explicitement utiliser delete() sur monFils (celle qui t'a met en commentaire).
    essayer avec inverse="true" et cascade="all-delete-orphan".

Discussions similaires

  1. [Mapping] Relation père fils sur une même table.
    Par Invité dans le forum Hibernate
    Réponses: 1
    Dernier message: 11/06/2008, 17h14
  2. [MySQL] Relation père-fils en PHP et MySQL
    Par nabians dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 18/07/2007, 11h02
  3. Formulaire sous-formulaire: relation père fils
    Par Zinemon dans le forum IHM
    Réponses: 5
    Dernier message: 27/06/2007, 10h14
  4. Table avec lignes ayant une relation "père-fils"
    Par the java lover dans le forum Windows Forms
    Réponses: 7
    Dernier message: 02/04/2007, 11h20
  5. [pthread] relation père - fils ?
    Par jedimind dans le forum C
    Réponses: 3
    Dernier message: 14/11/2005, 11h18

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