【问题标题】:Why does adding @Transactional causes exception org.springframework.beans.factory.BeanCreationException: Error creating bean with name?为什么添加 @Transactional 会导致异常 org.springframework.beans.factory.BeanCreationException: Error created bean with name?
【发布时间】:2016-02-26 03:42:36
【问题描述】:

我正在使用 Hibernate 学习 Spring,我正在使用我的配置来完全理解它是如何工作的。对此的回答将非常有助于理解正在发生的事情。我对将@Transactional 添加到我的@Repository 对象感到相当困惑。当我添加它时,我得到了错误:

WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'soccerController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.edu.spring.soccer.service.AccountService com.edu.spring.soccer.controller.SoccerController.accountService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accountService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.edu.spring.soccer.dao.AccountDaoImpl com.edu.spring.soccer.service.AccountService.accountDaoImpl; nested exception is java.lang.IllegalArgumentException: Can not set com.edu.spring.soccer.dao.AccountDaoImpl field com.edu.spring.soccer.service.AccountService.accountDaoImpl to com.sun.proxy.$Proxy63
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:298)

但是,当我删除 @Transactional 时,一切正常。我在几个地方读到@Repository 后面应该跟@Transactional

下面你看我的配置。这是带有@Transactional@Repository 对象。请注意,它扩展了一个包含 SessionFactory 对象的 AbstractDao 类。

@Repository
@Transactional //It causes the exception, without it, it works.
public class AccountDaoImpl extends AbstractDao implements AccountDao {

    public void saveAccount(Account account, String password) {
        //Both methods come from AbstractDao
        persist(account); 
        insertPassword(account, password); 
    }

}

但是,当我删除 @Transactional 时,一切正常。我在几个地方读到@Repository 后面应该跟@Transactional

下面你看我的配置:

beans-data.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/jee
 http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/tx  
 http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <context:property-placeholder location="/WEB-INF/spring/environment.properties" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="${dataSource.driverClassName}"
        p:url="${dataSource.url}" p:username="${dataSource.username}"
        p:password="${dataSource.password}" />

<!-- Taken from http://websystique.com/spring/spring4-hibernate4-mysql-maven-integration-example-using-annotations/ -->


    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <value>com.edu.spring.soccer.domain</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop>
            </props>
        </property>
    </bean>

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

    <tx:annotation-driven />
    <context:component-scan base-package="com.edu.spring.soccer.dao" />


</beans>

dispatcher-servlet.xml

我正在对我的所有包进行组件扫描并添加注释驱动。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx  
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <tx:annotation-driven />

    <context:component-scan base-package="com.edu.spring.soccer.controller" />
    <context:component-scan base-package="com.edu.spring.soccer.dao" />
    <context:component-scan base-package="com.edu.spring.soccer.domain" />
    <context:component-scan base-package="com.edu.spring.soccer.service" />

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <mvc:resources mapping="/resources/**" location="/resources/" />

    <mvc:annotation-driven />

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
        p:basename="classpath:/messages" />

</beans>

是否可能与在dispatcher-servlet.xml 中进行组件扫描和&lt;tx:annotation-driven /&gt; 然后再次添加@Transactional?.有关可能这会导致某种冗余。

【问题讨论】:

    标签: spring hibernate spring-mvc transactions


    【解决方案1】:

    我相信这不是因为tx:annotation-driven & @Transactional。无论是否在 Hibernate 中,我很确定 @Transactional 必须用于服务层而不是 @Repository Dao 层。如果您需要处理跨越多个 Daos 的事务怎么办? Dao 应该只是有凝聚力的组件,事务逻辑应该驻留在 Service 层。

    请看 http://www.byteslounge.com/tutorials/spring-with-hibernate-persistence-and-transactions-example

    但我仍然看到@Transactional在Dao层使用的帖子,我不同意。但是如果你坚持使用@Transactional@Repository,也许可以尝试将@Transactional 放在Dao 方法saveAccount 上?

    【讨论】:

    • 非常感谢您的回答,是的,您关于跨 DAO 的事务的示例确实阐明了。该示例的良好链接。我不能将其视为已接受,因为正如您所说,DAO 中仍然存在 Transactional 的地方。实际上,如果我删除 Transactional 它会正常工作,但它不起作用。无论如何感谢您的回答和示例。
    【解决方案2】:

    异常堆栈说明了一切:

    nested exception is java.lang.IllegalArgumentException: Can not set com.edu.spring.soccer.dao.AccountDaoImpl field com.edu.spring.soccer.service.AccountService.accountDaoImpl to com.sun.proxy.$Proxy63
    

    您正在尝试在您的 AccountService 中自动连接 AccountDaoImpl

    但是

    AccountDaoImpl@Transactionnal 注释,所以 Spring 已经“代理”了它... 你应该自动装配接口而不是实现,也就是说,在你的 AccountService改变:

    private AccountDaoImpl accountDaoImpl;

    private AccountDao accountDao;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-06
      • 2015-04-09
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多