zhangzhenhuajack / spring-data-jpa-guide

spring-data-jpa-guide,Spring Data JPA实战,SpringDataJpa详解
http://www.jackzhang.cn/spring-data-jpa-guide/
363 stars 157 forks source link

为什么JAP的saveAndFlush之后能取到mysql自增主键实体的ID?背后是什么原理? #61

Open zhangzhenhuajack opened 3 months ago

zhangzhenhuajack commented 3 months ago
  1. 首先 在一个大的事务里面 saveAndFlush 只是代表到数据库里面执行了一下sql语句,不代表事务提交。
  2. save和saveAndFlush的区别是:save不会真正到数据库里面执行,只是在java的session里面保存,之后触发了flush的机制才会执行把save的sql到数据库里面执行一下。

那么当saveAndFlush之后虽然事务没有提交,但是依然可以拿到mysql的自增的ID值,因为save的sql已经到mysql里面执行了。

我们首先打开jpq和mysql的jdbc驱动的日志:

1. datasource的url上面添加:&logger=Slf4JLogger&profileSQL=true 如下:
    url: jdbc:mysql://192.168.3.10:3306/hephaestus_dev?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&logger=Slf4JLogger&profileSQL=true
2. 开启jdbc,hibernate的sql日志:
logging:
  level:
    org.springframework.jdbc.core.JdbcTemplate: DEBUG
    org.springframework.jdbc.core.StatementCreatorUtils: TRACE
    com.zaxxer.hikari.HikariConfig: DEBUG
    com.zaxxer.hikari: TRACE
    org.hibernate.SQL: trace
    org.hibernate.type:
      descriptor:
        sql:
          BasicBinder: trace

测试代码如下: image 日志如下: image debug的过程: image

image

我们看到有一个ok_packet对象,找一下官方文档:

image

参考:https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_ok_packet.html 也就是说JDBC的驱动包里面已经在报文里面给了insert之后产生的自增的ID了。