“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.

Lors de l'extension de 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