获取Spring中自定义存储库的域类型

时间:2019-01-07 14:45:37

标签: java spring spring-data-jpa

下午好,这是我在StackOverflow上的第一个问题。

我不是Spring框架的专家,有时我会因为相对容易解决的问题而迷失了很多时间,但是这次我无法真正摆脱它。

我正在尝试在自定义的Spring Data Repository中实现一个方法,该方法应该与多个Entity一起工作,并根据Entity字段上特定注释的存在对数据库执行一些操作。

我已经尝试了很多在Internet上找到的变通办法,但是我实际上无法实现所需的结果。我会尝试更具体:

这是带有注释的示例实体:

@Data
@Entity
@MyAnnotation
public class User{

    @Id
    @MyDataAnnotation
    private Long id;

    @MyDataAnnotation
    private String firstName;

    @MyDataAnnotation
    private String lastName;

    private String userName;
    private int followers;
    private int following;
}

然后在UserService类中添加如下内容:

@Service
public class UserService {

    private final UserRepository repository;

    public void doSomethingOnUser(Long id){
        repository.myCustomMethod(id);
    }
}

对于UserRepository,我做了这样的事情,只是非常基本的东西:

@Repository
public interface UserRepository extends CrudRepository<User,Long>,MyCustomRepository<User,Long> {}

我有自定义的回购界面:

public interface MyCustomRepository<T,ID>{

    public void myCustomMethod(ID id);
}

最后是myCustomMethod的实现:

public class MyCustomRepositoryImpl <T,ID> implements MyCustomRepository{

    @PersistenceContext
    EntityManager entityManager;


    @Override
    public void myCustomMethod(Object id){

        User user = entityManager.find(User.class,id);

        List<Field> markedFields =   MyAnnotationProcessor.getAnnotated(user.getClass());

        //Here I'll manipulate the fields that i've obtained
        ...

        entityManager.persist(u);

        //And then i'm persisting the modified entity
    }
} 

这实际上是与用户实体一起使用的,但是我需要找到一种方法,使其对扩展MyCustomRepository的存储库管理的每个域类型都有效。

例如,如果我有:

public interface WhateverRepository extends CrudRepository<WhateverClass,Long>,MyCustomRepository<WhatheverClass,Long>

myCustomMethod无论如何应该做他的东西。

我尝试做的一件事是使用这段代码来检索Class<T>实例:

 private final Class<T> type;

 public MyCustomRepositoryImpl(Class<T> type) {
      this.type = type;
 }

并使用type代替User.class,但无法加载ApplicationContext:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Class<?>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}`

感谢您阅读到这里,希望您能给我一些提示,如果我不太清楚,请随时向我询问更多信息。

更新

在@amineT回答之后,我尝试使用Spring提供的GenericTypeResolver,但实际上我没有使用null。 documentation指出,如果返回null,则表示它无法解析类型。

这是我使用的代码:

private final Class<?>[] genericType;

    public MyCustomRepositoryImpl(){
        this.genericType = GenericTypeResolver.resolveTypeArguments(getClass(), MyCustomRepositoryImpl.class);
    }

我认为某种程度上,这个“问题”与Spring在幕后所做的所有代理有关,但是我目前没有确切的主意。

如果有人有任何线索,请在此处写下,我们将不胜感激。

2 个答案:

答案 0 :(得分:0)

我遇到了类似的问题,这个answer帮助了我。之所以得到NoSuchBeanDefinitionException,是因为您试图注入一个类类型字段,但没有在Spring上下文中创建一个。您需要做的是使用Spring的GenericTypeResolver查找泛型并相应地处理数据。 希望这会有所帮助

答案 1 :(得分:0)

实际上,我参考了answer指向的@amineT,创建了一个示例项目,看它是否适合您的问题。

根据我的理解,您想要的是确定运行时Bean的类型,而不是CustomRepositoryImpl的类型。构建示例项目后,我发现您的代码几乎正确。

以下是我对您的代码进行处理以使其正常工作的示例:

    @Override
    public void myCustomMethod(Class cls, Object id){

        Object user = entityManager.find(cls,id);

        List<Field> markedFields =   MyAnnotationProcessor.getAnnotated(cls);

        //Here I'll manipulate the fields that i've obtained
        ...

        entityManager.persist(u);

        //And then i'm persisting the modified entity
    }

此外,这是我创建的示例项目的github