【问题标题】:Changes from an inner transaction are not visible from outer内部事务的更改从外部不可见
【发布时间】:2014-04-16 12:47:39
【问题描述】:

我正在尝试更新新事务中的 Company 对象,并希望检索到具有更新参数的相同对象。但它们不是 :( 名称不会改变。'after' 和 'before' 是相同的。数据库已更新,但外部事务不知道这一点。您知道这种情况的任何解决方法吗?

  @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
    public Status newTransactionTest() {
    logger.info("newTransactionTest() INNER");
    Company company = companyDAO.findOne(10000013);
    company.setName(company.getName() + "X");

    return Status.OK;
  }

  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Status test() {
    logger.info("test() BEFORE");
    Company company1 = companyDAO.findOne(10000013);
    String before = company1.getName();

    // run in a new transaction
    applicationContext.getBean(beanName, AdminService.class).newTransactionTest();

    logger.info("test() AFTER");
    Company company2 = companyDAO.findOne(10000013);
    String after = company2.getName();

    logger.info("COMPANY NAME BEFORE: " + before);

    logger.info("COMPANY NAME AFTER: " + after);

    return Status.OK;
  }

日志是:

test() BEFORE
connection: 122 select company0_.name as name7_4_0_ ... where company0_.id=5000062
newTransactionTest() INNER
connection: 123 select company0_.name as name7_4_0_ ... where company0_.id=5000062
connection: 123 update Company set name='TestorexX' where id=5000062
connection: 123 commit
test() AFTER
connection: 122 select company0_.name as name7_4_0_ ... where company0_.id=5000062
COMPANY NAME BEFORE: Testorex
COMPANY NAME AFTER: Testorex

【问题讨论】:

  • test() 方法中的第二个 findOne 不会进入数据库。它只是从一级缓存中返回对象,即相同的对象。要刷新一级缓存,需要clear一级缓存。
  • 你的意思是分离吗?
  • 但我在 JDBC 驱动程序日志中看到有一个对 db 的选择查询
  • 不是来自第二个findOne,而是来自newTransactionTest 方法中的一个。即使有你仍然会从一级缓存中获得相同的 bean 实例,这就是 JPA 的工作方式(并且如规范中所述)。
  • 那么如何从一级缓存中移除这个对象呢?

标签: spring hibernate google-app-engine transactions spring-transactions


【解决方案1】:

好的,我终于修复了这个错误。问题在于我的本地 mySQL 实例上的默认隔离级别和 Cloud SQL 设置为 REPEATABLE-READ。要检查我使用的这些设置:

SHOW VARIABLES WHERE Variable_name ='tx_isolation'

所以我的重复查询返回了相同的结果,因为在 db 级别上完成的兑现不像我在 hibernate/spring 上所期望的那样

为了将 REPEATABLE-READ 更改为 READ COMMITTED,我将其添加到我的 persistence.xml 中

<property name="hibernate.connection.isolation">2</property>

在哪里

1: READ UNCOMMITTED
2: READ COMMITTED
4: REPEATABLE READ
8: SERIALIZABLE

现在一切正常,正如预期的那样。在每个新事务的开始,休眠都会这样做

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED

外部事务从内部看到变化!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-10
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多