hibernate中持久化对象的生命周期分为三个状态:自由态、持久态和游离态:
- 自由态的对象只存在于内存,不在数据库里也不再session里;
- 持久态的对象与session关联并且在数据库中有相应数据;
- 游离态的对象脱离了session,只存在数据库;
对自由态进行sql语句的操作会将自由态转为持久态,当session清理缓存时持久态会变成游离态。而游离态再被执行sql语句的操作时会变成持久态,如果被delete则会从持久态变成自由态。
然后再说说@Transactional的自动save。我的理解是在服务里进行findbyxx、findall等将持久化对象从游离态转为持久态,当事务结束的时候就会自动再将持久态转 回游离态。就是通过jpa取出来的实体类,对它进行set或者其他的操作,在事务结束时会自动提交并保存到数据库内。
使用spring data jpa时,关于service层一个方法中进行【删除】和【插入】两种操作在同一个事务内处理 执行spring data的delete操作,并不会立即执行,而是等到service方法执行完成,才会提交事务。但是这样的话 insert插入就会出现 重复数据存在,不能重复插入的错误!!!
理一下这个逻辑:【spring的事务@Transactional底层是spring AOP】
- 进入方法,开启事务
- 代码delete方法是jpa的delete方法,断点在此处发现并没有执行delete的sql语句,但是执行了一条select语句。【可见自定义的delete方法是根据查到的数据再拼接sql在事务提交的时候才执行】
- 执行save的插入方法,执行了insert语句,报错数据已经存在,不能重复插入
- 关闭事务
解决方案1:
仅更改service代码
手动调用flush()方法,【让jpa在selete出这个对象之后,拼接了delete语句,然后即刻执行sql作用到数据库】,这样在下面insert的时候delete已经执行了,就不会出现重复数据的错误。
解决方案2:
仅改变dao层代码,就是写@Query(“JPQL语句”)
告诉jpa,我要明确执行这条delete的sql语句,避免了【让它去查一遍,拿到实体以后再拼接SQL语句,最后在方法结束,事务提交的时候才去执行delete语句】,这个时候已经迟了。
这个时候是不会执行select语句的,只执行了delete和insert
关于级联关系的删除 https://blog.csdn.net/liyiming2017/article/details/90218062



