java—如何使用代理解析从simplejparepository< t,id>对象获取存储库接口对象

xesrikrc  于 2021-07-23  发布在  Java
关注(0)|答案(3)|浏览(320)

存储库类

@Repository
public interface AllFileRepository extends JpaRepository<AllFile, Long> {
    @Query("SELECT a From AllFile a where a.guid = :guid")
    AllFile findByGuid(@Param("guid") String guid);
}

服务等级

@Service
@Data
public class PipelineService implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    @Autowired
    AllFileRepository allFileRepository;
}

创建对象simplejparepository<allfile,long>

PipelineService pipelineService = new PipelineService();

void methodX() {
    AnnotationConfigApplicationContext applicationContext = (AnnotationConfigApplicationContext) 
    ApplicationContextUtils.getApplicationContext();
    AutowireCapableBeanFactory autowireCapableBeanFactory = 
        applicationContext.getAutowireCapableBeanFactory();
    autowireCapableBeanFactory.autowireBean(pipelineService);
    JpaRepository<AllFile, Long> jpaRepository = (SimpleJpaRepository<AllFile, Long>) 
        AopProxyUtils.getSingletonTarget(pipelineService.getAllFileRepository());

    // (AllFileRepository) jpaRepository casting causes ClassCastException
 }

例外

java.lang.ClassCastException: org.springframework.data.jpa.repository.support.SimpleJpaRepository cannot be cast to ....repository.AllFileRepository

如何获取allfilerepository接口的对象?我可以进入的地方 findByGuid(""); 更新
我能得到 SimpleJpaRepository<AllFile, Long> 属于inturn扩展jparepository的接口allfilerepository

public void initialize() {
        AnnotationConfigApplicationContext applicationContext = (AnnotationConfigApplicationContext) ApplicationContextUtils
                .getApplicationContext();
        EntityManager em = applicationContext.getBean(EntityManager.class);
        AllFileRepository allFileRepository = new JpaRepositoryFactory(em).getRepository(AllFileRepository.class);
        allFileRepository.findByGuid(""); // Method is accessible here but the object is proxy
        SimpleJpaRepository<AllFile, Long> simpleJpaRepository = (SimpleJpaRepository<AllFile, Long>) (AopProxyUtils
                .getSingletonTarget(allFileRepository)); // But proxy resolution yeilds SimpleJpaRepository cannot
                                                         // explicitly cast to AllFileRepository
        ((AllFileRepository) simpleJpaRepository).findByGuid(""); // class
                                                                  // org.springframework.data.jpa.repository.support.SimpleJpaRepository
                                                                  // cannot be cast to class
                                                                  // com.example.spingaoprepository.repository.AllFileRepository
                                                                  // (org.springframework.data.jpa.repository.support.SimpleJpaRepository
                                                                  // and
                                                                  // com.example.spingaoprepository.repository.AllFileRepository
                                                                  // are in unnamed module of loader 'app'

    }

这里有一个链接到示例程序

yebdmbv4

yebdmbv41#

试图将不兼容的类型强制转换为其他类型是没有用的。这不是spring的问题,而是java基础知识。我也已经告诉过您如何在spring中解决这个问题:您需要提供一个实际实现的类 AllFileRepository 确保springdatajpa将其用作存储库而不是接口。为了做到这一点,你需要
更改接口注解 @Repository@NoRepositoryBean ,
创建类 @Repository AllFileRepositoryImpl 并提供了一个 AllFile findByGuid(String guid) 做一些有意义的事情。
然后您可以很容易地按您想要的方式进行强制转换,因为您的代理的目标对象将是 AllFileRepositoryImpl 示例。
我给你发了一个请求,你只需要接受。在相关commit@5705cbb中更改的类如下所示:

package com.example.spingaoprepository.repository;

import com.example.spingaoprepository.model.AllFile;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface AllFileRepository extends JpaRepository<AllFile, Long> {
    @Query("SELECT a From AllFile a where a.guid = :guid")
    AllFile findByGuid(@Param("guid") String guid);
}
package com.example.spingaoprepository.repository;

import com.example.spingaoprepository.model.AllFile;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;

@Repository
public class AllFileRepositoryImpl extends SimpleJpaRepository<AllFile, Long> implements AllFileRepository {
  public AllFileRepositoryImpl(EntityManager em) {
    super(AllFile.class, em);
  }

  @Override
  public AllFile findByGuid(String guid) {
    System.out.println("Finding AllFile by GUID " + guid);
    return null;
  }
}
package com.example.spingaoprepository.serializable;

import com.example.spingaoprepository.repository.AllFileRepository;
import com.example.spingaoprepository.service.PipelineService;
import com.example.spingaoprepository.utils.ApplicationContextUtils;

import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;

public class PipelineConfigurer {
    private ApplicationContext applicationContext = ApplicationContextUtils.getApplicationContext();
    private PipelineService pipelineService = applicationContext.getBean(PipelineService.class);

    public void initialize() {
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        autowireCapableBeanFactory.autowireBean(pipelineService);
        AllFileRepository allFileRepository = (AllFileRepository) AopProxyUtils
                .getSingletonTarget(pipelineService.getAllFileRepository());
        allFileRepository.findByGuid("XY-123");
    }

}
myss37ts

myss37ts2#

您正在使用 new 关键字,然后在methodx()中手动获取spring上下文。
原则上,你当然可以不用Spring手动完成。但是如果您的存储库和服务都是springbean,那么最好让spring来处理bean生命周期。无论如何,这当然更容易。
由于pipelineservice是一个Springbean,您应该让任何使用它的类也能感知spring。所以只需要用一个spring注解来注解这个类,比如 @Component , @Service ,或者 @RestController 如果是控制器。
如果您坚持手动创建bean,那么请尝试-

ApplicationContext context = new AnnotationConfigApplicationContext();
 PipelineService pipelineService = context.getBean(PipelineService.class);
lxkprmvk

lxkprmvk3#

使用@autowired,您正在注入一个实现allfilerepository的对象。这个单例是在启动时创建的,因此您可以使用is allFileRepository.findByGuid("");

相关问题