类与仓库地图

huangapple go评论79阅读模式
英文:

Class with map of repositories

问题

我有一个用于存储库的接口

public interface CrudRepository<T, ID> {
    <S extends T> S save(S entity);

    Optional<T> findById(ID id);

    Class<T> getEntityClass();
}

我需要实现一个类,以提供所有存储库的聚合使用

public class PersistenceManager {
    private final Map<Class<?>, CrudRepository> repositories;

    public PersistenceManager(List<CrudRepository> repository) {
        repositories = repository.stream()
                .collect(Collectors.toMap(
                        CrudRepository::getEntityClass,
                        rep -> rep));
    }

    public void store(EntityWrapper<? extends BaseEntity> entity) {
        Optional.of(repositories.get(next.getType()))
                .orElseThrow(() -> new IllegalStateException("No repository class for entity" + entity.getType()))
                .save(entity.getObject());
    }

    public <T extends BaseEntity, ID> Optional<T> findById(Class<T> clazz, ID id) {
        return Optional.of(repositories.get(clazz))
                .orElseThrow(() -> new IllegalStateException("No repository class for entity" + clazz.getSimpleName()))
                .findById(id);
    }
}

这个实现是可行的,但我担心 CrudRepository 没有参数化。我尝试过类似 CrudRepository<? super BaseEntity, ?> 的方式,但这只适用于 store() 方法。

是否有改进这段代码的方法,使其具备类型参数化,或者保持现状就可以了?

英文:

I have such interface for repository

public interface CrudRepository&lt;T, ID&gt; {
    &lt;S extends T&gt; S save(S entity);

    Optional&lt;T&gt; findById(ID id);

    Class&lt;T&gt; getEntityClass();
}

And I need to implement class which provide aggregated usage of all repositories

public class PersistenceManager {
    private final Map&lt;Class&lt;?&gt;, CrudRepository&gt; repositories;

    public PersistenceManager(List&lt;CrudRepository&gt; repository) {
        repositories = repository.stream()
                .collect(Collectors.toMap(
                        CrudRepository::getEntityClass,
                        rep -&gt; rep));
    }

    public void store(EntityWrapper&lt;? extends BaseEntity&gt; entity) {
        Optional.of(repositories.get(next.getType()))
                .orElseThrow(() -&gt; new IllegalStateException(&quot;No repository class for entity&quot; + entity.getType()))
                .save(entity.getObject());
    }

    public &lt;T extends BaseEntity, ID&gt; Optional&lt;T&gt; findById(Class&lt;T&gt; clazz, ID id) {
        return Optional.of(repositories.get(clazz))
                .orElseThrow(() -&gt; new IllegalStateException(&quot;No repository class for entity&quot; + clazz.getSimpleName()))
                .findById(id);
    }
}

This implementation works but I'm worried that CrudRepository is not parametrised. I've tried something like CrudRepository&lt;? super BaseEntity, ?&gt; but it works only for store() method.

Is there a way to improve this code with type parametrisation or that's ok as is?

答案1

得分: 1

在我看来,这已经足够好了。您的CrudRepository::getEntityClass只能返回与存储库参数类型相同的类。由于这个类是您的映射中的关键,所以在findById()中不可能得到错误的类。

英文:

In my opinion, this is good enough. Your CrudRepository::getEntityClass can only return the same class as the parameter type of the repository. Since this class is the key in your map, it's not possible to get the wrong class in findById()

huangapple
  • 本文由 发表于 2020年5月19日 18:40:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/61889039.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定