Spring Boot应用程序:JPA查询返回旧数据。

5
我们创建了一个使用1.3.5版本的spring boot工程,并且该应用程序与Mysql数据库进行交互。我们创建了一组jpa-repositories,其中使用了findAll、findOne和其他自定义查询方法。
我们正在面对一个随机出现的问题。以下是复现它的步骤:
1. 使用spring-boot应用程序在数据库上执行读取查询。 2. 现在,在mysql控制台中手动更改由上面读取查询返回的记录的数据。 3. 再次使用应用程序执行相同的读取查询。
在第3步之后,我们应该已经收到了第2步修改后的结果,但我们得到的是修改前的数据。
如果我们再次使用应用程序执行读取查询,它会给我们正确的值。
这个问题是随机出现的,我们在应用程序中没有使用任何缓存。
调试时,我发现jpa-repository代码实际上调用了mysql,并获取了最新的结果,但当这个调用返回到我们的应用程序服务时,返回值却有旧的数据。
请帮助我们确定可能的原因。
JPA/数据源配置:
spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/dbname?autoReconnect=true spring.datasource.username=root spring.datasource.password=xxx spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect spring.datasource.max-wait=15000 spring.datasource.max-active=100 spring.datasource.max-idle=20 spring.datasource.test-on-borrow=true spring.datasource.remove-abandoned=true spring.datasource.remove-abandoned-timeout=300 spring.datasource.default-auto-commit=false spring.datasource.validation-query=SELECT 1 spring.datasource.validation-interval=30000 hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.show_sql=false hibernate.hbm2ddl.auto=update 服务方法:
     @Override
    @Transactional
    public List<Event> getAllEvent() {
        return  eventRepository.findAll();
    }

JPARepository:

public interface EventRepository extends JpaRepository<Event, Long> {
    List<Event> findAll();
}

你是否调用了COMMIT;?请展示你的更新查询、数据源和JPA配置。 - Sully
Hitham,我已经在问题本身中更新了详细信息。更新查询仅是更改varchar属性列的值。 - ankur garg
考虑到你在Hibernate后台更改了值,过期的值是否可能来自它的一级缓存? - Andy Wilkinson
@安迪,但是这两个事务完全独立,对应于两个不同的线程。 - ankur garg
你是如何验证这种情况的?提供一个最小化、完整化、可验证化的示例将使人们更容易地看到发生了什么。 - Andy Wilkinson
4个回答

3
@Cacheable(false)

例子:

@Entity
@Table(name="table_name")
@Cacheable(false)
public class EntityName {
    // ...
}

在我的情况下,我在控制器上有一个注释@Cacheable(cacheNames = AppCacheManager.DEFAULT_CACHE),需要找到缓存的替代方案。 - silentsudo

1

这可能是由于一些“脏读”引起的。如果遇到类似问题,请尝试使用事务锁,特别是“可重复读取”,这可能可以避免此问题。如果我说错了,请纠正我。


0

你可以使用

entityManager.refresh(entity)

获取实体的最新值


-1

您可以使用:

@Autowired
private EntityManager entityManager;

在再次查询相同实体之前:

 entityManager.clear();

然后调用查询


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接