gpt4 book ai didi

java - 更新数据库列后检索它的值

转载 作者:行者123 更新时间:2023-11-29 06:43:09 26 4
gpt4 key购买 nike

提前抱歉,帖子很长。我正在使用一个Java WebApplication,它使用Spring(2.0,我知道...)和带有Hibernateimplementation的Jpa(使用hibernate 4.1和hibernate-jpa-2.0.jar)。更新数据库表(MySql 5)后,我在检索列的值时遇到问题。这是我的情况(简化,但这是它的核心):

KcUser:

    Id:Long (primary key)
Name:String
.
.
.
Contract_Id: Long (foreign key, references KcContract.Id)

KcContract:

    Id: Long (primary Key)
ColA
.
.
ColX

在我的服务器中,我有这样的内容:

MyController {
myService.doSomething();
}


MyService {

private EntityManager myEntityManager;

@Transactional(readOnly=true)
public void doSomething() {
List<Long> IDs = firstFetch(); // retrieves some users IDs querying the KcContract table
doUpdate(IDs); // updates a column on KcUser rows that matches the IDs retrieved by the previous query
secondFecth(IDs); // finally retrieves KcUser rows <-- here the returned rows contains the old value and not the new one i updated in the previous method
}

@Transactional(readOnly=true)
private List<Long> firstFetch() {
List<Long> userIDs = myEntityManager.createQuery("select c.id from KcContract c" ).getResultList(); // this is not the actual query, there are some conditions in the where clause but you get the idea

return userIDs;
}

@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW)
private void doUpdate(List<Long> IDs) {
Query hql = myEntityManager().createQuery("update KcUser t set t.name='newValue' WHERE t.contract.id IN (:list)").setParameter("list", IDs);
int howMany = hql.executeUpdate();
System.out.println("HOW MANY: "+howMany); // howMany is correct, with the number of updated rows in DB

Query select = getEntityManager().createQuery("select t from KcUser t WHERE t.contract.id IN (:list)" ).setParameter("list", activeContractIDs);
List<KcUser> users = select.getResultList();
System.out.println("users: "+users.get(0).getName()); //correct, newValue!
}

private void secondFetch(List<Long> IDs) {
List<KcUser> users = myEntityManager.createQuery("from KcUser t WHERE t.contract.id IN (:list)").setParameter("list", IDs).getResultList()

for(KcUser u : users) {
myEntityManager.refresh(u);
String name = u.getName(); // still oldValue!
}
}
}

奇怪的是,如果我注释对第一个方法( myService.firstFetch() )的调用,并使用常量 ID 列表调用其他两个方法,我会在 secondFetch( 中获得正确的新 KcUser.name 值。 ) 方法。

我对 Jpa 和 Hibernate 不是很专家,但我认为这可能是缓存问题,所以我尝试过:

  • 更新后使用 myEntityManager.flush()
  • 使用 myEntityManager.clear() 和 myEntityManager.getEntityManagerFactory().evictAll() 清除缓存;
  • 使用 hibernate Session.clear() 清除缓存
  • 在 KcUser 实体上使用 myEntityManager.refresh
  • 使用 native 查询 (myEntityManager.createNativeQuery("")),据我了解,这不应涉及任何缓存

这些都不起作用,我总是返回 secondFetch() 中的旧 KcUser.name 值。方法。

到目前为止唯一有效的是:

  • 制作 firstFetch()方法 public 并将其调用移到 myService.doSomething() 之外,因此在 MyController 中执行类似的操作:

    List<Long> IDs = myService.firstFetch();
    myService.doSomething(IDs);

  • secondFetch(中使用新的EntityManager ),所以做这样的事情:

EntityManager newEntityManager = myEntityManager.getEntityManagerFactory().createEntityManager();

并使用它执行后续查询以从数据库中获取用户

使用最后两种方法中的任何一种,第二个选择工作正常,我让用户在“名称”列中获得更新的值。但我想知道到底发生了什么以及为什么其他事情都不起作用:如果它实际上是一个缓存问题,那么简单 .clear().refresh()我认为应该有效。或者也许我完全错了,它根本与缓存无关,但是我对实际可能发生的事情有点迷失了。

我担心我们使用 hibernate/jpa 的方式可能有问题,这可能会在将来困扰我们。有什么想法吗?如果您需要更多详细信息,请告诉我,感谢您的帮助。

最佳答案

操作按以下顺序执行:

  1. 只读事务 A 打开。
  2. 第一次获取(事务 A)
  3. 非只读事务B打开
  4. 更新(事务 B)
  5. 交易 B 结束
  6. 第二次获取(事务 A)
  7. 交易 A 结束

事务 A 是只读的。该事务中的所有后续查询只能看到事务开始之前提交的更改 - 您的更新是在事务开始之后执行的。

关于java - 更新数据库列后检索它的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50696560/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com