2016-11-25 16 views
1

春のデータリポジトリを扱うときに奇妙な振る舞いを見つけました。春のデータリポジトリStackOverflow

私は、これらのクラスとインタフェースを書いた:私はUserRepositoryImplをテストしようとすると

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

、java.lang.StackOverflowErrorをを

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) 

を投げている私は、保存(といくつかの問題があることを確認)方法。また、delete()メソッドでstackoverflowがスローされます。

私はすでに解決策を見つけました。私の問題は、リポジトリインタフェースを拡張するインタフェースの名前を(例えば)JpaUserRepositoryに変更すると消えます。

質問は「何が起こっているのですか」です。スプリングデータリポジトリを実装するインターフェイス名がパターンと一致すると、stackoverflowがスローされる理由Classnameリポジトリ?

私の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> 

+0

あなたはUserRepositoryImplで電話しますか? UserRepositoryをテストするコード行を投稿してください – emoleumassi

答えて

3

さて、問題はありませんので、理由命名RepositoryClassnameのImplのが、を命名クラス名 RepositoryImplのています。あなたがこれでやっていることは、RepositoryClassnameインターフェイスのいくつかのメソッドに対して、カスタム動作を証明していることをSpringに伝えているです。つまり、春はJpaRepositoryにすべての標準CRUDメソッドを実装しています。実装では、リポジトリBeanを注入できますが、を委任するだけでなく、実装の一部として使用することを意味します。あなたのImplクラスにsave()を実装すると、は実際にはインターフェイスsave()メソッドのカスタム実装を提供しているので、カスタム実装でインターフェイスsave()を呼び出している間は、は無限ループは、stackoverflow例外で終了します。

カスタムビヘイビアを与えない場合は、Implクラスでメソッドを宣言しないでください。一方、いくつかのインタフェースメソッドにカスタム動作を与えようとせず、別のリポジトリを作成しようとしているだけの場合は、RepositoryInterfaceName Implという名前にしないでください。実装を変更しようとしている場合は、interface.save()メソッドを呼び出さないでください。

PS: 通常、永続レイヤーで@Transactionalを使用するのは悪い習慣ですが、ビジネスロジックを処理するため、サービスレイヤーで@Transactionalを使用する方が良いと思います。詳細については、this postを参照してください。

関連する問題