此问题是Hibernate方面的:
在我们添加数据时:
Transaction tx = session.beginTransaction();
User user =new User();
user.setName("admin');
session.save(user);
tx.commit();
是这样的一个步骤;
如果我将Hibernate.cfg.xml中的show_sql="true",则
在我tx.commit()提交前,控制台就显示了插入的sql;
而我们在执行update、delete时,在事务提交前是不会在控制台显示sql语句的,而是在事务提交后显示!我想save和update、delete在Hibernate中的操作应该类似呀?难道说save()有一些别的特性吗?
顺便再问一下:
show_sql=true ->如果在客户端显示sql语句,能不能说明访问了数据库呀?
按照对象在Hibernate中的状态,对象可以分为3种:
1 持久态,已经被持久化(保存)到数据库中的对象
2 游离态,对象已经从数据库中Load到缓存中,或者已经被delete,但还没有从缓存中清除
3 瞬态,直接用new运算符产生的对象,还没有进入Hibernate的缓存管辖之下再结合save,update,delete三个接口以及Hibernate的缓存的特点这样就容易理解了:
第一,sql语句,准确说是hql语句的作用是先将对象加入缓存中(如果对象还不再缓存中的话),并在事务提交时候将对象从缓存中持久化到数据库(含insert和update)或者删除(delete)
第二,save只能操作第3类对象,缓存中还不存在该类对象,save之后sql语句就被执行了--只是用于把对象加入到Hibernate的缓存中,只等待提交
delete,update可以操作1,2类对象,由于它们在缓存中已经存在,只等待提交
楼主可以再试一下:你从数据库load一条数据然后把它delete,delete之后立即再save回去,再观察ql语句与commit出现的顺序和你实验的有什么不同
补充一下:hibernate的一个机制 就是懒加载。
像四楼朋友第二点提到的“save之后sql语句就被执行了--只是用于把对象加入到Hibernate的缓存中,只等待提交”----我觉得不能这样理解,因为楼主既然已经save对象了,在没提交事务之前SQL语句就已经发出了,SQL语句只是针对数据库进行的操作,所以此时该对象已经存到数据库了,只是楼主用查询的方式看不到该对象而已,这个可以设置的。要不我们在没有提交事务之前怎么可以回滚事务呢!这个回滚就是针对已经入库但我们还看不到的数据。
而像楼主遇到的这问题,save时我们就按正常的思路去理解,打印出SQL,但当update和delete时,Hibernate先会去从Session缓存中查找对应的对象(update和delete的对象都是库里有的对象),如果缓存中有这对象,Hibernate只会改变缓存中的对象,所以不发SQL,当提交事务后再根据缓存中对象的变动发SQL去操作数据库。
那是因为native是由使用了数据库自增生成策略,执行完save之后session中有个属性叫existIndatabase,他的状态已经为true,说明已经与数据库同步,自然发出sql语句,虽然sql语句已经发出,但是一般在数据库中还是查不出数据,这根数据库的隔离级别有关,只有提交之后惨能查到。
uuid是hibernate定义的一种主键生成策略,当执行save之后只是将数据存储在session管理中,此时existIndatabase的状态为false,也就是未与数据库同步,只有执行了flush方法,才会发出sql。(commit方法的调用会默认先执行以下flush)