此问题是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语句,能不能说明访问了数据库呀?

解决方案 »

  1.   

    发出sql语句不代表就提交事务啊 你可以debug的方式跟踪看看 改变数据的时候它会自动提交 有脏数据检查 和数据库同步
      

  2.   

    第一个问题不确定,但hibernate的show_sql应该是在执行前显示。hibernate的工作顺序大概是获得请求后把java转化成sql,显示sql,发送sql到数据库,然后等待数据库返回结果……………… save和update的区别应该只在于一个是insert一个是update,不知道为何你提交的时候出现的顺序不一样。第二个问题,hibernate里show_sql显示出的SQL并不代表被成功执行,这应该只是hibernate打印到终端的文字,而实际执行的显示应该是数据库的打印输出,这两个的区别应该在此。以MYSQL为例,在MYSQL的LOG里看到的SQL才是执行后的,而你软件里log4j之类的输出只是一个显示。
      

  3.   

    这个和Hibernate缓存中的持久化对象状态有关
    按照对象在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出现的顺序和你实验的有什么不同
      

  4.   

    java技术讨论群100756746,希望大家加入,我们共同讨论,共同进步!
      

  5.   


    补充一下:hibernate的一个机制 就是懒加载。
      

  6.   

    我觉的楼主的问题应该从数据库和缓存的对比一致性上来分析
    像四楼朋友第二点提到的“save之后sql语句就被执行了--只是用于把对象加入到Hibernate的缓存中,只等待提交”----我觉得不能这样理解,因为楼主既然已经save对象了,在没提交事务之前SQL语句就已经发出了,SQL语句只是针对数据库进行的操作,所以此时该对象已经存到数据库了,只是楼主用查询的方式看不到该对象而已,这个可以设置的。要不我们在没有提交事务之前怎么可以回滚事务呢!这个回滚就是针对已经入库但我们还看不到的数据。
    而像楼主遇到的这问题,save时我们就按正常的思路去理解,打印出SQL,但当update和delete时,Hibernate先会去从Session缓存中查找对应的对象(update和delete的对象都是库里有的对象),如果缓存中有这对象,Hibernate只会改变缓存中的对象,所以不发SQL,当提交事务后再根据缓存中对象的变动发SQL去操作数据库。
      

  7.   

    HIBERNATE是尽量延迟向数据库执行SQL。但是save是立即执行的,因为需要得到数据库的ID。
      

  8.   

    save之后未提交就有sql发出,说明你的主键生成策略是native(increment)也就是自增型,如果是uuid就不会发出,你可是试试看
    那是因为native是由使用了数据库自增生成策略,执行完save之后session中有个属性叫existIndatabase,他的状态已经为true,说明已经与数据库同步,自然发出sql语句,虽然sql语句已经发出,但是一般在数据库中还是查不出数据,这根数据库的隔离级别有关,只有提交之后惨能查到。
    uuid是hibernate定义的一种主键生成策略,当执行save之后只是将数据存储在session管理中,此时existIndatabase的状态为false,也就是未与数据库同步,只有执行了flush方法,才会发出sql。(commit方法的调用会默认先执行以下flush)