gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-05 02:04:43 43 4
gpt4 key购买 nike

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

Optional<User> findUserById(Long id);

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

  • 如果在方法内部使用 @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 不知道您的查询要求什么,因此它无法“猜测”结果。它需要委托(delegate)给数据库。

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

关于java - 在 Spring Data JPA 中,派生的 find 方法在一个事务中多次调用时不使用一级缓存,但默认的 findById 会,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64190242/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com