“Les opérations d'écriture ne sont pas autorisés en mode lecture seule” erreur : confondre avec le Printemps, @Service @transaction @Référentiel et Hibernate
Je suis en train de travailler sur un projet existant à l'aide de Spring et Hibernate et je suis confus parce que je reçois un
org.springframework.dao.InvalidDataAccessApiUsageException: Écrire
les opérations ne sont pas autorisés en mode lecture seule (FlushMode.MANUEL): Tour
votre Session en FlushMode.S'ENGAGER/AUTO ou supprimer 'readOnly' marqueur
à partir de l'opération de définition.
d'erreur lorsque vous essayez d'enregistrer des objets mais je n'ai toujours pas quel est exactement le problème.
Il y a une couche de service qui est annoté à l'aide de @Service
et un save
méthode qu'il devrait être transactionnelle de sorte qu'il est annoté avec @Transactional(readOnly = false)
. Pour moi, cela signifie que le printemps doit gérer les transactions.
@Service
public class LadyService {
Logger log = Logger.getLogger(LadyService.class);
@Autowired
private PictureDAO pictureDao;
@Autowired
private LadyDAO ladyDao;
@Autowired
private AddressDAO addressDao;
@Transactional(readOnly = false)
public void save(Lady lady) {
Address a = addressDao.getExistingAddress(lady.getAddress());
if (a == null) {
a = addressDao.save(lady.getAddress());
}
lady.setAddress(a);
ladyDao.save(lady);
pictureDao.savePictures(lady.getPictures());
}
L'erreur se produit lors de la réalisation d'une sauvegarde dans le AddressDAO
. Il est annoté comme @Repository
.
@Repository
public class AddressDAO extends HibernateDaoSupport {
public Address save(Address address) {
getHibernateTemplate().save(address); <-- write not permitted error happens here
return address;
}
@SuppressWarnings({ "unchecked" })
public Address getExistingAddress(Address address) {
DetachedCriteria cd = DetachedCriteria.forClass(Address.class);
cd.add(Restrictions.eqOrIsNull("administrative_area_level_1",
address.getAdministrative_area_level_1()));
cd.add(Restrictions.eqOrIsNull("administrative_area_level_2",
address.getAdministrative_area_level_2()));
List<Address> result = (List<Address>) getHibernateTemplate()
.findByCriteria(cd);
if (result.isEmpty()) {
return null;
} else {
return (Address) result.get(0);
}
}
}
Ce que je pensais qui allait arriver était que @Transactional
fait le printemps de créer une session et une opération pour l'enregistrer sur la couche de service, et que, dans le DAOs, hibernate modèle serait d'obtenir la session en cours et de transaction que le printemps gère et l'utiliser pour enregistrer les objets.
Le message d'erreur, si, me fait penser que ma méthode de service et des méthodes dao ne sont pas dans la même transaction.
Dans le servlet-context.xml il y a de ces déclarations:
<annotation-driven />
<context:component-scan base-package="com.kog.fable" />
<beans:bean id="mySessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="myDataSource" />
<beans:property name="packagesToScan">
<beans:array>
<beans:value>com.kog.fable.**.*</beans:value>
</beans:array>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<!-- create, validate, update -->
<beans:prop key="hibernate.hbm2ddl.auto">create</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<beans:prop key="hibernate.connection.pool_size">10</beans:prop>
<beans:prop key="hibernate.connection.autocommit ">false</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="mySessionFactory" />
</beans:bean>
<beans:bean id="addressDAO" class="com.kog.fable.dao.AddressDAO">
<beans:property name="sessionFactory" ref="mySessionFactory" />
</beans:bean>
<beans:bean id="ladyDAO" class="com.kog.fable.dao.LadyDAO">
<beans:property name="sessionFactory" ref="mySessionFactory" />
</beans:bean>
<beans:bean id="pictureDAO" class="com.kog.fable.dao.PictureDAO">
<beans:property name="sessionFactory" ref="mySessionFactory" />
</beans:bean>
Ici, je ne comprends pas pourquoi, si le composant d'analyse est utilisé, les DAO, les haricots sont encore déclaré explicitement. Ne pas le composant de la fonction de balayage être en mesure de créer ces par elle-même depuis le DAO classes annotées avec @Repository
?
Depuis que j'ai pensé à cette configuration pourrait créer des doublons de haricots, j'ai essayé de supprimer les entrées xml, mais ensuite j'ai commencé à avoir:
org.springframework.les haricots.usine.BeanCreationException: Erreur
la création de haricot avec le nom "addressController': Injection de autocâblés
dépendances a échoué; nested exception est
org.springframework.les haricots.usine.BeanCreationException: ne Peut pas
autowire domaine privé: com.kog.fable.dao.AddressDAO
com.kog.fable.le contrôleur.AddressController.addressDAO; imbriqué
exception est org.springframework.les haricots.usine.BeanCreationException:
Erreur lors de la création de haricots avec le nom "addressDAO" n'est pas définie dans le fichier
[***\com\kog\fable\dao\AddressDAO.class]: Invocation de la méthode init
échoué; nested exception java.lang.IllegalArgumentException:
la "sessionFactory" ou "hibernateTemplate" est nécessaire
Ici, je pensais que l'extension de HibernateDaoSupport pour mon DAOs les rendrait hériter de la sessionFactory et les méthodes connexes donc je ne comprends pas ce qui se passe.
Que j'ai lu, j'ai pu choisir la couleur en mode AUTO ou définir la setCheckWriteOperations sur le modèle à FALSE pour résoudre ce genre de problèmes et il semble fonctionner, mais je suppose que cela ne permettrait pas d'assurer que la transaction de la cohérence dans tous les cas comme je le voudrais.
Toute aide serait appréciée comme je suis assez nouveau à Spring et Hibernate et je suis un peu coincé ici.
HibernateDaoSupport
vous ne pourrez pas bénéficier de permettra à l'autowiring, vous devrez remplacer la setSessionFactory
méthode et de mettre un @Autowired
sur elle. Sinon cela ne fonctionnera pas. Je voudrais également s'attendre à une <tx:annotation-driven />
sans que le @Transactional
est assez inutile et ne fait rien.Deinum vous remercie pour votre intervention. En effet, j'ai raté le remplacer, et maintenant que c'est fait, je peux supprimer le dao haricots entrées dans le fichier xml sans erreurs, donc je suppose que maintenant, je suis sûr que les haricots sont instanciés à la fois. Concernant l'annotation-driven tag, c'est une erreur de ma part, j'ai oublié de le copier ici. J'ai cette entrée dans le fichier de configuration:
<tx:annotation-driven transaction-manager="transactionManager" />
de sorte qu'il n'était pas réellement disparu. "Les opérations d'écriture ne permet pas" d'erreur est toujours là.Assurez-vous que vous n'êtes pas à l'analyse pour les mêmes composants que deux fois. Si vous avez un
applicationContext.xml
ou tout fichier qui est chargé par le ContextLoaderListener
assurez-vous que vous n'avez pas la même <context:component-scan />
.Encore merci pour vos commentaires. J'ai vérifié et la configuration semble être correct. J'ai fait des tests un peu plus et en fait après les modifications de votre premier commentaire, il avait résolu mon problème lors de l'appel de la
save
méthode déjà. Le problème était toujours là quand j'ai utilisé une upsert
méthode sans @transactional
annotation qui serait ensuite appeler la save
méthode. Et puis j'ai découvert que c'est normal et que ce upsert
méthode doit avoir la @transactional
annotation pour travailler. Donc, votre commentaire a résolu le problème.Aussi, si vous écrivez votre commentaire, comme réponse, je vais le marquer comme une solution, car il a résolu mon problème.
OriginalL'auteur Flop000 | 2015-01-30
Vous devez vous connecter pour publier un commentaire.
Lors de l'extension de
HibernateDaoSupport
vous ne pourrez pas bénéficier de permettra à l'autowiring, vous devrez remplacer lasetSessionFactory
méthode et de mettre un@Autowired
annotation sur elle. Sinon cela ne fonctionnera pas.Je voudrais également s'attendre à une
<tx:annotation-driven />
sans que le@Transactional
est assez inutile et ne fait rien.Créer un constructeur, autowire que, et de les appeler
setSessionFactory
. De ne pas utiliserHibernateDaoSupport
que ce n'est pas recommandé plusmerci @M. Deinum
OriginalL'auteur M. Deinum
si votre application Spring MVC basé sur...
dans l'application de contexte essayer..
mais dans répartiteur-servlet (pas dans appContext !!!)
N'oubliez pas les espaces de noms pour l'émission, et un pot de bibliothèques printemps-tx,printemps-orm,hibernate-core
OriginalL'auteur Seymur Asadov
Dans le fichier de configuration
faire le changement:-
(OU)
OriginalL'auteur SAN