当前位置: 首页 > 知识库问答 >
问题:

“只读模式下不允许写入操作”错误:与Spring@Service@事务@Repository和Hibernate混淆

陈马鲁
2023-03-14

我正在使用Spring和Hibernate处理一个现有的项目,我感到很困惑,因为我得到了一个

org.springframework.dao。InvalidDataAccessApiUsageException:只读模式下不允许写入操作(FlushMode.MANUAL):将会话转换为FlushMode。COMMIT/AUTO或从事务定义中删除“readOnly”标记。

尝试保存对象时出错,但我仍然找不到到底是哪里出错了。

有一个使用@Service注释的服务层和一个保存方法,它应该是事务性的,所以用@Transactional(只读=false)注释。对我来说,这意味着Spring应该自己处理事务。

@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());
    }

地址DAO中执行保存时发生错误。它被注释为@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);
        }
    }
}

我认为会发生的事情是,@Transactional使spring在服务层上创建一个会话和一个事务来保存,而在DAO中,hibernate模板将获得spring管理的当前会话和事务,并使用它来保存对象。

但是,错误消息使我认为我的服务方法和dao方法不在同一事务中。

在 servlet 上下文中.xml有以下语句:

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

在这里,我不明白为什么如果使用组件扫描,DAO bean仍然被显式声明。因为DAO类是用@Repository注释的,所以组件扫描功能不应该能够自己创建这些类吗?因为我认为此配置可能会创建重复的bean,所以我尝试删除xml条目,但随后我开始得到:

org . spring framework . beans . factory . beancreationexception:创建名为“addressController”的bean时出错:自动连接依赖项的注入失败;嵌套异常为org . spring framework . beans . factory . beancreationexception:无法自动连线字段:private com . kog . fablem . Dao . address Dao com . kog . fablem . controller . address controller . address Dao;嵌套异常为org . spring framework . beans . factory . beancreationexception:创建在文件[* * * \ com \ kog \寓言\dao\AddressDAO.class]中定义的名为“addressDAO”的bean时出错:调用init方法失败;嵌套异常是Java . lang . illegalargumentexception:需要“sessionFactory”或“hibernateTemplate”

在这里,我认为对我的Dao的HibernateDaoSupport的扩展会使它们继承sessionFactory和相关方法,所以我不明白会发生什么。

我已经了解到,我可以将刷新模式设置为AUTO,或将模板上的setCheckWriteOperations设置为FALSE,以解决此类问题,这似乎是可行的,但我想这并不能确保所有情况下的事务一致性,正如我所希望的那样。

任何帮助都将不胜感激,因为我对Spring和Hibernate都很陌生,有点困在这里。

共有3个答案

夏侯臻
2023-03-14

进行更改:-

@Configuration
@EnableTransactionManagement   <-----Put this line

public PersistenceConfig{
//your code
}

(或)

@Bean
@Autowired
public HibernateTemplate getHibernateTemplate(SessionFactory session) {
        HibernateTemplate hb = new HibernateTemplate();
        hb.setCheckWriteOperations(false);
        hb.setSessionFactory(session);
        return hb;
    }
滕令雪
2023-03-14

如果您的应用程序是基于Spring MVC的…

应用程序上下文中,尝试这样做..

 <bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  <property name="sessionFactory" ref="yourSessionFactory"></property>
        </bean>

但在dispatcher servlet中(不在appContext中!!!)

<tx:annotation-driven />

不要忘记tx和jar库的名称空间spring tx、spring orm、hibernate core

郎睿
2023-03-14

扩展HibernateDaoSupport时,您将无法从自动装配中受益,您必须覆盖setSessionFactory方法并在其上放置@Autowire注释。否则它将不起作用。

我还期待一个

 类似资料:
  • 我正在使用Spring和Hibernate处理一个现有的项目,我感到困惑,因为我得到了一个 有一个服务层使用进行注释,还有一个方法,该方法应该是事务性的,因此它使用进行注释。对我来说,这意味着spring应该自己处理事务。 在中执行保存时会发生错误。它被注释为。 我认为,让spring在服务层为保存创建一个会话和一个事务,而在DAOs中,hibernate模板将获得spring管理的当前会话和事务

  • 问题内容: 最近,我一直很烦人,但在Google和这个论坛上进行了一些研究之后,我仍然找不到能够解决我的问题的答案。 事情就是这样-有时,当我尝试使用hibernate更新或创建新对象时遇到以下错误: 真正奇怪的是,有时使用该方法更新对象会起作用,但是有时使用相同的对象并通过调用相同的方法却无法起作用,但这似乎取决于我如何在对象中获取对象。第一名。 示例:假设我有一个包含3个字段的表:id,类型,

  • 问题内容: 尝试将对象保存到数据库时遇到了以下错误。我尝试了here1和here2提到的解决方案,但是效果不好。我遵循的是一个教程,但唯一的区别是Spring和Hibernate的版本。 我可以直接使用SessionFactory持久化对象,但是如果我使用HibernateDaoSupport尝试使用此方法,它将失败并显示以下错误 spring.xml CustomerDAOImpl.java 使

  • 问题内容: 我正在尝试运行一个Python脚本,该脚本使用由后链接程序创建的二进制文件(xFiles.bin.addr_patched)。但是,我收到此错误。 当我通过ls-l检查此xFiles.bin的权限时,它表明 我认为错误是因为此文件是由其他应用程序创建的,我正在运行的python脚本无法访问它。因为我是ubuntu的初学者,所以我真的不知道如何解决它。对于如何解决这个问题,有任何的建议吗

  • 嗨,我是java laungage一个有一个映射片段,如果我经常打开对话框并执行一些操作。我得到了 set_timerslack_ns写入失败:不允许操作 我已经尝试过这个解决方案,当运行地图活动时,应用程序崩溃,但问题是一样的。什么时候研发的,它显示在地图碎片上显示对话框导致了这个问题。有没有办法解决...?将标记添加到清单无法解决我的问题。

  • 我收到这个错误,我不知道为什么: SQLException: ResultSet关闭后不允许操作。错误出现在同时(rs1.next()){ 和consultaPortada方法: