我正在这个项目中尝试检查事务隔离。我从READ_UNCOMMITTED级别开始,它不起作用。 代码很简单。
主要班级
@SpringBootApplication
@EnableTransactionManagement
public class HibernateTransactionsLocksTestApplication {
public static void main(String[] args) {
SpringApplication.run(HibernateTransactionsLocksTestApplication.class, args);
}
}
控制器
@RestController
public class HomeController {
private final AccountService accountService;
public HomeController(AccountService accountService) {
this.accountService = accountService;
}
@GetMapping("/updateAccount2RU")
public String updateAccount2RU() throws InterruptedException {
accountService.updateAccount2RU();
return "done!";
}
@GetMapping("/update2Account2RU")
public String update2Account2RU() throws InterruptedException {
accountService.update2Account2RU();
return "done!";
}
}
服务
@Service
public class AccountService {
private final AccountRepository accountRepository;
public AccountService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void updateAccount2RU() throws InterruptedException {
Account a = accountRepository.findById(2).get();
System.out.println("Account amount: " + a.getAmount());
a.setAmount(a.getAmount()+1);
accountRepository.save(a);
Thread.currentThread().sleep(5000);
}
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void update2Account2RU() throws InterruptedException {
Account a = accountRepository.findById(2).get();
System.out.println("Account amount: " + a.getAmount());
a.setAmount(a.getAmount()+1);
Thread.currentThread().sleep(5000);
}
}
存储库是一个简单的SpringData存储库
@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {
@Transactional(propagation = Propagation.MANDATORY, isolation = Isolation.READ_UNCOMMITTED)
Account findByName(String name);
}
application.properties
server.contextPath=/
spring.datasource.url=jdbc:mysql://localhost:3306/trasactions-locks-tests
spring.datasource.username=
spring.datasource.password=
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
#spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.jpa.open-in-view=false
#Check transactions behaviour
logging.level.org.springframework.transaction.interceptor=TRACE
基本上,我在Chrome中打开2个标签,并访问updateAccount2RU(这将读取帐户并增加金额,并且线程应在唤醒和提交事务之前休眠5秒钟),与此同时,我访问了第二种方法update2Account2RU读取相同的帐户,并且金额是从第一种方法读取的金额,而不是从更新的方法读取的金额。
答案 0 :(得分:0)
您很可能需要在第一种方法中使用accountRepository.save(a);
。
SQL更新通常由Hibernate缓冲,直到事务提交(即您的事务方法返回)之时为止。
因此,在T2读取记录时,没有待处理的未提交数据库更改。
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void updateAccount2RU() throws InterruptedException {
Account a = accountRepository.findById(2).get();
System.out.println("Account amount: " + a.getAmount());
a.setAmount(a.getAmount()+1);
// force explicit flush so T2 should now see the uncommitted change
accountRepository.saveAndFlush(a);
Thread.currentThread().sleep(5000);
}
请参阅:
https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/objectstate-flushing.html
Session有时会执行所需的SQL语句 使JDBC连接的状态与对象的状态同步 保存在内存中。默认情况下,刷新过程会在 以下几点
- 在执行某些查询之前
- 来自org.hibernate.Transaction.commit()
- 来自Session.flush()