Spring 数据存储库 StackOverflow
Spring Data Repository StackOverflow
在使用 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.WhosebugError 被抛出
Caused by: java.lang.WhosebugError
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.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() 方法也会抛出 Whosebug。
我已经找到解决办法了。当我将扩展 Repository 接口的接口名称更改为(例如)JpaUserRepository 时,我的问题就消失了。
所以,问题是"What is going on"。为什么当实现 spring 数据存储库的接口名称与模式 ClassnameRepository 匹配时抛出 Whosebug?
我的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>
<!-- -->
<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 class、 中实现 save() 时,您实际上是在为接口 save() 方法提供自定义实现,因此,当您调用接口 save()在您的 "custom" 实现中,您正在强制执行无限循环,最终导致 Whosebug 异常。
如果您不打算提供自定义行为,请不要在您的 Impl 中声明该方法 class。另一方面,如果您不想为某些接口方法提供自定义行为,而只是想创建一个单独的存储库,请不要将其命名为 RepositoryInterfaceNameImpl。如果您试图修改实现,请不要调用 interface.save() 方法。
PS:
通常在持久层使用@Transactional 是一种不好的做法,我认为在服务层使用@Transactional 总是更好,因为它将处理您的业务逻辑。查看 this post 了解更多信息。
在使用 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.WhosebugError 被抛出
Caused by: java.lang.WhosebugError
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.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() 方法也会抛出 Whosebug。
我已经找到解决办法了。当我将扩展 Repository 接口的接口名称更改为(例如)JpaUserRepository 时,我的问题就消失了。
所以,问题是"What is going on"。为什么当实现 spring 数据存储库的接口名称与模式 ClassnameRepository 匹配时抛出 Whosebug?
我的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>
<!-- -->
<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 class、 中实现 save() 时,您实际上是在为接口 save() 方法提供自定义实现,因此,当您调用接口 save()在您的 "custom" 实现中,您正在强制执行无限循环,最终导致 Whosebug 异常。
如果您不打算提供自定义行为,请不要在您的 Impl 中声明该方法 class。另一方面,如果您不想为某些接口方法提供自定义行为,而只是想创建一个单独的存储库,请不要将其命名为 RepositoryInterfaceNameImpl。如果您试图修改实现,请不要调用 interface.save() 方法。
PS: 通常在持久层使用@Transactional 是一种不好的做法,我认为在服务层使用@Transactional 总是更好,因为它将处理您的业务逻辑。查看 this post 了解更多信息。