Spring的JPARepository和@Scheduled返回陈旧的数据

e0uiprwp  于 2023-11-19  发布在  Spring
关注(0)|答案(1)|浏览(129)

我有一个简单的应用程序,可以定期从Postgres视图中读取数据。为此,我设置了一个Sping Boot (v3)应用程序,如下所示:

订单实体:

@Entity
@Table(name = "order_view")  //order_view is a view
@Getter
@Setter
@ToString
public class Order implements Serializable {
    @Id
    @Column(name = "ID", columnDefinition = "numeric")
    private Long id;
    
    @Column(name = "CLIENT_NAME")
    private String clientName;
}

字符串

订单回购:

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
   
}

订单服务:

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
    private final OrderRepository orderRepository;
   
    @Override
    @Transactional(readOnly = true)
    public List<Order> getAllOrders() {
        return orderRepository.findAll();
    }
}

**

@Service
@RequiredArgsConstructor
public class SchedulerService {

   private final OrderService orderService;

   @Scheduled(fixedDelay = 5000)
    public void readFromDB() {
        List<Order> orders= orderService.getAllOrders();
        log.debug("DATA: {}", orders);
}


一切正常,但问题是,当视图数据更新时(例如通过另一个应用程序),readFromDB()的输出仍然给我旧数据,而查询视图直接给我最新数据。
甚至我创建了一个rest控制器,如下所示,直接调用OrderService,令人惊讶的是,该控制器还返回一个陈旧的数据,而不是新的:

@GetMapping(path = "/orders")
    public List<Order> getAllData() {
        return orderService.getAllOrders();
 }


我只有在重新启动应用程序后才能获得新数据,而且,当视图更新时,输出不会反映在视图输出中。
现在,当我删除@Scheduled注解(禁用调度程序)时,控制器按预期工作并返回最新数据!
我尝试了很多建议,比如在@Scheduled方法中调用entiyManager.clear(),但都没有成功。此外,我添加了不同传播和隔离类型的@Transactional(),也没有成功。

**

我已经重新测试了这个问题,将不同的实体Map到常规表而不是Map到视图,这个问题不再发生。
另外,我通过@Scheduled方法直接通过JdbcTemplate查询视图,现在我得到了更新的数据。

uyto3xhc

uyto3xhc1#

我认为,你在这种情况下滥用了Hibernate,因为Hibernate并不期望其他任何东西来改变数据。Hibernate主要不是用来读取正在被其他东西更新的数据。至少这是我个人的观点。
如果你有一个小的应用程序,它只对数据库做那么一点事情,我建议你不要使用Hibernate。
但我认为你的问题在于Hibernate缓存:

  • 如果启用了Hibernate L2缓存,则禁用它
  • 您可以尝试使用detach()clear()方法从Hibernate L1缓存中清除会话缓存
  • 或者您可以尝试使用无状态会话

我希望你能解决这个恼人的问题!

相关问题