gpt4 book ai didi

java - "Write operations are not allowed in read-only mode"错误 : confused with Spring @Service @transaction @Repository and Hibernate

转载 作者:搜寻专家 更新时间:2023-11-01 02:43:27 27 4
gpt4 key购买 nike

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

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

尝试保存对象时出错,但我仍然找不到确切的错误。

有一个使用 @Service 注释的服务层和一个 save 方法,它应该是事务性的,所以它被注释为 @Transactional(readOnly =假)。对我来说,这意味着 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());
}

AddressDAO 中进行保存时发生错误。它被注释为 @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 创建一个 session 和一个事务以保存在服务层上,而在 DAO 中,hibernate 模板将获取当前 session 并spring 管理的事务并使用它来保存对象。

不过,错误消息让我觉得我的服务方法和 dao 方法不在同一个事务中。

在 servlet-context.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.springframework.beans.factory.BeanCreationException: Error creating bean with name 'addressController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.kog.fable.dao.AddressDAO com.kog.fable.controller.AddressController.addressDAO; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'addressDAO' defined in file [***\com\kog\fable\dao\AddressDAO.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required

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

我读过我可以将刷新模式设置为 AUTO 或将模板上的 setCheckWriteOperations 设置为 FALSE 来解决这类问题并且它似乎有效,但我想这不能确保所有情况下的事务一致性正如我所愿。

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

最佳答案

扩展HibernateDaoSupport时你不会从 Autowiring 中受益,你将不得不覆盖 setSessionFactory方法并放置一个 @Autowired上面的注释。否则它不会工作。

我还希望得到 <tx:annotation-driven />没有那个 @Transactional几乎没用,什么也不做。

关于java - "Write operations are not allowed in read-only mode"错误 : confused with Spring @Service @transaction @Repository and Hibernate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28237252/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com