[英]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.