org.springframework.beans.factory.BeanCreationException 与事务管理器

org.springframework.beans.factory.BeanCreationException with Transaction Manager

我一直在 Spring 应用程序上研究 Spring MVC,但我正在努力让它工作。

我的应用程序具有以下结构:

我想使用 @Transactional 进行查询,但在 on server start 配置它时收到错误消息spring xml 文件.

WARN : org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'calendarController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.com.milo.repository.CalendarRepository br.com.milo.controller.CalendarController.repository; nested exception is java.lang.IllegalArgumentException: Can not set br.com.milo.repository.CalendarRepository field br.com.milo.controller.CalendarController.repository to com.sun.proxy.$Proxy47
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5253)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5543)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

只有在我的 spring 配置文件中添加以下配置时才会发生此错误:

<tx:annotation-driven transaction-manager="transactionManager"/>    

如果我删除这一行,问题就会消失,Restful 请求工作正常,但是,存储库方法不保存数据。在这种情况下,将显示以下消息(此错误发生在另一个控制器上,因为 Callendar 功能尚未完成。尽管如此,异常是相关的,因为它与事务有关):

Dec 29, 2015 5:03:45 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/milo] threw exception [Request processing failed; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call] with root cause
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:277)
    at com.sun.proxy.$Proxy45.persist(Unknown Source)
    at br.com.milo.repository.FarmRepository.save(FarmRepository.java:28)
    at br.com.milo.controller.FarmController.insertFarm(FarmController.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at br.com.milo.security.CsrfHeaderFilter.doFilterInternal(CsrfHeaderFilter.java:34)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:120)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

这是我的 spring 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
                        http://www.springframework.org/schema/mvc/spring-mvc.xsd
                        http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.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.xsd">

    <mvc:annotation-driven />

    <context:component-scan base-package="br.com.milo" />

    <resources mapping="/resources/**" location="/resources/" />
    <resources mapping="/pages/**" location="/pages/" />
    <resources mapping="/login/**" location="/login/" />

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

    <beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="jsonMessageConverter"/>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </beans:bean>   

    <beans:bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <beans:property name="dataSource" ref="dataSource" />
      <beans:property name="packagesToScan" value="br.com.milo" />
      <beans:property name="jpaVendorAdapter">
         <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
      </beans:property>
      <beans:property name="jpaProperties">
         <beans:props>
            <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</beans:prop>
         </beans:props>
      </beans:property>
   </beans:bean>

   <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <beans:property name="driverClassName" value="org.postgresql.Driver" />
      <beans:property name="url" value="jdbc:postgresql://localhost:5432/milo" />
      <beans:property name="username" value="123" />
      <beans:property name="password" value="123" />
   </beans:bean>

    <beans:bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <beans:property name="entityManagerFactory" ref="myEmf" />
    </beans:bean>
    <!-- Just when I add this line the error above  is shown -->
    <tx:annotation-driven transaction-manager="transactionManager"/>    
</beans:beans>

这里是ClassCalendarController.java

package br.com.milo.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import br.com.milo.domain.Calendar;
import br.com.milo.domain.Owner;
import br.com.milo.domain.DTO.CalendarMonthDTO;
import br.com.milo.repository.CalendarRepository;
@RestController
@RequestMapping("/rest/calendar")
public class CalendarController {

    private static final Logger logger = LoggerFactory.getLogger(CalendarController.class);

    @Autowired
    private CalendarRepository repository;

    @RequestMapping(value = RestPaths.GET_CALENDAR, method = RequestMethod.GET)
    public @ResponseBody Calendar getCalendar(@PathVariable("id") int id) {
        logger.info("Start Get Calendar. ID=" + id);
        return repository.findById(id);
    }

    @RequestMapping(value = RestPaths.LIST_CALENDARS, method = RequestMethod.GET)
    public @ResponseBody List<Calendar> listCalendars() {
        logger.info("Start List Calendars.");
        List<Calendar> calendars = repository.list();
        return calendars;
    }

    @RequestMapping(value = RestPaths.LIST_CALENDAR_BY_OWNER, method = RequestMethod.GET)
    public @ResponseBody List<Calendar> listByOwner(@RequestBody Owner o) {
        logger.info("Start List Calendars By Owner.");
        List<Calendar> calendars = repository.listByType(o);
        return calendars;
    }

    @RequestMapping(value = RestPaths.UPDATE_CALENDAR, method = RequestMethod.POST)
    public @ResponseBody Calendar updateCalendar(@RequestBody Calendar calendar) {
        logger.info("Start Update Calendar.");
        repository.update(calendar);
        return calendar;
    }

    @RequestMapping(value = RestPaths.INSERT_CALENDAR, method = RequestMethod.POST)
    public @ResponseBody Calendar insertCalendar(@RequestBody Calendar calendar) {
        logger.info("Start Insert Calendar.");
        repository.save(calendar);
        return calendar;
    }

    @RequestMapping(value = RestPaths.DELETE_CALENDAR, method = RequestMethod.PUT)
    public @ResponseBody Calendar deleteCalendar(@PathVariable("id") int calendarId) {
        logger.info("Start delete Calendar.");
        Calendar calendar = repository.findById(calendarId);
        repository.delete(calendar);
        return calendar;
    }

    @RequestMapping(value = RestPaths.LIST_CALENDAR_BY_MONTH, method = RequestMethod.GET)
    public @ResponseBody List<Calendar> listByMonth(@RequestBody CalendarMonthDTO calendarDTO) {
        logger.info("Start List Calendar By Month.");
        List<Calendar> calendars = repository.listByMonth(calendarDTO.getOwner(), calendarDTO.getYear(), calendarDTO.getMonth());
        return calendars;
    }

}

这里是classCalendarRepository.java

package br.com.milo.repository;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import br.com.milo.domain.Calendar;
import br.com.milo.domain.Owner;

@Repository
public class CalendarRepository implements br.com.milo.repository.Repository<Calendar, Owner>{

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional
    public void save(Calendar calendar) {
        entityManager.persist(calendar);
    }

    @Override
    @Transactional
    public void update(Calendar calendar) {
        entityManager.merge(calendar);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        this.delete(this.findById(id));
    }

    @Override
    @Transactional
    public void delete(Calendar calendar){
        entityManager.remove(calendar);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Calendar> list() {
        Query query = entityManager.createQuery("from Calendar c order by c.calendarDate DESC");
        return query.getResultList();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Calendar> listByType(Owner o) {

        if(o != null){
            Query query = entityManager.createQuery("from Calendar c join c.ownerList o where o.name = :owner");
            query.setParameter("owner", o.getName());
            return query.getResultList();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public List<Calendar> listByMonth(Owner o, int year, int month) {

        if(o != null){
            Query query = entityManager.createQuery("from Calendar c join c.ownerList o "
                + "where o.name = :owner "
                + "and month(e.calendarDate)=:month "
                + "and year(e.calendarDate)=:year");
            query.setParameter("owner", o.getName());
            query.setParameter("month", month);
            query.setParameter("year", year);
            return query.getResultList();
        }
        return null;
    }

    @Override
    public Calendar findById(Integer id) {
        Calendar calendar = entityManager.find(Calendar.class, id);
        return calendar;
    }

}

提前感谢您关注我的问题!

您在 CalendarController 中的 repository 字段应该由接口定义,而不是 class。 Spring 围绕您的 CalendarRepository 创建了一个 Proxy,它实现了相同的接口,但不是 CalendarRepository.

的子 class

这个问题是关于完全相同的问题:@Autowired return exception on UserDetails in Spring-security

You are trying to autowire your user details service by class, but that can't work, because the spring bean is actually a proxy created around that class (and not an instance of the class). The proxy will however implement all interfaces of the original bean, so injecting by interface is safe.

Exchange this line:

@Autowired
private MyCustomUserDetailsService myCustomUserDetailsService;

for this one:

@Autowired
private UserDetailsService myCustomUserDetailsService;

Read the section on Proxying Mechanisms in the Spring AOP to understand the details.

所以在你的情况下,你可以用你需要的方法创建一个新的 interface CalendarRepository,然后在 class CalendarRepositoryImpl implements CalendarRepository:

中实现
interface CalendarRepository extends br.com.milo.repository.Repository<Calendar, Owner>{
    void save(Calendar calendar);
    void update(Calendar calendar);
    void delete(Integer id);
    ... (and all other methods you need)
}

@Repository
class CalendarRepositoryImpl implements CalendarRepository {
    ... (what you currently have in CalendarRepository)
}

class CalendarController {
    @Autowired
    CalendarRepository repository; // NOT CalendarRepositoryImpl
}