当前位置: 首页 > 图文教程 > 网络编程 > JSP > Eclipse开发Hibernate应用程序

JSP
Java 创建cookie和删除cookie
jsp 从web.xml读取连接数据库的参数
jsp 不支持EL表达式,解决办法
jsp 获取客户端的浏览器和操作系统信息
struts2 session 解读
struts2 spring整合fieldError问题
jsp 生成验证码代码
搭建java WEB开发环境和应用
JSP 自定义标签
Java 区分文本中的中英文字符函数
通用JSP页面 jsp入门级文章
jsp struts1 标签实例详解
一个jdbc 测试程序代码
SSH整合中 hibernate托管给Spring得到SessionFactory
jsp SmartUpload 实现上传功能代码
jsp Unsupported encoding: gb2312 错误原因
java Struts2 在拦截器里的跳转问题
jsp 对request.getSession(false)的理解(附程序员常疏忽的一个漏洞)
Java 项目生成静态页面的代码
jdk与jre的区别 很形象,很清晰,通俗易懂

JSP 中的 Eclipse开发Hibernate应用程序


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 87 ::
收藏到网摘: n/a


  Hibernate是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction处理功能的,Hibernate的Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装,下面我们详细的分析:
  Hibernate可以配置为JDBCTransaction或者是JTATransaction,这取决于你在hibernate.properties中的配置:
  #hibernate.transaction.factory_class
  net.sf.hibernate.transaction.JTATransactionFactory
  #hibernate.transaction.factory_class
  net.sf.hibernate.transaction.JDBCTransactionFactory
  如果你什么都不配置,默认情况下使用JDBCTransaction,如果你配置为:
  hibernate.transaction.factory_class
  net.sf.hibernate.transaction.JTATransactionFactory
  将使用JTATransaction,不管你准备让Hibernate使用JDBCTransaction,还是JTATransaction,我的忠告就是什么都不配,将让它保持默认状态,如下:
  #hibernate.transaction.factory_class
  net.sf.hibernate.transaction.JTATransactionFactory
  #hibernate.transaction.factory_class
  net.sf.hibernate.transaction.JDBCTransactionFactory
  在下面的分析中我会给出原因。
  一、JDBC Transaction

  看看使用JDBC Transaction的时候我们的代码例子:
  Session session = sf.openSession();
  Transaction tx = session.beginTransactioin();
  ...
  session.flush();
  tx.commit();
  session.close();
  这是默认的情况,当你在代码中使用Hibernate的Transaction的时候实际上就是JDBCTransaction。那么JDBCTransaction究竟是什么东西呢?来看看源代码就清楚了:
  Hibernate2.0.3源代码中的类
  net.sf.hibernate.transaction.JDBCTransaction:
  public void begin() throws HibernateException {
  ...
  if (toggleAutoCommit) session.connection().setAutoCommit(false);
  ...
  }
  这是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗?是不是很熟悉?
  再来看
  public void commit() throws HibernateException {
  ...
  try {
  if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
  try {
  session.connection().commit();
  committed = true;
  }
  ...
  toggleAutoCommit();
  }
  这是提交方法,看到connection().commit() 了吗?下面就不用我多说了,这个类代码非常简单易懂,通过阅读使我们明白Hibernate的Transaction都在干了些什么?我现在把用Hibernate写的例子翻译成JDBC,大家就一目了然了:
  Connection conn = ...; <--- session = sf.openSession();
  conn.setAutoCommit(false); <--- tx = session.beginTransactioin();
  ... <--- ...
  conn.commit(); <--- tx.commit(); (对应左边的两句)
  conn.setAutoCommit(true);
  conn.close(); <--- session.close();
  看明白了吧,Hibernate的JDBCTransaction根本就是conn.commit而已,根本毫无神秘可言,只不过在Hibernate中,Session打开的时候,就会自动conn.setAutoCommit(false),不像一般的JDBC,默认都是true,所以你最后不写commit也没有关系,由于Hibernate已经把AutoCommit给关掉了,所以用Hibernate的时候,你在程序中不写Transaction的话,数据库根本就没有反应。
  二、JTATransaction

  如果你在EJB中使用Hibernate,或者准备用JTA来管理跨Session的长事务,那么就需要使用JTATransaction,先看一个例子:
  javax.transaction.UserTransaction tx = new
  InitialContext().lookup("javax.transaction.UserTransaction");
  Session s1 = sf.openSession();
  ...
  s1.flush();
  s1.close();
  ...
  Session s2 = sf.openSession();
  ...
  s2.flush();
  s2.close();
  tx.commit();
  这是标准的使用JTA的代码片断,Transaction是跨Session的,它的生命周期比Session要长。如果你在EJB中使用Hibernate,那么是最简单不过的了,你什么Transaction代码统统都不要写了,直接在EJB的部署描述符上配置某某方法是否使用事务就可以了。
  现在我们来分析一下JTATransaction的源代码, net.sf.hibernate.transaction.JTATransaction:
  public void begin(InitialContext context, ...
  ...
  ut = (UserTransaction) context.lookup(utName);
  ...
  看清楚了吗? 和我上面写的代码 tx = new Initial Context?().lookup("javax.transaction.UserTransaction"); 是不是完全一样?
  public void commit() ...
  ...
  if (newTransaction) ut.commit();
  ...
  JTATransaction的控制稍微复杂,不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的。
  但是你现在是否看到了什么问题? 仔细想一下,Hibernate Transaction是从Session中获得的,tx = session.beginTransaction(),最后要先提交tx,然后再session.close,这完全符合JDBC的Transaction的操作顺序,但是这个顺序是和JTA的Transactioin操作顺序彻底矛盾的!!! JTA是先启动Transaction,然后启动Session,关闭Session,最后提交Transaction,因此当你使用JTA的Transaction的时候,那么就千万不要使用Hibernate的Transaction,而是应该像我上面的JTA的代码片断那样使用才行。
  总结:
  1、在JDBC上使用Hibernate 必须写上Hibernate Transaction代码,否则数据库没有反应。此时Hibernate的Transaction就是Connection.commit而已
  2、在JTA上使用Hibernate 写JTA的Transaction代码,不要写Hibernate的Transaction代码,否则程序会报错
  3、在EJB上使用Hibernate 什么Transactioin代码都不要写,在EJB的部署描述符里面配置
  |---CMT(Container Managed Transaction)
  |
  |---BMT(Bean Managed Transaction)
  |
  |----JDBC Transaction
  |
  |----JTA Transaction