Bonjour,

Ma configuration :
EJB 3.0, JBOSS, Hibernate

j'ai besoin d'un peu d'aide sur un problème de persistence, alors voilà

j'ai 2 entity bean, un trainer et un assistant

Voici le trainer :

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
 
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package org.lesson.model;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
 
/**
 *
 *
 */
@Entity
public class Trainer extends Checker implements Serializable {
 
    private Assistant assistant;
 
    @Override
    public String toString() {
        return "org.lesson.model.Trainer[id=" + userId + "]";
    }
 
    @OneToOne
    @JoinColumn(name="assistantId",referencedColumnName = "userId")
    public Assistant getAssistant() {
        return assistant;
    }
 
    public void setAssistant(Assistant assistant) {
        this.assistant = assistant;
    }
 
}
et voici l'assistant

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
 
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package org.lesson.model;
 
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
 
 
/**
 *
 
 */
@Entity
public class Assistant extends Checker implements Serializable {
 
    private Trainer trainer;
 
 
    @OneToOne(mappedBy="assistant")
    public Trainer getTrainer() {
        return trainer;
    }
 
    public void setTrainer(Trainer trainer) {
        this.trainer = trainer;
    }
 
 
    @Override
    public String toString() {
        return "org.lesson.model.Assistant[id=" + userId + "]";
    }
 
}
Pour travailler sur ces entity beans j'ai définit les session beans respectifs :

TrainerDao :

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
 
 
package org.lesson.integration.dao;
 
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.lesson.model.Assistant;
import org.lesson.model.Course;
import org.lesson.model.Trainer;
 
@Stateless
public class TrainerDao implements TrainerDaoLocal {
 
    @PersistenceContext (unitName = "Lesson-ejbPU")
    EntityManager em;
 
 
    public void createOrUpdate(Trainer t) {
        em.merge(t);
    }
 
 
    public void remove(Trainer t) {
        em.remove(t);
    }
 
    public void addAssistant(Trainer t,Assistant a) {
        t.setAssistant(a);
    }
 
   public Trainer find(long id){
       return em.find(Trainer.class,id);
    }
 
 
    public List<Trainer> findAll() {
        Query q = em.createQuery("SELECT t FROM Trainer t");
        return q.getResultList();  
 
    }
 
 
    public Assistant findAssistant(Trainer t) {
        return t.getAssistant();
    }
 
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
 
}
et AssistantDao :

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
 
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package org.lesson.integration.dao;
 
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.lesson.model.Assistant;
import org.lesson.model.Trainer;
 
/**
 *
 
 */
 
 
@Stateless
public class AssistantDao implements AssistantDaoLocal {
 
   @PersistenceContext (unitName = "Lesson-ejbPU")
   EntityManager em;
 
 
    public void createOrUpdate(Assistant a){
         em.merge(a);
    }
 
 
    public void remove(Assistant a){
        em.merge(a);
    }  
 
    public  Assistant find(long id){
        return em.find(Assistant.class,id);
 
    }
 
    public List<Assistant> findAll() {
        Query q = em.createQuery("SELECT a FROM Assistant a");
        return q.getResultList();
    }  
 
    public Trainer findTrainer(Assistant a) {
       return a.getTrainer();
    }
 
 
 
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
 
}
Les 2 précédents sessions beans étant locaux , j'ai implémenté le pattern Façade pour les accèder en remote et les tester

TrainerDaoFacade :

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
 
package org.lesson.facade;
 
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import org.lesson.integration.dao.TrainerDaoLocal;
import org.lesson.model.Assistant;
import org.lesson.model.Course;
import org.lesson.model.Trainer;
 
/**
 *
 
 */
@Stateless
public class TrainerDaoFacade implements TrainerDaoFacadeRemote {
 
    @EJB
    private TrainerDaoLocal trainerDaoLocal;
 
    public void createOrUpdate(Trainer t) {
        trainerDaoLocal.createOrUpdate(t);
    }
 
    public void remove(Trainer t) {
        trainerDaoLocal.remove(t);
    }
 
    public Trainer find(long id){
        return trainerDaoLocal.find(id);
    }
 
    public List<Trainer> findAll() {
        return trainerDaoLocal.findAll();
    }
 
 
    public void addAssistant(Trainer t, Assistant a) {
        trainerDaoLocal.addAssistant(t, a);
    }
 
    public Assistant findAssistant(Trainer t) {
        return trainerDaoLocal.findAssistant(t);
    }
 
 
 
}
AssistantDaoFacade :

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
 
 
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package org.lesson.facade;
 
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import org.lesson.integration.dao.AssistantDaoLocal;
import org.lesson.model.Assistant;
 
/**
 *
 
 */
@Stateless
public class AssistantDaoFacade implements AssistantDaoFacadeRemote {
 
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
 
    @EJB
    private AssistantDaoLocal assistantDaoLocal;
 
    public void createOrUpdate(Assistant a) {
       assistantDaoLocal.createOrUpdate(a);
    }
 
    public void remove(Assistant a) {
        assistantDaoLocal.remove(a);
    }
 
    public Assistant find(long id) {
        return assistantDaoLocal.find(id);
    }
 
    public List<Assistant> findAll() {
        return assistantDaoLocal.findAll();
    }
 
 
 
}
et on arrive au fichier de test JUNIT :

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
 
     @Test
        public void addAssistant()
        {
            try {
            InitialContext ctx;
            ctx = new InitialContext(ht);
            Object ref = ctx.lookup("java:/AssistantDaoFacade/remote");
            AssistantDaoFacadeRemote assistantRemote = (AssistantDaoFacadeRemote) PortableRemoteObject.narrow(ref,AssistantDaoFacadeRemote.class);
            ref =  ctx.lookup("java:/TrainerDaoFacade/remote");
            TrainerDaoFacadeRemote trainerRemote = (TrainerDaoFacadeRemote) PortableRemoteObject.narrow(ref,TrainerDaoFacadeRemote.class);
 
            Assistant a = new Assistant();
            a.setName("assistant");
            a.setSurname("assistant");
            a.setPassword("password");
            assistantRemote.createOrUpdate(a);
 
            Trainer t = new Trainer();
            t.setName("trainer");
            t.setSurname("trainer");
            t.setPassword("password");
            trainerRemote.createOrUpdate(t);
 
            System.out.println("trainer id is : "+t.getUserId());
 
            trainerRemote.addAssistant(t, a);
            a.setTrainer(t);
 
            trainerRemote.createOrUpdate(t);
 
 
            Assistant aFound = trainerRemote.findAssistant(t);
            if(aFound == null){
                   fail("Assistant not found");
            }
 
         //   trainerRemote.createOrUpdate(t);
 
        } catch (NamingException ex) {
            Logger.getLogger(TrainerDaoFacadeTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        }
Quand j'exécute le code du test, en base l'assistant est ajouté, le trainer également. Cependant le trainer n'a pas la foreign vers l'assistant (NULL), et encore pire, lorsque je fais un createOrUpdate du même trainer le second coup un nouveau trainer est créé au lieu de faire une fusion ! et l'id que j'affiche est toujours NULL également.

autre précision trainer et assistant héritent tous deux de la classe checker qui hérite elle même de la classe user (je ne sais pas si ça peut aider)

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
 
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package org.lesson.model;
 
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Temporal;
 
/**
 *
 
 */
@Entity(name="LESSON_USER")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class User implements Serializable {
    private static final long serialVersionUID = 1L;
 
 
    protected Long userId;
    protected String password;
    protected String name;
    protected String surname;
    @Temporal(javax.persistence.TemporalType.DATE)
    protected Date birthdate;
 
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    public Long getUserId() {
        return userId;
    }
 
    public void setUserId(Long userId) {
        this.userId = userId;
    }
 
 
    public Date getBirthdate() {
        return birthdate;
    }
 
 
 
    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public String getSurname() {
        return surname;
    }
 
    public void setSurname(String surname) {
        this.surname = surname;
    }
 
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (userId != null ? userId.hashCode() : 0);
        return hash;
    }
 
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof User)) {
            return false;
        }
        User other = (User) object;
        if ((this.userId == null && other.userId != null) || (this.userId != null && !this.userId.equals(other.userId))) {
            return false;
        }
        return true;
    }
 
    @Override
    public String toString() {
        return "org.lesson.model.User[id=" + userId + "]";
    }
 
}
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
 
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package org.lesson.model;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
 
/**
 *
 
 */
@Entity
public abstract class Checker extends User implements Serializable {
 
 
 
}