ams*_*ger 3 java spring hibernate spring-data-jpa spring-boot
我在存储库中创建了一个自定义(派生)查找方法:
Optional<User> findUserById(Long id);
findById(...)它的签名与继承自的默认签名 ( ) 相同,JpaRepository但它们的行为有点不同:
@Transactional,因此,我们会得到多个 select 语句。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()直接调用时(这是默认存储库方法在后台执行的操作)。
| 归档时间: | 
 | 
| 查看次数: | 1486 次 | 
| 最近记录: |