我对 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;
}
然后它起作用了......
但为什么它起作用了?为什么我必须添加两个空构造函数?我试图谷歌它,什么也没找到。我真的很想知道它为什么会这样......任何帮助将不胜感激!
谢谢!