为什么我不能在 Spring 中使这个 bean @Transactional ?
我正在编写一个简单的 bean,我想为其配置一个表名、一个包含一些数据的 XML 文件,这样,如果在应用程序启动时表为空,它就会使用该数据进行初始化。我决定使用简单的 SQL 查询,但我无法从 sessionfactory 获取会话,因为它说:
创建 ServletContext 资源 [/WEB-INF/spring/servlet-context.xml] 中定义的名为“vecchiOrdiniFiller”的 bean 时出错:调用 init 方法失败;嵌套异常是 org.hibernate.HibernateException:没有 Hibernate Session 绑定到线程,并且配置不允许在此处创建非事务性会话
但这是配置(与服务非常相似):
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<tx:annotation-driven />
<bean id="ordiniVecchioSistemaLoader" class="it.jsoftware.jacciseweb.assistenza.common.ExcelXmlDataLoader">
<property name="xmlFileName" value="WEB-INF/data/daticlientijaccisemarco.xml"></property>
</bean>
<bean id="vecchiOrdiniFiller" class="it.jsoftware.jacciseweb.assistenza.common.BaseTableFiller" init-method="init">
<property name = "sessionFactory" ref = "mySessionFactory"></property>
<property name="loader" ref="ordiniVecchioSistemaLoader"></property>
<property name="tableCreationString" value="CREATE TABLE `vecchiordini` ( `ID` INT(11) NOT NULL AUTO_INCREMENT, `codicejazz` VARCHAR(255) DEFAULT NULL, `progressivolicenza` INT(11), `codicearticolo` VARCHAR(255) DEFAULT NULL, `rivenditore` VARCHAR(255) DEFAULT NULL, `cliente` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`ID`)) ENGINE=INNODB DEFAULT CHARSET=utf8"></property>
<property name="table" value="vecchiordini"></property>
<property name="tableColumns">
<list>
<value>codicejazz</value>
<value>progressivolicenza</value>
<value>codicearticolo</value>
<value>rivenditore</value>
<value>nomecliente</value>
</list>
</property>
<property name="loaderColumns">
<list>
<value>clicod</value>
<value>licsmatricola</value>
<value>artcod</value>
<value>rivenditore</value>
<value>cliente</value>
</list>
</property>
</bean>
并且我注释了init () 方法与@Transactional。但它不会启动事务,并且我收到该错误:
@Transactional
public void init() throws Exception {
logger.info("BaseTableFilter per tabella: " + table + ", usando: "
+ loader.getSourceName());
Session session = dao.getSession();
Transaction tx = session.beginTransaction();
...
为什么这不起作用?
I'm writing a simple bean that I want to configure with a table name, an XML file with some data, so that if at application startup the table is empty it get initialized with that data. I decided to use simple SQL queries, but I can't get a session from the sessionfactory, because it says:
Error creating bean with name 'vecchiOrdiniFiller' defined in ServletContext resource [/WEB-INF/spring/servlet-context.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
But this is the configuration (very similar to a service):
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<tx:annotation-driven />
<bean id="ordiniVecchioSistemaLoader" class="it.jsoftware.jacciseweb.assistenza.common.ExcelXmlDataLoader">
<property name="xmlFileName" value="WEB-INF/data/daticlientijaccisemarco.xml"></property>
</bean>
<bean id="vecchiOrdiniFiller" class="it.jsoftware.jacciseweb.assistenza.common.BaseTableFiller" init-method="init">
<property name = "sessionFactory" ref = "mySessionFactory"></property>
<property name="loader" ref="ordiniVecchioSistemaLoader"></property>
<property name="tableCreationString" value="CREATE TABLE `vecchiordini` ( `ID` INT(11) NOT NULL AUTO_INCREMENT, `codicejazz` VARCHAR(255) DEFAULT NULL, `progressivolicenza` INT(11), `codicearticolo` VARCHAR(255) DEFAULT NULL, `rivenditore` VARCHAR(255) DEFAULT NULL, `cliente` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`ID`)) ENGINE=INNODB DEFAULT CHARSET=utf8"></property>
<property name="table" value="vecchiordini"></property>
<property name="tableColumns">
<list>
<value>codicejazz</value>
<value>progressivolicenza</value>
<value>codicearticolo</value>
<value>rivenditore</value>
<value>nomecliente</value>
</list>
</property>
<property name="loaderColumns">
<list>
<value>clicod</value>
<value>licsmatricola</value>
<value>artcod</value>
<value>rivenditore</value>
<value>cliente</value>
</list>
</property>
</bean>
and I annotated the init() method with @Transactional. But it doesn't start a transaction and I get that error:
@Transactional
public void init() throws Exception {
logger.info("BaseTableFilter per tabella: " + table + ", usando: "
+ loader.getSourceName());
Session session = dao.getSession();
Transaction tx = session.beginTransaction();
...
why doesn't that work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
init-method
或@PostConstruct
带注释的方法不是代理的,因此您将无法在其上使用 @Transactional。您应该在您的服务上使用@Transactional,为什么这不适合您?引自 SpringSource Jira:
如前所述,您可以尝试
mode="aspectj"
,但我认为您应该检查您的设计。The
init-method
or@PostConstruct
annotated methods are not proxied, so you will not be able to use @Transactional on that. You should use @Transactional on your service, why is that not suitable for you?Quoted from the SpringSource Jira:
As stated, you can try the
mode="aspectj"
but rather you should review your design in my opinion.我认为你不能使 init 方法具有事务性。但您可以从中调用另一个服务的另一个事务方法。
I don't think you can make the init method transactional. But you can invoke another transactional method of another service from it.