Detached Entity après un saveOrUpdate
Bonjour,
je suis confronté à un soucis dans mes tests que je ne comprend pas. Je test ma couche de DAO, et j'ai l'exception suivante de levée (en résumé) :
Code:
1 2 3 4
|
javax.ejb.EJBException: java.lang.IllegalArgumentException: Removing a detached instance org.javacrea.gestioncontacts.pu.Contact#1
at org.javacrea.test.gestioncontacts.TestDAO.createContact(TestDAO.java:91)
Caused by: java.lang.IllegalArgumentException: Removing a detached instance org.javacrea.gestioncontacts.pu.Contact#1 |
Le code du test est le suivant :
Code:
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
| @RunWith(Arquillian.class)
public class TestDAO {
@Inject
private GestionContacts fichier;
@Deployment
public static Archive<?> createDeployment() {
return ShrinkWrap
.create(JavaArchive.class, "DAOTest.jar")
.addClasses(GestionContacts.class, GestionContactsLocal.class, GestionContactsRemote.class, GestionContactsImpl.class, NullCriteriaValueException.class, MissingCVLineDatesException.class)
.addPackage(Contact.class.getPackage())
.addAsManifestResource("META-INF/test-beans.xml", "beans.xml")
.addAsResource("META-INF/test-persist.xml","META-INF/persistence.xml");
}
public void injectFichier(){
Assert.assertNotNull(fichier);
Assert.assertEquals("OK", fichier.test());
}
public void vider(){
fichier.closeSession();
List<Contact> all = fichier.chargerFichier();
for(Contact c : all){
fichier.updateContact(c);
fichier.deleteContact(c);
}
fichier.saveSession();
}
public void createContact() throws ParseException, MissingCVLineDatesException{
Contact moi = fichier.createContact("Monsieur","Delalleau", "François");
Assert.assertNotNull(moi);
Assert.assertTrue(moi.getId()!=null);
int i = moi.getId();
moi.addAdressePerso(new Adresse("mon adresse", "92110", "Clichy", null));
moi.addEmail(new Email("f.delalleau@gmail.com"));
moi.addTelephone(new LigneDirecte("0686000000"));
boolean saved = fichier.updateContact(moi);
Assert.assertTrue(saved);
moi = fichier.trouverContact("Delalleau").get(0);
Assert.assertEquals("François", moi.getPrenom());
fichier.closeSession();
Assert.assertNotNull(fichier.readContact(i));
moi = fichier.readContact(i);
boolean persistent = fichier.updateContact(moi);
Assert.assertTrue(persistent);
fichier.deleteContact(moi); // => l'erreur est ici
Assert.assertNull(fichier.readContact(i));
System.out.println("CRUD contact OK!");
fichier.closeSession();
}
@Test
public void runTest() throws ParseException, MissingCVLineDatesException{
injectFichier();
vider();
createContact();
vider();
}
} |
Et la classe de DAO (je zappe les méthodes non employées dans ce test):
Code:
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
| @Singleton
@ApplicationScoped
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class GestionContactsImpl implements GestionContactsLocal,
GestionContactsRemote {
private Integer dirtyCount = 0;
@PersistenceContext(unitName = "GestionContacts")
private Session session;
@PostConstruct
public void checkFlush() {
session.setFlushMode(FlushMode.COMMIT);
}
public String test() {
return "OK";
}
@SuppressWarnings("unchecked")
public List<Contact> chargerFichier() {
isTooDirty();
return session.createQuery("select c from Contact c").list();
}
@SuppressWarnings("unchecked")
public List<Contact> trouverContact(String nom) {
isTooDirty();
return session
.createQuery("select c from Contact c where c.nom like :nom")
.setParameter("nom", nom).list();
}
...
@Override
public Contact createContact(String titre, String nom, String prenom) {
Contact contact = new Contact();
contact.setTitre(titre);
contact.setNom(nom);
contact.setPrenom(prenom);
session.save(contact);
isTooDirty();
return contact;
}
@Override
public Contact readContact(Integer id) {
isTooDirty();
Contact c = (Contact) session.get(Contact.class, id);
if(c!=null){
return c;
} else {
throw new EntityNotFoundException();
}
}
@Override
public boolean updateContact(Contact contact) {
session.saveOrUpdate(contact);
isTooDirty();
return session.contains(contact);
}
@Override
public boolean deleteContact(Contact contact) {
session.delete(contact);
isTooDirty();
return !session.contains(contact);
}
@Override
public void saveSession() {
session.flush();
}
@Override
public void closeSession() {
session.flush();
session.clear();
}
private void isTooDirty() {
if(session.isDirty()){
dirtyCount++;
}
if(dirtyCount>10){
saveSession();
}
} |
J'ai probablement mal compris quelque chose dans l'utilisation de Hibernate, si quelqu'un peut m'éclairer.