Java / Hibernate - les opérations d'Écriture ne sont pas autorisés en mode lecture seule
J'ai eu une fâcheuse exception beaucoup ces derniers temps, et après quelques recherches sur Google et sur ce forum je n'ai toujours pas trouvé une réponse qui pourrait résoudre mon problème.
Voici la chose - parfois, j'ai l'erreur suivante lorsque vous tentez de mettre à jour ou créer un nouvel objet avec hibernate:
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1186)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:696)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:694)
Ce qui est vraiment étrange, c'est que, parfois, quand la mise à jour d'un objet avec la méthode getHibernateTemplate().saveOrUpdate(object);
cela va fonctionner, mais parfois avec le même objet et en appelant la méthode qu'elle ne fonctionne pas, mais il semble dépendre de la façon dont je reçois l'objet dans la première place.
Exemple: disons que j'ai une table avec 3 champs: id, type, longueur. Ce qui peut arriver, c'est que, si je suis l'objet avec l'id et la mise à jour de la longueur, puis il va travailler. Si je reçois par le type et la mise à jour de la longueur, puis ça ne marchera pas. Donc ce que j'ai fait jusqu'à présent pour éviter le problème, c'est de récupérer l'objet de la méthode qui ne posent pas problème à plus tard, mais cela devient de plus en plus et de plus ennuyeux de l'essayer et de trouver un moyen qui fonctionne.
Aussi, maintenant j'ai cette exception lorsque vous tentez de créer un objet (mais pas toutes, seulement sur une table spécifique), et ne peut pas trouver un moyen pour une solution de contournement. Et j'ai essayé d'ajouter @Transactional(readOnly = false)
dans la transaction, mais ça n'a rien changé, et l'affichage de la mode a été de dire que je n'étais pas en lecture seule de toute façon.
Des suggestions?
Modifier 26 juillet:
voici quelques concernant la configuration d'hibernate
<property name="hibernateProperties">
<props>
<prop key="jdbc.fetch_size">20</prop>
<prop key="jdbc.batch_size">25</prop>
<prop key="cglib.use_reflection_optimizer">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="connection.autoReconnect">true</prop>
<prop key="connection.autoReconnectForPools">true</prop>
<prop key="connection.is-connection-validation-required">true</prop>
</props>
</property>
aussi, si ça peut aider
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="execute*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
Modifier le 31 du mois d'août:
Le code dans ma classe qui étend la Classe HibernateDaoSupport
, pour enregistrer les objets est:
public void createObject(Object persisObj) {
getHibernateTemplate().save(persisObj);
}
@Cache
avec READ_ONLY mode? Ou avoir une méthode/classe annotée avec @Transactional(readOnly = true)
quelque part? J'ai couru dans ces sortes de questions moi-même et a constaté que ces deux configurations de jouer un rôle sur cette erreur. Surtout si vous chargez un objet, de le modifier, et persistent encore. Je suis particulièrement pas très friands de l'utilisation de HibernateTemplate
, c'est peut-être de cacher certains de configuration dans le fond. Si vous avez passé quelques extraits de votre configuration, je pourrais être en mesure de vous aider.Merci T l'Homme de prendre le temps de répondre. J'ai donc recherche pour l'un de @Cache/@Transactionnelle dans l'ensemble de mon projet, et il n'y a pas une telle chose (et je n'ai jamais mis dans mon projet). En fait je n'ai pas la configuration de hibernate ou écrire les méthodes, mais je vais ajouter ma configuration dans le poste maintenant. En outre, cette erreur s'affiche lors de la création de certains objets, mais pas tous d'entre eux (toujours le même), de sorte qu'il n'est pas seulement lié à la mise à jour d'un objet
OriginalL'auteur Guillaume | 2011-07-24
Vous devez vous connecter pour publier un commentaire.
J'ai changé la seule session propery de filtre d'affichage. Problème résolu:
J'ai essayé
getHibernateTemplate().getSessionFactory().getCurrentSession().setFlushMode(FlushMode.AUTO);
et mon problème est résolu...OriginalL'auteur Fırat KÜÇÜK
Que le message d'erreur est généralement lors de l'utilisation de la Printemps OpenSessionInViewFilter et en essayant de faire des opérations de persistance à l'extérieur d'un Printemps géré par transaction. Le filtre définit la session de FlushMode.JAMAIS/MANUEL (selon les versions de Spring et Hibernate vous utilisez--ils font à peu près l'équivalent). Au Printemps lorsque le mécanisme de transaction commence une transaction, il change de couleur en mode "validation". Après la fin de la transaction, il met de nouveau à JAMAIS/MANUEL, selon le cas. Si vous êtes absolument sûr que ce n'est pas le cas, alors la prochaine plus probable est non thread-safe utilisation d'une Session. La Session Hibernate doit être utilisé que dans un seul thread. Si il traverse entre les threads, toutes sortes de chaos peut se produire. Notez qu'une entité chargée de veille prolongée peut contenir une référence à la Session dans laquelle il a été chargé, et la remise de l'entité dans les threads peuvent ainsi provoquer la Session pour être accessible à partir d'un autre thread, trop.
La meilleure façon de commencer est probablement ajouter une exception point d'arrêt sur la InvalidDataAccessApiUsageException, et déboguer l'application et de la faire arriver. Ensuite, vérifiez la pile pour voir comment vous avez obtenu l'exception. Surtout vérifier pour voir comment et où la session a été ouverte et si une transaction a été commencé. Vous pouvez dire à certains de partir à l'exception stacktrace, mais l'avoir en direct dans un débogueur, c'est mieux.
Eh bien, je suis toujours bloqué sur cette. J'ai essayé de déboguer la chose, mais ne vois vraiment pas ce que je peux faire. Je ne vois pas de session ou que ce soit. Quelqu'un d'autre a des suggestions?
La réponse est utile même après 7 ans. Je commençais à cette question dans la persistance des données et de la méthode n'a pas été annotée avec @transaction je.e était en dehors de printemps de la transaction.
OriginalL'auteur Ryan Stewart
Je viens de tombé sur cette trop. J'avais besoin de changer la couleur mode du Printemps OpenSessionInViewFilter manuel, et tout à coup j'ai commencé à faire de cette exception. J'ai trouvé que les problèmes ont été hapening dans des méthodes qui n'étaient pas avec l'annotation @Transactional, donc je suppose que le Printemps implicitement traite toutes les données code d'accès en dehors des méthodes telles que la lecture seule. L'annotation de la méthode a résolu le problème.
Une autre façon est d'appeler le setCheckWriteOperations méthode sur la HibernateTemplate objet.
@Transactional
de la méthode (voir mon edit du post pour le code): n'a pas changer quoi que ce soit. Ensuite, j'ai essayé d'appelersetCheckWriteOperations(false);
avant de l'enregistrer, a obtenu l'exception:java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
. Ensuite, j'ai essayé de supprimer le,readOnly
partie de la<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
(voir mon premier montage) et cela a fonctionné! Avec cela,@Transactional
et vérifier la chose n'a pas d'importance, mais je suppose que ce n'est pas une bonne correction. Une idée de pourquoi ce qui se passe?Je n'ai vraiment pas ave un indice. Votre get* propriétés ne serait pas, par hasard, de créer de nouveaux objets? Dire, ajouter une entrée dans un journal de table de base de données ou quelque chose de similaire?
OriginalL'auteur alh84001
ajouter
au-dessus de votre fonction
OriginalL'auteur AhmadReza
Utiliser en dessous de haricot pour HibernateTemplate dans le contexte de l'application.
OriginalL'auteur Amit Sharma
Essayez d'utiliser cette
Le message d'erreur devrait disparaître à mesure que le modèle n'est pas de vérifier si vous êtes en utilisant une transaction.
J'ai essayé
getHibernateTemplate().getSessionFactory().getCurrentSession().setFlushMode(FlushMode.AUTO);
et mon problème est résolu.OriginalL'auteur bigrowedogg
Vous devez oublié d'ajouter @Transactional annotation à votre DAO service de classe/méthode, cela va indiquer que votre opération de base de données seront traitées par le printemps géré transaction.
OriginalL'auteur wise king
Ci-dessous morceau de code est travaillé pour moi.
OriginalL'auteur user3198259
1) ajouter @Transactionnel ci-dessus, vous fonctionnement de base de données et méthodes
2) assurez-vous que vous avez d'annotation piloté l'opération gestionnaire de
ajouter
ci-dessus HibernateTransactionManager de configuration dans applicationContext.xml fichier
OriginalL'auteur user3345582
J'ai eu le même problème et après une journée de recherches, j'ai observé la déclaration suivante
J'ai enlevé
et le problème a disparu
Peut-être que vous devez mettre dans votre fichier de config car à défaut, il a fait des fautes de valeurs d'attribut pour votre gestionnaire de transactions. Ce problème est le résultat de la mauvaise configuration et vous devez trouver ce qui ne va pas
OriginalL'auteur Mihai