Hibernate fonction de lecture affiche les données anciennes
J'ai un problème d'affichage de données à partir de la base de données. Si je mettre à jour un objet, parfois, je reçois les données anciennes, parfois la nouvelle. Fonction de mise à jour fonctionne bien (je peux voir en DB à droite de mise à jour), tandis que la fonction de lecture semble pour obtenir des données mises en cache. J'ai essayé de désactiver les caches, a essayé de l'ouvrir et de fermer la session en cours mise à jour/enregistrer, mais ça ne marche toujours pas.
À la fois Utilisateur et de Stocker des haricots ont Paresseux extrait.
Merci!
LA FONCTION DE LECTURE:
public static List<Store> getStoreByUser(User user)
throws HibernateException {
List<Store> result = null;
Session session = sessionFactory.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.getTransaction();
Criteria criteria = session.createCriteria(Store.class);
criteria.add(Restrictions.eq("userUserID", user));
result = criteria.list();
} catch (HibernateException he) {
logger.error("No Store found for user: = " + user, he);
throw he;
}
return result;
}
MISE À JOUR/LA FONCTION DE SAUVEGARDE:
public static Integer insertOrUpdateStore(Store store)
throws HibernateException {
Integer id = null;
Session session = sessionFactory.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.getTransaction();
if (store.getStoreID() != null && store.getStoreID() != 0) {
session.merge(store);
transaction.commit();
} else {
id = (Integer) session.save(store);
transaction.commit();
}
} catch (HibernateException he) {
if (transaction != null) {
transaction.rollback();
}
} finally {
}
return id;
}
OriginalL'auteur Gore | 2012-08-20
Vous devez vous connecter pour publier un commentaire.
Généralement, vous avez une niveau d'isolation "lire commis". Cela permet à votre transaction de voir les modifications qui ont été commis par d'autres transactions. Le niveau d'isolation est mis en œuvre par le sgbd sous-jacent, et non pas par hibernate.
Vous ne pouvez pas désactiver le premier niveau de cache (probablement en utilisant la session sans état, qui ne doit pas être utilisé à des fins générales). Lors de l'exécution d'une requête, NH renvoie toujours les valeurs du cache lorsqu'il est trouvé là, pour s'assurer que vous n'obtenez pas la même db enregistrer plus d'une fois dans la mémoire.
Si c'est un problème pour vous, vous devez passer à un plus haut niveau d'isolation. Par exemple repeatable read (ce qui signifie ce qu'il dit: lors de la lecture des mêmes données plusieurs fois, vous obtiendrez toujours le même résultat). Il y a encore la chance de voir les changements d'autres transactions. En utilisant le niveau d'isolation serializable, vous ne devriez pas avoir ce genre de problème plus.
Remarque: le passage à un autre niveau d'isolation est une modification importante de la plupart des systèmes et doit être soigneusement planifié.
Après quelques essais, j'ai remarqué que les données sont toujours présents, et parfois ils pop up... j'ai probablement besoin d'un frais d'exemple car je ne sais pas ce que je fais mal.
Lire ma réponse attentivement: lors de l'utilisation de "read committed", il peut encore se passer. Vous avez besoin d'élever le niveau d'isolation.
Si j'ai mis de niveau 4 ou 8 (serializable) j'obtiens une erreur: org.mise en veille prolongée.exception à la règle.GenericJDBCException: Verrouillage de délai d'attente dépassé; essayez de redémarrer transaction. C'est probablement un blocage. Je pense que C'est bizarre j'ai ce genre de problème, probablement il ya quelque chose de mal quand j'ai lu ou mettre à jour des données. Ce sujet de la session et de la transaction? Mai j'ai les ouvrir/fermer à chaque fois que je l'ai mise à jour/lire?
Vous devez garder la session et de la transaction pour l'ensemble des processus d'affaires (qui doit être aussi court que possible). Il doit être en cours d'exécution beaucoup en parallèle sur les mêmes données. Des délais d'attente et les blocages dépendent de la mise en œuvre de serializable dans le sgbd sous-jacent. E. g. SQL Server a beaucoup de verrouillage. Oracle est beaucoup mieux. Je me demande ce que vous faites dans ces parallèles transactions ...
OriginalL'auteur Stefan Steinegger
Vous pouvez ouvrir une nouvelle session pour arriver "frais"(mise à jour de la base de données) des données sans les vieilles entités de cache de session. Dans l'exemple ci-dessous, vous pouvez voir comme une entité est l'interrogation de la base de données. Vous pouvez également utiliser le même mécanisme pour retourner l'entité au lieu d'une valeur booléenne, ou appelez
session.Refresh()
(à partir de votre session de cours) pour actualiser les dernières modifications de la base de données:J'espère que cela vous aide.
OriginalL'auteur Carlos
J'ai le même problème, ma requête select * le retour des anciennes données.
J'ai dans mon hibernate.cfg.xml fichier éteint 2ème niveau de cache comme ce
Je vais essayer d'ajouter de la session.flush() ou de la session.clear() avant/après l'opération.commit()
mais il ne donne de résultat positif
OriginalL'auteur mario
Vous pouvez expulser les anciennes données de manière à s'assurer que les données sont lues à partir de db et pas de caches L1 et L2.
Aussi vous devez vous assurer que vous n'êtes pas dans un
REPEATABLE_READ
niveau d'isolation. Dans ce mode d'isolation, il garantit que les deux lectures dans le cadre d'une même opération retourne toujours le même résultat. Comme le niveau d'isolation prend la priorité sur le cache de l'expulsion, le cache expulser n'aura pas d'effet visible.Il est une des façons de contourner ce problème: Déclarer votre niveau d'isolation de transaction à
READ_UNCOMMITTED
ouREAD_COMMITTED
.OriginalL'auteur user1784833