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 :
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
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; } }
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
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); } } }
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
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);
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)".
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
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,
Partager