2013-05-02 128 views
1

我对Spring Data和Neo4j很陌生,有些我不明白使用@Transactional注释。看来我必须为一个类声明一个空的构造函数,我用@Transactional注释了它的一个方法,而且我还需要为事务将使用的节点实体类创建一个空的构造函数...(如果我不没有声明空构造函数,我得到一个异常)。但是..也许我错过了一些东西。我会给你举个例子,下面是一个例子代码,它演示了我在说什么(它是一个简短的spring-data-neo4j设置,可以启动并运行):Spring Data Neo4j - 尝试使用@Transactional注解时出现异常

我的配置类:

@Configuration 
@ComponentScan(basePackages={"org.technion.socialrescue.core"}) 
@ImportResource("spring-data-context.xml") 
@EnableTransactionManagement 
public class DefaultApplicationConfig { 
    @Bean(destroyMethod = "shutdown") 
    public GraphDatabaseService graphDatabaseService() { 
     return new EmbeddedGraphDatabase("target/graph.db"); 
    } 
} 

弹簧数据-context.xml文件:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:neo4j="http://www.springframework.org/schema/data/neo4j" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd"> 


    <neo4j:config graphDatabaseService="graphDatabaseService" /> 
    <neo4j:repositories base-package="org.technion.socialrescue" /> 
</beans> 

承载标有@Transactional方法的类:

@Component("someClass") 
public class SomeClass { 

    public SomeObjectRepository someObjects;  

    @Autowired 
    public SomeClass(SomeObjectRepository someOBjects) { 
     this.someObjects = someOBjects; 
    } 

    @Transactional 
    public void someMethod() { 
     someObjects.save(new SomeObject("roy"));   
    } 
} 

的SomeObject类(其将在图中被用作节点):

@NodeEntity 
public class SomeObject { 

    public SomeObject(String name) { 
     this.name = name; 
    } 

    @GraphId 
    private Long id;  

    @Indexed 
    String name; 
} 

的SomeObjectRepository接口:

package org.technion.socialrescue.core; 

import org.springframework.data.neo4j.repository.GraphRepository; 

public interface SomeObjectRepository extends GraphRepository<SomeObject> { 

} 

和代码启动该应用程序:

public class Playground { 

    public static void main(String[] args) { 
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DefaultApplicationConfig.class); 
     SomeClass someClass = (SomeClass)context.getBean("someClass"); 
     someClass.someMethod(); 
     context.close(); 
    } 
} 

因此,通过运行上面的代码,我收到以下异常:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someClass' defined in file [C:\Users\t-rvelic\workspace\social-rescue\target\classes\org\technion\socialrescue\core\SomeClass.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.technion.socialrescue.core.SomeClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) 
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73) 
    at org.technion.socialrescue.playground.Playground.main(Playground.java:13) 
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.technion.socialrescue.core.SomeClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given 
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:217) 
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111) 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477) 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362) 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) 
    ... 10 more 
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given 
    at org.springframework.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721) 
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:499) 
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33) 
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) 
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) 
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) 
    at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285) 
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205) 
    ... 17 more 

所以我试图跟随原因此异常,并添加一个空的构造为SomeClass,所以它看起来是这样的:

@Component("someClass") 
public class SomeClass { 

    public SomeObjectRepository someObjects; 

    public SomeClass() { 

    } 

    @Autowired 
    public SomeClass(SomeObjectRepository someOBjects) { 
     this.someObjects = someOBjects; 
    } 

    @Transactional 
    public void someMethod() { 
     someObjects.save(new SomeObject("roy"));   
    } 
} 

然后,我又开始了我的应用程序,并得到了以下异常:

Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: SomeObject: entity must have a no-arg constructor.; nested exception is java.lang.IllegalArgumentException: SomeObject: entity must have a no-arg constructor. 
    at org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:43) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at com.sun.proxy.$Proxy39.save(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at com.sun.proxy.$Proxy40.save(Unknown Source) 
    at org.technion.socialrescue.core.SomeClass.someMethod(SomeClass.java:23) 
    at org.technion.socialrescue.core.SomeClass$$FastClassByCGLIB$$d9c3b9ef.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) 
    at org.technion.socialrescue.core.SomeClass$$EnhancerByCGLIB$$d5a7b8cd.someMethod(<generated>) 
    at org.technion.socialrescue.playground.Playground.main(Playground.java:17) 
Caused by: java.lang.IllegalArgumentException: SomeObject: entity must have a no-arg constructor. 
    at org.springframework.data.neo4j.support.mapping.AbstractConstructorEntityInstantiator$1.create(AbstractConstructorEntityInstantiator.java:87) 
    at org.springframework.data.neo4j.support.mapping.AbstractConstructorEntityInstantiator.createEntityFromState(AbstractConstructorEntityInstantiator.java:56) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedInstantiator.createEntityFromState(Neo4jEntityPersister.java:135) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedInstantiator.createEntityFromState(Neo4jEntityPersister.java:122) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:86) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.read(Neo4jEntityPersister.java:170) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:189) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:244) 
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:231) 
    at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:293) 
    at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:287) 
    at org.springframework.data.neo4j.repository.AbstractGraphRepository.save(AbstractGraphRepository.java:109) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
    ... 28 more 

所以这一次,我添加一个空的构造为SomeObject类,它看起来就像是:

@NodeEntity 
public class SomeObject { 

    public SomeObject() { 

    } 

    public SomeObject(String name) { 
     this.name = name; 
    } 

    @GraphId 
    private Long id;  

    @Indexed 
    String name; 
} 

然后它的工作...

但为什么它的工作?为什么我不得不添加两个空构造函数?我试图谷歌它,什么都没发现。我真的很想知道为什么它会这样...任何帮助将不胜感激!

谢谢!

回答

3

cglib正在代理您的bean以启用事务管理。如果我没有弄错,cglib需要一个默认的构造函数来代理你的bean。你可以选择AspectJ代理你的类,所以你不需要默认的构造函数。

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ) 

确保AspectJ在您的类路径中!

+0

谢谢...即使这对我来说都很神奇......我不知道为什么这些东西可以帮助/工作......:-) – gipouf 2013-05-03 09:55:11

+1

我建议你阅读[参考手册](http://static.springsource.org/spring-data/data-neo4j/docs/current/reference/htmlsingle/),那里解释了所有的魔法。 :-) – tstorms 2013-05-03 10:24:23

+0

UPDATE: 嗯,我还需要每当我​​跑这条线来定义SomeObject一个空的构造: '页页= someClass.someObjects.findAll(新PageRequest(0,10));' 我在手册中找不到关于它的任何项目。 – gipouf 2013-05-03 12:22:03

相关问题