2017-10-06 10 views
0

J'écris deux méthodes pour réinitialiser la base de données dans mon application. Première doit dynamiquement répertorier toutes les tables, puis les tronquer. Le deuxième est responsable du remplissage des données.Hibernate doit échouer pour réussir la prochaine fois

méthode Truncate utilise requête native:

public void truncate() throws Exception { 
    List<String> names = getAllTableNames(); 

    names.forEach(tableName -> { 
      entityManager.createNativeQuery("TRUNCATE TABLE " + tableName + " CASCADE").executeUpdate(); 
    }); 

//  entityManager.setFlushMode(FlushModeType.COMMIT); 
//  entityManager.getEntityManagerFactory().getCache().evictAll(); 
     entityManager.flush(); 
} 

Deuxième méthode pour les données re-init juste parse des documents, crée des entités et les enregistre en vrac. Les deux méthodes se trouvent dans le service @Transactional. J'ai deux extrémités pour pouvoir les appeler séparément.

Maintenant, ce qui se passe est que, après que je tronque tables (sans erreur se termine) j'appelle re-init et je reçois:

WARNING: org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [com.nws.vedica.model.entity.DocType#ACCOUNTCONTRACTCANCEL]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.nws.vedica.model.entity.DocType#ACCOUNTCONTRACTCANCEL] 

comme si les entités étaient toujours présentes dans le cache EM. La même chose se produit après l'expulsion après le cache de EM (ligne commentée)

maintenant deux observations:

la deuxième demande 1.- pour recréer des entités est toujours Successfull.

2.- La demande de recréation est réussie À DROITE APRÈS l'opération de tronquage si je cours une nouvelle création deux fois (premier succès, deuxième échec), puis tronquer puis recréer. --very weired

Veuillez me guider sur ce qui se passe et comment faire fonctionner correctement.

Merci!

EDIT:

je remarquai que après avoir appelé

  truncateDatabaseSrv.truncate(); 
programme

se bloque lorsque je tente de collection interroger:

 List<DocType> docTypes = docTypeDAO.getAllDocTypes(); 

donc je mis

 entityManager.createNativeQuery("COMMIT;").executeUpdate(); 

dans la méthode tronquée.

Maintenant, il ne va pas se bloquer et retournera tableau vide comme prévu. Mais encore quand j'appelle la collecte DocType re-init dans la demande suivante, je reçois la même erreur que mentionné ci-dessus.

Aussi je l'ai remarqué Diry vérification qui se passe après troncature:

2:05:04,200 DEBUG AbstractFlushingEventListener:132 - Processing flush-time cascades 
12:05:04,202 DEBUG AbstractFlushingEventListener:174 - Dirty checking collections 
12:05:04,203 DEBUG Collections:189 - Collection found: [com.nws.vedica.model.entity.DocType.fieldValidities#ACCOUNTCONTRACTCANCEL], was: [com.nws.vedica.model.entity.DocType.fieldValidities#ACCOUNTCONTRACTCANCEL] (initialized) 
12:05:04,203 DEBUG Collections:189 - Collection found: [com.nws.vedica.model.entity.DocType.keywords#ACCOUNTCONTRACTCANCEL], was: [com.nws.vedica.model.entity.DocType.keywords#ACCOUNTCONTRACTCANCEL] (initialized) 
12:05:04,204 DEBUG Collections:189 - Collection found: [com.nws.vedica.model.entity.DocType.fieldValidities#ACCOUNTDEBTSLIENCONTRACT], was: [com.nws.vedica.model.entity.DocType.fieldValidities#ACCOUNTDEBTSLIENCONTRACT] (initialized) 

que (initialized) semble suspect pour moi, mais c'est tout ce que je dois cette fois ...

+0

Je suis rouillé avec Hibernate ... Avez-vous essayé quelque chose comme: entityManager.getTransaction(). Commit()? – JFPicard

+0

il échoue dès que vous essayez d'obtenir la forme de transaction em. avant l'opération tronquée. erreur dit quelque chose comme, tx est déjà géré .. (par @Transactional annotation je suppose) – greengold

Répondre

0

Je ne suis pas Bien sûr comment vous le faites, donc je fais des hypothèses ici et je suggère quelque chose comme comment je l'ai fait.J'utilisais Spring/Hibernate et mes annotations transactionnelles étaient présentes sur les deux méthodes commerciales sur le haricot de printemps. Quelque chose comme ça -

@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT) 

Après 1ère méthode de ressort est retourné transaction est engagée depuis qu'il a été gérée par conteneur (non gérées par l'utilisateur que je crois est le cas ici). Ensuite, vous revenez au contrôleur et appelez une autre méthode dans le même service.

Si vous ne voulez pas revenir à votre contrôleur alors je vous suggère d'avoir cette annotation sur votre 2ème méthode et l'appeler de 1ère méthode (ou cependant façon dont vous gérez vos transactions) -

@Transactional(readOnly = false, propagation = *Propagation.REQUIRES_NEW*, rollbackFor = Exception.class, isolation = Isolation.DEFAULT) 

Je pense que cela devrait fonctionner. Ça vaut le coup d'essayer.

+0

même chose arrive. Pour être clair, j'appelle truncate et re-init séparément. après la fin de la requête tronquée, je peux voir que la base de données est effacée, donc ça marche ... c'est quelque chose à propos du gestionnaire d'entité qui lui fait penser que j'ai encore des données tat en place – greengold

+0

Hmm .. si vous avez vu la DB est claire votre client sql fav alors je dirais que cela pourrait être un bug dans votre script de reseed ou le code java. On dirait que vous (ou hibernate) assignez le même PK à plus d'un objet. Juste une intuition. –

+0

aucun script de reseed Im using. ce deuxième appel au service devrait le réappeler. et il a échoué pour la première fois. travaille sur la seconde. Je ne suis pas sûr que tu m'attrapes. que dois-je te montrer de plus? – greengold