2009-12-09 5 views
7

J'ai rencontré des questions similaires sur StackOverflow, j'ai essayé les solutions, mais je n'ai pas trouvé de réponse. J'utilise une stratégie JPA assez commune pour définir les dernières heures modifiées sur certaines entités. Définissez les colonnes et les champs, puis marquez une méthode avec @PreUpdate et laissez-les définir l'heure actuelle. Le problème est que je peux voir dans le débogueur que la méthode est appelée et que le champ est en cours de mise à jour, mais dans mes journaux DB, je vois seulement un appel SQL à UPDATE le champ modifié qui n'inclut pas un UPDATE pour le champ d'horodatage. Pour compliquer davantage les choses, @PrePersist fonctionne parfaitement, seul @PreUpdate présente ce comportement.L'appel EclipseLink JPA `@ PreUpdate` n'a pas persisté

L'explication la plus proche que j'ai trouvé jusqu'à présent est à LINK.

Des questions similaires à: # 1725699 et # 1745890

J'utilise EclipseLink v2 et JPA v1 pour la compatibilité avec GlassFish v2.

J'ai essayé d'utiliser les deux annotations directement sur les méthodes de la classe Entity, ainsi qu'un EntityListener attaché à la classe Entity avec l'annotation @EntityListener. Je pense qu'il s'agit d'un bug dans EclipseLink, mais je ne peux pas le prouver. Bug ou pas J'aimerais beaucoup cette opération simple pour travailler. Y a-t-il un problème avec cette implémentation? Est-ce un problème connu dans EclipseLink? Est-ce un problème connu dans JPA? Y a-t-il un moyen de contourner ceci?

A défaut d'accéder à la base de données et d'utiliser des déclencheurs, existe-t-il un autre chemin permettant à mon code Java de définir l'horodatage updated_on?

Merci pour le conseil!

Les extraits de code suivent.

champs Entité:

@Column(name = "updated_on") 
@Temporal(TemporalType.TIMESTAMP) 
private Date updatedOn; 
@Column(name = "created_on") 
@Temporal(TemporalType.TIMESTAMP) 
private Date createdOn; 

méthodes de mise à jour annotés:

@PreUpdate 
public void setUpdatedOn(Timestamped object) { 
    object.setUpdatedOn(new Date()); 
} 

@PrePersist 
public void setCreatedOn(Timestamped object) { 
    if (object.getCreatedOn()==null) { 
     object.setCreatedOn(new Date()); 
    } 
} 

Répondre

4

Le lien que vous fournissez décrit exactement votre situation: pour le contrôle sale, champs mis à jour sont détectés avant que la méthode @PreUpdate est appelée et les modifications de la méthode @PreUpdate ne sont plus détectées. Cela est probablement fait pour des raisons de performances, car les chèques sales peuvent être très coûteux sur les grands graphiques d'objets. Il semble maintenant que vous avez choisi d'utiliser un mécanisme spécifique au fournisseur (DescriptorEvent) ou de passer à Hibernate.

+0

Felix - Je vous remercie de cette précision. Je pensais que c'était ce que je voyais. Je vois comment implémenter la gestion de DescriptorEvent, presque aussi facile que d'annoter quelques méthodes. Il faut juste trouver le bon fichier XML pour ajouter le gestionnaire. Merci encore! – Freiheit

+0

Salut Freiheit, je suis confronté au même problème en ce moment, cela vous dérangerait-il de partager votre code DescriptorEvent par exemple? :) merci – sunnycmf

+0

@Freiheit aimerait voir la solution aussi bien. Merci d'avance. –

3

Mybe un peu tard, mais pour l'exhaustivité des informations ce n'est pas un bug, mais un comportement documenté:

La date ou les types Calendrier sont supposés PAS pour être mutable par défaut, si l'on souhaite Pour appeler les méthodes set sur la date ou le calendrier, le mappage doit être défini sur @Mutable.

Pour les types Date et Calendrier, la propriété de persistance globale "eclipselink.temporal.mutable" peut également être définie sur "true".

donc, que ce soit annoter

@Mutable 
@Column(name = "updated_on") 
@Temporal(TemporalType.TIMESTAMP) 
private Date updatedOn; 

ou définir

<property name="eclipselink.temporal.mutable" value="true" /> 

dans persistence.xml

+0

Merci beaucoup Michele, C'est travailler avec moi comme un charme. –

+0

Vous êtes les bienvenus :) –

+0

J'ai ajouté cette annotation mais cela ne fonctionne toujours pas ([voir ma question] (https://stackoverflow.com/questions/47081932/prepersist-not-working-with-mappedsuperclass-in-hibernate -spring-environnement)). Une idée pourquoi? – displayname

Questions connexes