在使用Spring数据存储库时发现一些奇怪的行为。
我写了这些类和接口:
@Transactional(readOnly = true)
public interface UserRepository extends Repository<User, Integer> {
@Transactional
@Modifying
@Query("DELETE FROM User u WHERE u.id=:id")
int delete(@Param("id") int id);
@Transactional
User save(User user);
User findOne(Integer id);
List<User> findAll();
}
public interface AbstractRepository<T> {
T save(T user);
// false if not found
boolean delete(int id);
// null if not found
T get(int id);
List<T> getAll();
}
@Repository
public class UserRepositoryImpl implements AbstractRepository<User> {
@Autowired
private JpaUserRepository repository;
@Override
public User save(User user) {
return repository.save(user);
}
@Override
public boolean delete(int id) {
return repository.delete(id) != 0;
}
@Override
public User get(int id) {
return repository.findOne(id);
}
@Override
public List<User> getAll() {
return repository.findAll();
}
}
当我尝试测试UserRepositoryImpl时,java。lang.StackOverflowerr被抛出
Caused by: java.lang.StackOverflowError
at org.springframework.data.repository.util.ClassUtils.unwrapReflectionException(ClassUtils.java:166)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:505)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:478)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:115)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy55.save(Unknown Source)
at ru.emitrohin.votingsystem.repository.UserRepositoryImpl.save(RestaurantRepositoryImpl.java:24)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
我发现save()方法存在一些问题。此外,delete()方法会引发stackoverflow。
我已经找到了解决办法。当我更改将存储库接口扩展为(例如)JpaUserRepository的接口的名称时,我的问题就消失了。
所以,问题是“发生了什么”。为什么在实现spring数据存储库的接口名与模式ClassnameRepository匹配时抛出stackoverflow?
我的pom。xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>xxx</name>
<url>xxx</url>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<tomcat.version>8.0.33</tomcat.version>
<spring.version>4.3.4.RELEASE</spring.version>
<spring-security.version>4.2.0.RELEASE</spring-security.version>
<spring-data-jpa.version>1.10.4.RELEASE</spring-data-jpa.version>
<!-- Logging -->
<logback.version>1.1.7</logback.version>
<slf4j.version>1.7.21</slf4j.version>
<!--DB-->
<postgresql.version>9.4.1211</postgresql.version>
<!--Tests-->
<junit.version>4.12</junit.version>
<!-- Hibernate -->
<hibernate.version>5.2.4.Final</hibernate.version>
<hibernate-validator.version>5.3.2.Final</hibernate-validator.version>
<!--Tools-->
<ehcache.version>2.10.3</ehcache.version>
</properties>
<build>
<finalName>xxx</finalName>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
<!-- http://stackoverflow.com/questions/4305935/is-it-possible-to-supply-tomcat6s-context-xml-file-via-the-maven-cargo-plugin#4417945 -->
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<container>
<containerId>tomcat8x</containerId>
<systemProperties>
<file.encoding>UTF-8</file.encoding>
<spring.profiles.active>tomcat,datajpa</spring.profiles.active>
</systemProperties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
</container>
<configuration>
<configfiles>
<configfile>
<file>src/main/resources/tomcat/context.xml</file>
<todir>conf/Catalina/localhost/</todir>
<tofile>context.xml.default</tofile>
</configfile>
</configfiles>
</configuration>
<deployables>
<deployable>
<groupId>com.xxx</groupId>
<artifactId>xxx</artifactId>
<type>war</type>
<properties>
<context>${project.build.finalName}</context>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data-jpa.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- spring security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring-security.version}</version>
</dependency>
<!--hibernate-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache.version}</version>
</dependency>
<!--Web-->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Test-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.2.21</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.4</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>hsqldb</id>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.4</version>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
嗯,问题不是因为ClassnameRepositoryImpl命名,而是因为RepositoryClassnameImpl命名。您所做的是告诉Spring,您正在对RepositoryClassname接口上的一些方法进行自定义行为。也就是说,Spring正在为您实现JpaRepository中的所有标准CRUD方法。您的实现允许您注入存储库bean,但它应该作为实现的一部分使用,而不仅仅是用于委托。当您在Impl类中实现保存()时,实际上是为接口保存()方法提供了一个自定义实现,因此,当您在自定义实现中调用接口保存()时,您正在强制执行一个无限循环,最终导致stackoverflow异常。
如果你不打算给出一个自定义行为,就不要在你的Impl类中声明这个方法。另一方面,如果您没有尝试为某些接口方法提供自定义行为,而只是尝试创建一个单独的存储库,那么不要将其命名为RepositoryInterfaceNameImpl。如果您试图修改实现,就不要调用接口。save()方法。
PS:通常在持久层使用@Transactional是一种不好的做法,我认为在服务层使用@Transactional总是更好的,因为它将处理您的业务逻辑。更多信息,请查看此帖子。
我正在努力让Spring JPA Data为我工作,但一直在努力。问题出在这里。 我有两个域类,它们之间有一个简单的一对多关系: 我已经为每个类设置了存储库接口:CardRepository,扩展JpaRepository的用户存储库,两个存储库都注入到服务中 非常基本的设置。someMethod() 出现问题,其中我用它的标识符查询了一个用户,然后尝试获取映射@OneToMany的列表,然后发生
我使用的是spring boot 1.5.2和spring boot数据redis 1.8。 我有两个@Id注释,一个用于JPA,另一个用于redis哈希。这里我想使用由mysql主键自动增量生成的JPA@Id值。 但我发现每次使用redis@Id注释时,redis中我的Id都会是另一个随机值,但我想使用mysql主键。 我的实体是这样的: 我的服务是这样的: 我得到了以下错误: redis的数据
阅读有关在DAO层中使用Java泛型的信息,我怀疑将其应用于spring数据存储库。我的意思是,使用 spring 数据存储库,你有这样的东西: 但是如果我有其他10个实体,我必须创建10个类似于上面的接口来执行CRUD操作等等,我认为这不是很可扩展的。Java Generics和DAO是关于创建一个接口和一个实现,并将其用于实体,但使用Spring数据存储库,我必须为每个实体创建一个界面,因此。
主要内容:1.离线数仓,2.Lambda架构,3.Kappa架构,4.Smack架构,5.湖仓一体传统数仓 离线数仓 实时数仓 Lambda架构 Kappa架构 Smack架构 数据湖架构 仓湖一体架构 1.离线数仓 2.Lambda架构 Lambda架构是大数据平台里最成熟、最稳定的架构,它的核心思想是:将批处理作业和实时流处理作业分离,各自独立运行,资源互相隔离。 (1)Batch Laye:主要负责所有的批处理操作,支撑该层的技术以Hive、Spark-SQL或MapReduce这类批处
英文自我介绍和项目介绍 Good Afternoon, my name is Wang Longjiang,graduated from Anhui University. I have been working in the Institute of Aerospace Information, Chinese Academy of Sciences for two years. Focus o
主要内容:1.ETL,2.ELT,3.ELT的演变,4.ELT的工作原理,5.什么时候我们选择ELT,6.数据湖是不是很好的ELT落脚点,7.总结ETL 和 ELT 有很多共同点,从本质上讲,每种集成方法都可以将数据从源端抽取到数据仓库中,两者的区别在于数据在哪里进行转换 1.ETL ETL - 抽取、转换、加载 从不同的数据源抽取信息,将其转换为根据业务定义的格式,然后将其加载到其他数据库或数据仓库中。另一种 ETL 集成方法是反向 ETL,它将结构化数据从数据仓库中加载到业务数据库中,如我们