1

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

我的配置类:

@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");
    }
}

spring-data-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;
}

然后它起作用了......

但为什么它起作用了?为什么我必须添加两个空构造函数?我试图谷歌它,什么也没找到。我真的很想知道它为什么会这样......任何帮助将不胜感激!

谢谢!

4

1 回答 1

3

您的 bean 被 cglib 代理以启用事务管理。如果我没记错的话,cglib 需要一个默认的构造函数来代理你的 bean。您可能会选择 AspectJ 来代理您的类,因此您不需要默认构造函数。

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

确保 AspectJ 在您的类路径中!

于 2013-05-03T08:10:51.477 回答