java - 如何从 SimpleJpaRepository 取回 Repository Interface 对象具有代理解析的对象
问题描述
存储库类
@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>
属于接口 AllFileRepository 的对象,该接口又扩展了 JpaRepository
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'
}
这是示例程序的链接
解决方案
尝试将不兼容的类型相互转换是没有用的。这不是 Spring 问题,而是 Java 基础知识。我已经告诉过你如何在 Spring 中解决这个问题:你需要提供一个实际实现的类AllFileRepository
,并确保 Spring Data JPA 将它用作存储库而不是接口。为此,您需要
- 将接口注释从 更改
@Repository
为@NoRepositoryBean
, - 创建类
@Repository AllFileRepositoryImpl
并在那里提供AllFile findByGuid(String guid)
做一些有意义的事情的实现。
然后您可以轻松地以您想要的方式进行转换,因为您的代理的目标对象将是一个AllFileRepositoryImpl
实例。
我向您发送了一个拉取请求,您只需要接受即可。相关提交 @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");
}
}
推荐阅读
- angular - 如何在 angular2 和 .net 核心应用程序中修复“错误:找不到模块'webpack/lib/dependencies/ContextElementDependency'”!
- c# - C# webclient - 从传输流中接收到意外的 EOF 或 0 字节
- java - Swagger - /api-docs 的自定义身份验证
- amazon-web-services - Moto 不适用于 python 单元测试 setUp() 调用
- vuetify.js - 如何在 vue-cli 项目中动态使用 Vuetify 组件
- java - 如何使用参数形式测试控制器功能?
- python - 使用 PyDev 在 Eclipse 上导入 numpy 时出错
- python - 如何从elasticsearch django返回的查询集中获取数据
- assembly - 当立即打印 mips 中算术运算的结果时,将其直接存储到 $a0 更好吗?
- android - Volley 未在 RecyclerView 中显示数据