繁体   English   中英

在 Spring Data JPA 中,派生的 find 方法在一个事务中多次调用时不使用一级缓存,但默认的 findById 会

[英]In Spring Data JPA, a derived find method doesn't use first-level cache while called multiple times in one transaction, but the default findById does

我在存储库中创建了一个自定义(派生) find 方法:

Optional<User> findUserById(Long id);

它的签名与从JpaRepository继承的默认签名( findById(...)JpaRepository但它们的行为有点不同:

  • 如果派生方法在使用@Transactional的方法内被多次调用,则派生方法似乎不尊重一级缓存(持久上下文),因此,我们得到多个选择语句。
  • 另一方面,默认的findById方法使用一级缓存,并且在与上述相同的条件下,实际只执行一个 select 语句(下一次调用获取缓存的结果)。

即使我的自定义方法也被称为findById也会发生相同的(多选)(但在这种情况下,我们显然不能使用默认方法,因为它被它遮住了)。

有谁知道为什么会这样? 提前致谢。

我正在使用 Spring Boot 2.3.4.RELEASE / Hibernate 5.4.21.Final

下面是一些有意义的代码(完整的测试项目可以在Github上找到):

用户实体

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    @Id
    private Long id;
    private String name;
}

用户存储库

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findUserById(Long id);
}

数据库服务

@Service
@RequiredArgsConstructor
@Slf4j
public class DatabaseService {

    private final UserRepository userRepository;

    @Transactional
    public void testDefaultMethod() {
        log.info("Start to call default findById");
        userRepository.findById(1L);
        userRepository.findById(1L);
        userRepository.findById(1L);
        log.info("End to call default findById");
    }

    @Transactional
    public void testCustomMethod() {
        log.info("Start to call custom findUserById");
        userRepository.findUserById(1L);
        userRepository.findUserById(1L);
        userRepository.findUserById(1L);
        log.info("End to call custom findUserById");
    }
}

调用testDefaultMethod()输出:

2020-10-04 03:11:26.379  INFO 19264 --- [           main] c.e.f.domain.DatabaseService             : Start to call default findById
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from user user0_ where user0_.id=?
2020-10-04 03:11:26.388  INFO 19264 --- [           main] c.e.f.domain.DatabaseService             : End to call default findById

调用testCustomMethod()输出:

2020-10-04 03:11:26.399  INFO 19264 --- [           main] c.e.f.domain.DatabaseService             : Start to call custom findUserById
Hibernate: select user0_.id as id1_0_, user0_.name as name2_0_ from user user0_ where user0_.id=?
Hibernate: select user0_.id as id1_0_, user0_.name as name2_0_ from user user0_ where user0_.id=?
Hibernate: select user0_.id as id1_0_, user0_.name as name2_0_ from user user0_ where user0_.id=?
2020-10-04 03:11:26.500  INFO 19264 --- [           main] c.e.f.domain.DatabaseService             : End to call custom findUserById

在没有查询缓存的情况下,总是针对数据库执行自定义查询。 JPA 不知道您的查询要求什么,因此它无法“猜测”结果。 它需要委托给数据库。

唯一不执行查询的时间是实体已经加载到上下文中并且您直接调用EntityManager.find() (这是默认存储库方法在后台执行的操作)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM