Spring Data JPA强制CGLib代理到非存储库类 [英] Spring Data JPA forces CGLib proxying to non repository classes

查看:94
本文介绍了Spring Data JPA强制CGLib代理到非存储库类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将现有的Spring 3 JPA 2 Hibernate Web应用程序迁移到Spring Data JPA. 但是,只需将最新的Spring Data JPA添加到Maven项目并按以下方式配置Spring Data

I am trying to migrate an existing Spring 3 JPA 2 Hibernate web application to Spring Data JPA. However just by adding the latest Spring Data JPA to the Maven project and configuring Spring Data as following

<jpa:repositories 
    base-package="myapp.persistence.spring" 
    entity-manager-factory-ref="entityManagerFactory"
    transaction-manager-ref="transactionManager" />

春天开始抱怨:

2012-07-31 16:54:23,153 ERROR [ContextLoader       ] - [Context initialization failed                                                                       ] - [remoteAddress=, remoteHost=, thread=pool-2-thread-1] org.springframework.web.context.ContextLoader
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'companyRepository' defined in file [C:\Development\ApplicationServer\apache-tomcat-7.0.27\webapps\myapp\WEB-INF\classes\myapp\persistence\CompanyRepository.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469) ~[spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:282) ~[spring-web-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:204) ~[spring-web-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) [spring-web-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4779) [catalina.jar:7.0.27]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5273) [catalina.jar:7.0.27]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.27]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566) [catalina.jar:7.0.27]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556) [catalina.jar:7.0.27]
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) [na:1.6.0_24]
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) [na:1.6.0_24]
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [na:1.6.0_24]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [na:1.6.0_24]
    at java.lang.Thread.run(Thread.java:662) [na:1.6.0_24]
Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
    at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67) ~[spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104) ~[spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112) ~[spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.postProcessAfterInitialization(PersistenceExceptionTranslationPostProcessor.java:133) ~[spring-tx-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    ... 21 common frames omitted

请注意,当上面的错误引用了软件包myapp.persistence中的类时,Spring Data已配置为扫描软件包myapp.persistence.spring.当我将CGlib添加到项目中时,包括Spring Data在内的所有东西都可以正常工作.但是发生了什么事?我是春季新秀,很困惑.我不知道Spring Data是如何做到这一点的.至少官方示例根本不包含CGlib.进一步的信息:

Notice that Spring Data is configured to scan package myapp.persistence.spring while the error above references a class from package myapp.persistence. When I add CGlib to the project everything including Spring Data works fine. But what's happening? I am a Spring rookie and quite puzzled. I could not figure out how Spring Data does it's proxy magic. At least the official examples do not include CGlib at all. Further information:

CompanyRepository是使用EntityManager的简单的自制JPA-DAO:

CompanyRepository is a simple self-made JPA-DAO using EntityManager:

@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class CompanyRepository extends AbstractRepository<Company, Long> {
  …
}

通过@Transactional和AspectJ编译时编织启用事务.上下文配置代码段:

Transactions are enabled via @Transactional and AspectJ compile time weaving. Context configuration snippet:

<tx:annotation-driven proxy-target-class="true" mode="aspectj"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

部署到Tomcat 7.0.27

Deployed to Tomcat 7.0.27

推荐答案

JavaDoc 开始@Repository注释的主要目的是异常转换,它将应用于带有注释的组件.如果您的类实现了接口,则可以使用普通的JDK代理.如果不是(如您所愿),则需要CGLib创建代理.有关详细信息,请参见 Spring参考文档.

As described in the reference documentation using <jpa:repositories /> activates persistence exception translation for Spring beans annotated with @Repository. As of the JavaDoc of @Repository the primary purpose of the annotation is exception translation which will be applied to the component annotated with it. If your class implements an interface plain JDK proxies can be used. If it does not - as in your case - CGLib is required to create the proxy. More details on that in the Spring reference documentation.

要在不使用CGLib的情况下使用<jpa:repositories />,您在方案中实际上有两个选择:

To use <jpa:repositories /> without CGLib you essentially have two choices in your scenario:

  1. 为每个用@Repository注释的组件引入一个接口.这仍然会应用您可能想要的持久性异常转换.
  2. 首先不使用@Repository,而实际上@Component禁用这些组件的异常翻译.
  1. Introduce an interface for each component annotated with @Repository. This will still apply the persistence exception translation which is probably what you want.
  2. Not use @Repository in the first place but rather @Component essentially disabling exception translation for these components.

这篇关于Spring Data JPA强制CGLib代理到非存储库类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆