【问题标题】:JpaRepository implementation- Lists vs. SetsJpaRepository 实现 - 列表与集合
【发布时间】:2021-11-03 21:52:20
【问题描述】:

我正在使用 JPA 构建我的第一个 Spring Boot 应用程序,并设置了我的数据存储库和服务,如下所示:

@Repository
public interface FooRepository extends JpaRepository<Foo, Long> {
    Set<Foo> findAllByActiveInstallationIsNull();
}

然后是 CrudService

public interface CrudService<T extends BaseEntity> {
    Set<T> findAll();

    T findById(Long id);

    T save(T object);

    void delete(T object);

    void deleteById(Long id);
}

以及扩展它的示例类服务接口

public interface FooService extends CrudService<Foo> {
    Set<Foo> findAllAvailable();
    Foo getIfAvailable(Long id);
}

服务实现的抽象类

public abstract class AbstractJpaService<T extends BaseEntity, R extends JpaRepository<T, Long>> implements CrudService<T> {
    protected R repository;

    public AbstractJpaService(R repository) {
        this.repository = repository; }

    @Override
    public Set<T> findAll() {
        return new HashSet<>(repository.findAll()); }

    @Override
    public T findById(Long id) {
        return repository.findById(id).orElse(null); }

    @Override
    public T save(T object) {
        return repository.save(object); }

    @Override
    public void delete(T object) {
        repository.delete(object); }

    @Override
    public void deleteById(Long id) {
        repository.deleteById(id); }
}

最后是扩展上述服务类的实际服务类示例:

@Service
@Transactional
public class FooJpaService extends AbstractJpaService<Foo, FooRepository> implements FooService {
    public FooJpaService(FooRepository repository) {
        super(repository);
    }
 ///
}

我编写了一些服务层逻辑、控制器,当我对第一次迭代感到满意后,我就进行了一些邮递员测试,这些测试工作顺利。

然后我退后一步,开始为我的服务类编写一些单元测试,结果发现虽然我的服务中的 findAll() 按我的预期返回 Set,但 JpaRepository 方法和我自己的 repos 扩展为 List。

    @Test
    void findAll() {
        Set<Foo> returnFooSet = new HashSet<>();
        returnFooSet.add(new Foo(boo, 1d, 2d));
        returnFooSet.add(new Foo(baz, 3d, 4d));
        when(fooRepository.findAll()).thenReturn(returnFooSet);
        Set<Foo> foos = service.findAll();

        assertNotNull(foos);
        assertEquals(2, foos.size());
    }

导致 thenReturn() 方法需要一个 List。

对不起,代码墙,但我对此很陌生,非常困惑,所以我想我会提供过多的上下文,即使大多数可以假设,因为我的新手实现可能很奇怪和错误。

那是什么? 我已经阅读了在 JPA 中使用 Sets 的好处,并且我看到的大多数代码示例都使用了它们。 我自己的带有 Set 返回的 findAllByArgument 方法,就像您在存储库中看到的那样工作得很好,所以我认为没有什么能阻止我在我的所有存储库中覆盖基本的 FindAll() 方法(因为 CrudRepository 似乎只有 Iterable 那里),但这似乎...关闭?

我应该在 JPA 中使用 Sets 吗?在这种情况下有哪些好的做法?

【问题讨论】:

    标签: java spring-boot jpa spring-data-jpa spring-data


    【解决方案1】:

    我相信关于JPA 世界中的ListSet 的唯一经验法则(在引擎盖下使用Hibernate)是始终在@ManyToMany 关系上使用Set,而不是List。 除此之外,我不知道其他任何事情。不过,我可以猜测Set 在性能方面可能会更好,因为它是无序的,而List 是有序的。鉴于 JpaRepository 有一个返回 List 的方法,因此最终更好的性能可能不够相关。

    【讨论】:

    • 好的,这很有道理,但是如何让 JpaRepository 方法返回 Set?
    • 假设Set&lt;Foo&gt; findAllByActiveInstallationIsNull(); 工作是唯一的方法。您需要自己添加方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多