【问题标题】:Spring boot is caching results without enabling itSpring boot 正在缓存结果而不启用它
【发布时间】:2020-04-06 07:30:25
【问题描述】:

我几年前一直在使用 Spring Boot,但最近我遇到了一个不寻常的错误。从我的角度应用程序调用 spring boot 应用程序的 GET API 时,它返回的行数少于 DB 上的实际行数。

重新部署 Spring Boot 应用程序后,上述问题已解决。怀疑它是某种缓存问题,我保留了这个标题。

注意:我没有在应用上启用缓存。

另一个嫌疑人是 EntityManager 没有被刷新。我正在使用 Spring 存储库来获取数据,实体管理器不是由我的自定义代码处理的。所以,我不确定这是怎么发生的。

我使用 AWS RDS postgresql 实例作为我的数据库。

追了两天没成功,放在这里征求专家意见

@Data
@EntityListeners(AuditingEntityListener.class)
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "uid_gen_seq")
    @SequenceGenerator(name = "uid_gen_seq", allocationSize = 1)
    @Column(name = "user_id", updatable = false, nullable = false)
    private long userId;
    private String name;
    private String address;
    @Column(name = "ph_no")
    private String phNo;
    @Column(name = "rent_pass")
    private int rentPass;
    @CreatedBy
    private String createdBy;
    @LastModifiedBy
    private String modifiedBy;
}

控制器方法:

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<UserVO>> getAllUsers()
        throws Exception, NoContentException {
    return ResponseEntity.ok(userService.getAllUsers());
}

服务方式:

@Override
public List<UserVO> getAllUsers() throws NoContentException {
    logger.info("Get all users");
    List<User> users = userRepository.findAll();
    List<UserVO> userVOs = converter.convertToVO(users);
    return userVOs;
}

更新:

我想我已将可能的情况缩小到 1 个。那是会话没有刷新。根据我的理解,调用存储库方法会隐式创建一个会话并关闭它。除非服务或控制器方法已使用 @Transactional 注释。

在我的例子中,服务方法没有用@Transactional 注释,会话仍然没有刷新。

作为一种解决方法,我使用 @Transactional(TxType.REQUIRED_NEW) 注释了这些方法,以避免使用任何旧会话。到目前为止,这是有效的,但如果没有这种解决方法,我仍然不相信应用程序的行为。

【问题讨论】:

  • 检查你的hiberante第二层缓存是启用还是禁用
  • 也许你应该向我们展示一些代码和配置。否则我们无能为力
  • @GolamMazidsajib 未启用
  • @SimonMartinelli:这是一个简单的应用程序,这里没有特殊配置

标签: java spring postgresql spring-boot amazon-rds


【解决方案1】:

你是如何插入数据的?如果您没有通过您的应用程序插入,则不会重新加载缓存。 看到这个答案 - Are entities cached in jpa by default?

【讨论】:

  • 数据被插入到同一个应用程序中,使用计划的作业,我没有使用缓存。
  • 一级缓存在hibernate中默认开启,它是会话范围的,你不能禁用它,可能你必须找到一种机制来刷新所有会话缓存。为确保这是问题所在,请在获取数据之前尝试执行 session.refresh()session.flush()
  • 据我了解,这是 L1(持久性上下文)缓存,仅对单个 Hibernate 会话有效。 Spring Repository 使用事务管理在内部关闭会话,除非您使用 @Transaction (但这是另一个讨论)。此外,insert 和 fetch 调用是两个不同的调用,具有很大的时间间隔。正如我在问题中提到的那样,我怀疑这一点,但经过分析,我怀疑是否会出现这种情况
猜你喜欢
  • 2016-08-10
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 2015-10-13
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多