Java 事务讨论

欢迎参与Java 事务讨论
bruce http://www.jdon.com Jul 14, 2003 6:13 AM  回复

*****************************
**JTA与JDBC中事务处理的区别**
*****************************
JTA(Java Transaction API) , 如begin(), commit()
JDBC中也有事务处理的API, 如begin(), commit()

两者都是控制事务的API, 不知它们有什么区别? 是不是底层实现相同?

****************************************
**另外,也谈谈我对CMP与Hibernate的理解**
****************************************
显然,CMP在处理复杂的查询时弱于Hibernate. CMP也没有动态查询。
但是,CMP在事务处理方面强于Hibernate, 原因是CMP与EJB容器结合,其CMT直接在Declarative transaction申明事务的类型,其它的事情交给EJB容器,代码量少,也容易维护。

*********************************************************
**在EJB中用hibernate代替CMP的可行性到底有多少?(好与坏)**
*********************************************************

 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 14, 2003 9:00 PM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
顶一顶. 不相信大家对此不感兴趣。
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 14, 2003 9:54 PM   回复 
 
发表人: blues    发表文章: 67 / 注册时间: 2002-09 
先说一说hibernate:
在此之前大家对hibernate进行了很多讨论。由于我没有真正在项目中使用过hibernate,所以不敢乱说。但看了一些资料和使用hibernate的Sample后,我感觉使用hibernate并非会有根本性的好处(当然cmp也不是必须使用的)。
先列出2种后台层次结构:
1.一个使用hibernate的sample
sessionBean --> (domain object) -->DAO -->hibernate
2.我在上一个项目中使用的结构
sessionBean --> (domain object) -->DAO
比较上面2种结构,区别在于:
方式1在DAO中使用了hibernate进行persistence工作,实现对关系型数据库的操作;而我方式2中,是在DAO中使用jdbc直接操作关系数据库。

我的结论是:
1.方式1能做的事情,在方式2中都能做;而方式2能做的事情方式1不一定能胜任。例如在DAO优化方面,方式2要比方式1更灵活;

2.方式1在代码量方面不比方式2少。--实际上方式1需要维护的是o/r mapping 文件,而方式2可以通过代码生成工具方便地生成绝大部分代码

3.o/r mapping的概念,更应该是一个面向对象设计的原则。在实现的时候,直接在DAO使用JDBC操作数据库也是一种o/r 转换的做法。因此还是没有理由一定要使用hibernate。

说的片面之处,请各位指正.
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 3:05 AM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
Hibernate好处很多,这也是为什么大家对此如此关注的原因。

sessionBean --> DAO(JDBC+SQL) 业务逻辑与数据库偶合太密。不利于扩展及维护。这个我以前做项目深有体会,特别是SQL量大的时候。并且ORM在数据库端是透明的,以前做项目用一种数据库SQL Server,后来又让支持另一种数据库Oracle,光写传参数和写if 语名判断不说,连有些SQL语句也要变,现在想起来还记忆有新。

所以我们才会用ORM这种映射。


“1.方式1能做的事情,在方式2中都能做;而方式2能做的事情方式1不一定能胜任。例如在DAO优化方面,方式2要比方式1更灵活;

Hibernate在SQL优化方面已经帮我们做了很多,自已优化需要对JDBC了解较深入,学习周期长。

“方式1在代码量方面不比方式2少。--实际上方式1需要维护的是o/r mapping 文件,而方式2可以通过代码生成工具方便地生成绝大部分代码

ORM 文件可以通过XDoclet去做,很方便,即使是Ojbect的属性有变化,只需用Xdoclet重新生成一次就行。但我现在还不知道如果数据库端若有变化,如何将变化自动或半自动的反映到Object这边,我对Hibernate还在了解中。

 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 12:46 PM   回复 
 
发表人: guty    发表文章: 55 / 注册时间: 2003-06 
> sessionBean --> (domain object) -->DAO -->hibernate

为什么要这么麻烦,

hibernate API
直接 service ---------------> POJO
不就可以了?


 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 12:51 PM   回复 
 
发表人: guty    发表文章: 55 / 注册时间: 2003-06 
用了O-R Mapping工具,DAO是不需要存在的
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 10:21 PM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
JDBC是一种DAO,ORM也是一种DAO。关键看DAO怎么定义了。
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 10:30 PM   回复 
 
发表人: blues    发表文章: 67 / 注册时间: 2002-09 
to guty:
我理解hibernate与jdbc是同一层次的东西。

"使用hibernate后就不需要DAO"
I don't think so.用不用hibernate与用不用DAO没有必然联系。这其实涉及到对DAO的作用的理解。DAO的一个重要目的是为了将"操作"/"属性"分开。
回头再看你所提出的结构:session bean ->POJO
在这个结构中,POJO的功能是"操作"+"属性";
如果我们愿意让"操作"+"属性"不分开,自然也可以不用DAO,如下:
session bean ->java object
其中java object是(数据库操作+value object)。

但我们都不愿意这么做,而是将java object分割为DAO+value object

--请指教

to robbin:
>澄清一个事实:Hibernate本身没有事务处理功能!

I think so.使用container的transaction,在transaction context中调用hibernate就OK。当然hibernate中所使用的connection从txDatasource中获取
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 14, 2003 11:45 PM   回复 
 
发表人: robbin    发表文章: 591 / 注册时间: 2003-06 
>>**JTA与JDBC中事务处理的区别**

去找本教科书看

>>CMP在事务处理方面强于Hibernate, 原因是CMP与EJB容器结合,其CMT直接在Declarative transaction申明事务的类型,其它的事情交给EJB容器,代码量少,也容易维护

澄清一个事实:Hibernate本身没有事务处理功能!

如果在Session Bean里面调用Hibernate,一样可以使用CMT。

CMP的代码量比Hibernate只多不少,可维护性更加是一场恶梦!不要凭空去想,实际做做项目你就知道了。

>>**在EJB中用hibernate代替CMP的可行性到底有多少?(好与坏)**

如果你觉得你可以用Session Bean + DAO + JDBC可以取代Session Bean + CMP,那么你就可以一样用Session Bean + DAO + Hibernate取代 Session Bean + CMP。

Hibernate只不过是JDBC的一个非常好用,非常简单的lightweight的对象封装框架而已,没有必要老是拿来和CMP做对比。凡是用JDBC的地方,你都可以用Hibernate,仅此而已。


 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 4:27 AM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
hi, robbin,以下我的总结不知是否正确,还望指点。

JDBC和JTA是BMT中的两种事务类型。
JDBC 事务受数据库的事务管理器控制。JTA 允许事务在不受数据库的事务管理器控制的情况下划分事务, EJB中利用JTS实施事务管理器,在代码中调用JTA方法,由JTA调用JTS提供的服务。所以JTA受JTS控制,JTS支持JTA. 如果事务要跨不同的数据库,就需要一个JTA事务。在BMT的SessionBean 中,也可以将 JDBC 和 JTA 事务混合在一起。但是这样做容易引起混乱,不利于维护代码。

我对hibernate还在了解中,可能看问题太片面。我想说的是,CMT比BMT代码量少。如果hibernate也可以用在CMT中,那SessionBean+hibernate确实是一个不错的组合。
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 1:04 AM   回复 
 
发表人: robbin    发表文章: 591 / 注册时间: 2003-06 
>>**在EJB中用hibernate代替CMP的可行性到底有多少?(好与坏)**


Hibernate的优点有很多,我相信前面的帖子已经讨论的够充分了。简单,易用,强大,灵活而且速度够快。

Hibernate的缺点从功能上来说,不适合处理批量update和delete(这也是ORM共同的缺点)。HQL只有select,没有update和delete。本来在HQL里面增加update和delete只不过是举手之劳而已。但是一旦在HQL里面增加update和delete,必须同步更新在JVM里面的persistent object,否则会造成persisent object的状态不一致的问题。这边厢数据库里面的记录已经被删除了,那边厢persistent object还在JVM里面好好的运行呢!

所以Gavin King建议批量update和delete使用JDBC,这也符合他的软件哲学,把95%的事情做到最好,剩下5%的瓶颈交给JDBC,“非不能也,是不为也”。

不过,实际上在一个面向用户交互的软件中,极少会遇到批量更新和批量删除的情况,即便遇到,批量处理的记录数也不会很多,一般用Hibernate处理也足够了。只有一些数据库后台维护程序会比较频繁的使用批量更新和批量删除,但对于这样的情况,直接使用数据库的C API更加符合要求。

另一个我曾经认为是Hibernate的缺点是不支持动态映射数据库表,不支持映射非表的其他数据库对象,当然这也是JDO,CMP同样的面临的问题。但我最近几天发现Hibernate完全可以做到。

在Hibernate中,persistent object通过XML Mapping文件映射到数据库表上,这样就不能动态映射不同的表,比如有时候会遇到根据不同的情况选择是从当前表还是从历史表中进行查询。不过persistent object通过XML Mapping文件也可以选择不映射数据库表,而是映射到一个Java class上,这样就可以自己编写一个ClassPersister,处理如何把persistent object和数据库进行数据映射。更进一步,通过该方法,也可以解决在Hibernate中调用Store procedure的问题。

说实话,从功能上就ORM这一点来说,我还没有发现Hibernate的缺点,大概是因为我对Hibernate研究还不够深入吧。
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 4:44 AM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
"但是一旦在HQL里面增加update和delete,必须同步更新在JVM里面的persistent object,否则会造成persisent object的状态不一致的问题。这边厢数据库里面的记录已经被删除了,那边厢persistent object还在JVM里面好好的运行呢!"

的确,如果在同步的话,性能必定要打折扣。看样Gavin King也很圆滑呀。


"在Hibernate中,persistent object通过XML Mapping文件映射到数据库表上,这样就不能动态映射不同的表,比如有时候会遇到根据不同的情况选择是从当前表还是从历史表中进行查询。不过persistent object通过XML Mapping文件也可以选择不映射数据库表,而是映射到一个Java class上,这样就可以自己编写一个ClassPersister,处理如何把persistent object和数据库进行数据映射。更进一步,通过该方法,也可以解决在Hibernate中调用Store procedure的问题。"

你的意思是不是这个被映射的Java class,做为一个control的功能,然后由它来指向不同的数据库表。
如果是的话,那Hibernate功能实在强大。有没有相关的URL? 我也想研究一下。

 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 9:11 AM   回复 
 
发表人: robbin    发表文章: 591 / 注册时间: 2003-06 
>>sessionBean --> DAO(JDBC+SQL) 业务逻辑与数据库偶合太密。不利于扩展及维护。

用ORM的原因主要不是因为降低耦合。使用JDBC并不会造成和数据库过分的耦合,除非你总是用数据库扩展的SQL,而不是ANSI SQL92。当然ORM和数据库的耦合度更低。

自己使用JDBC来实现ORM绝不是blues说的那么容易的,要处理大量很棘手的问题,否则ORM就没有存在的必要了。简单的来说,一个复合持久对象你用JDBC实现ORM就非常麻烦,主要的困难不在于多表查询,在于你怎么实现动态的lazy loading?我相信blues没有用JDBC做过复杂的ORM工作,否则就不会这样想当然了。我在没有听说过ORM之前就是自己手工写JDBC代码来实现ORM的,一旦持久对象之间存在复杂的组合和聚合关系,很难按照OO设计做下去了。我曾经为此头疼过很久,一直没有好的解决办法,直到接触JDO和Hibernate,才算找到答案。


>>但我现在还不知道如果数据库端若有变化,如何将变化自动或半自动的反映到Object这边

http://hibernate.bluemars.net/52.html

ReverseEngTool可以这样做,但还不够好。可以手工修改XML Mapping File,然后用CodeGenerator自动生成代码。


>>在BMT的SessionBean 中,也可以将 JDBC 和 JTA 事务混合在一起。但是这样做容易引起混乱,不利于维护代码

不能混合使用,事务不能嵌套,会报错的。本质上来说,JDBC事务是由数据库管理的,JTA事务是由App Server容器的事务管理器来管理的。JTA可以实现跨数据库连接,跨域的事务控制。

在多个数据库参与事务的情况下,JTA管理方式颇有不同,需要启动2PC。第一阶段通知参与事务的各资源准备提交,如果有资源没有准备好,全体放弃;第二阶段真正提交,并且记录日志。另外JTA除了可以管理数据库资源外,也可以管理其他资源,比如JMS。


>>你的意思是不是这个被映射的Java class,做为一个control的功能,然后由它来指向不同的数据库表。

对。Hibernate里面提供了一个接口ClassPersister,其抽象了persistent class和数据库对象的映射操作。同时Hibernate也提供了两个
ClassPersister接口的具体实现类:

EntityPersister:根据Mapping 文件中定义的对象属性和表字段映射关系,处理"table-per-class-hierarchy" mapping
NormalizedEntityPersister:根据Mapping 文件中定义的对象属性和表字段映射关系,处理"table-per-subclass" mapping

默认情况下,Hibernate就是调用EntityPersister和NormalizedEntityPersister 来处理对象和表映射的。但如果EntityPersister和NormalizedEntityPersister都不能满足你的要求的话,就可以自己写一个ClassPersister的实现类,处理更复杂多变的动态映射关系。

最后在XML Mapping文件里面指定使用你自己写的ClassPersister实现类,而不使用默认的EntityPersister。由此也可以看出Hibernate本身具有很强的可扩展性,如果Hibernate功能不能满足你的需要,还可以自己扩充Hibernate的功能。相关介绍和例子见Hibernate文档第4.1.3节:

http://hibernate.bluemars.net/hib_docs/reference/html/or-mapping.html#or-mapping-s1-3


 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 10:56 AM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
多谢robbin的 Reference URL,我会仔细看看的。

ORM的优势我总结为:
将对象映像到关系数据库,多分出一个持久层,减少耦合.对关系数据库结构的简单改动并不影响你的面向对象代码的。而且应用程序开发者不需要了解关系数据库结构,事实上,他们甚至不需要知道对象是保存在关系数据库中。

"我在没有听说过ORM之前就是自己手工写JDBC代码来实现ORM的,一旦持久对象之间存在复杂的组合和聚合关系,很难按照OO设计做下去了"
厉害,凡是自已写ORM的人都不简单。佩服!
的确,对象之间的关系太难处理。一对一,一对多,多对多还可以通过外键和association 表解决,但对于组合和聚合这种M-M,O-M 关系来说,考虑增删改就太复杂了。这也就是老外说的 impedance mismatch. 关系数据库是基于关系数学,无法充分体现OO的关系。


"不能混合使用,事务不能嵌套,会报错的"
我可没说这两个要嵌套使用,难道JDBC和JTA不能是并行的关系,各管各的?

"在多个数据库参与事务的情况下,JTA管理方式颇有不同,需要启动2PC。第一阶段通知参与事务的各资源准备提交,如果有资源没有准备好,全体放弃;第二阶段真正提交,并且记录日志"

在第一阶段还有一个叫交易日志,不知与第二阶级参与者和协调者提交或中止记录写入的日志有什么区别?感觉是一样的。

另外,感觉2PC容易形成瓶颈.


"除非你总是用数据库扩展的SQL,而不是ANSI SQL92"
时间长了,我也记不得了,只记得那时SQL Server 与Oracle的左联,右联SQL语句写法不同,那时改得真的都发毛了。
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 25, 2003 10:24 PM   回复 
 
发表人: newjoy    发表文章: 21 / 注册时间: 2003-06 
good
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 12:19 PM   回复 
 
发表人: zzeric    发表文章: 21 / 注册时间: 2002-10 
Robbin,如果使用JDBC来进行update/delete操作,会不会在Hibernate的cache里得到反映?如果可以,我很想知道Hibernate是怎么知道何时需要更新cache的
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 1:26 PM   回复 
 
发表人: robbin    发表文章: 591 / 注册时间: 2003-06 
> Robbin,如果使用JDBC来进行update/delete操作,会不会在H
> bernate的cache里得到反映?如果可以,我很想知道Hibernat
> 是怎么知道何时需要更新cache的

你的问题问得很好!答案是不可以。

上面我提到如果Hibernate可以在HQL里面批量update/delete,那么必须进行POJO的同步,这里面隐含一个前提,就是在同一个数据库连接里面处理。如果不是在同一个数据库连接里面处理的话,其实就不是Java程序能够控制的了,需要根据数据库设定的隔离级别来确定到底会产生什么样的结果。


 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 15, 2003 10:19 PM   回复 
 
发表人: bruce    发表文章: 191 / 注册时间: 2003-05 
"上面我提到如果Hibernate可以在HQL里面批量update/delete,那么必须进行POJO的同步,这里面隐含一个前提,就是在同一个数据库连接里面处理。如果不是在同一个数据库连接里面处理的话,其实就不是Java程序能够控制的了,需要根据数据库设定的隔离级别来确定到底会产生什么样的结果。"

不知我的理解是否正确。
你的意思是不是,如果在同一个数据库连接里面处理的话,通过设置JDBC transaction 隔离级别为Serializable mode?
如果是跨多个数据库的话,所有的数据库设置为最高隔离级别,这样才能保证批量update/delete完整性和一致性.


 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 16, 2003 12:18 AM   回复 
 
发表人: robbin    发表文章: 591 / 注册时间: 2003-06 

> 不知我的理解是否正确。
> 你的意思是不是,如果在同一个数据库连接里面处理的话,通
> 柚肑DBC transaction 隔离级别为Serializable mode?
> 如果是跨多个数据库的话,所有的数据库设置为最高隔离级别
> 庋拍鼙Vづ縰pdate/delete完整性和一致性.
>

你误解了。我的意思很简单,如果在一个数据库连接中,既用Hibernate修改数据库,又用JDBC直接修改数据库,当然要考虑POJO同步的问题。如果分别在不同的数据库连接中各自干各的,本来互不干扰,就根本没有必要去管数据同步问题。


 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Jul 21, 2003 10:31 AM   回复 
 
发表人: yyanghhong    发表文章: 63 / 注册时间: 2003-06 
Hibernate有一个很方便的功能, 它把持久层对象中的表数据定义从代码中分离出来, 防在配置文件中, 这比传统ORM使用code generator的方法要自动高效. 在struts中action mapping也采用了类似的方法, 这些简洁实用的设计在好的架构中应用的很普遍.
 
 

 Re: 欢迎参与Java 事务讨论  发表时间: Dec 23, 2004 1:50 PM   回复 
 
发表人: tonykee    发表文章: 6 / 注册时间: 2004-10 
我认为DAO的真正意义在于隔离会话,隔离事务,把这些封装到DAO里面才是真正的数据访问对象,
不论是DAO+Jdbc或 者是DAO+Hibernate其实思想都一样,但是事务这一块需要“横切”出来在BO里面
不直接调用连接jdbc connection 或hibernate session 通过事务封装类来间接调用地层所有dao

合理组合搭配到事务中去,DAO+ hibernate 我还有个很深刻的感受,很多人对PO和VO做了太多的争论
认为PO不能做VO, VO也不能做PO,诚然这点没有什么错误,有的人甚至想出了很极端的方法
利用BeanUitl.copyproperties(destVO, srcPO)的方法来转换,我认为效率太低。

DAO在这其中又是一个非常重要的角色了,DAO分离了连接会话,它也分离了PO和VO非常的微妙。

DAO传入的参数可以是VO得到的结果也是VO,DAO外界不跟任何PO打交道,只有DAO内布才存在PO
这样开发起来是很轻松的,不过这样会出先session的频繁打开和关闭,幸好hibernate 在这方面做了
大量的工作用线程池来负责维护会话,我想我们不必过多担心这个问题,我现在做了大量的封装

DAO隔离会话,隔离PO VO 同时配合抽象通用事务类完成复杂的事务控制。我感觉这样的DAO才是真正意义
上的DAO,这些全部继承我过去对DAO + jdbc orm的封装思想,采用抽象工厂和接口多态继承和实现
xxxDAOImplOracle xxxDAOImpleSqlsrv ...的机制可以跨任何的数据库
现在DAO + hibernate 也完好继承了过去的思想,而且用起来更强大,更方便。
 

你可能感兴趣的:(java,DAO,数据库,Hibernate,object,jdbc)