??xml version="1.0" encoding="utf-8" standalone="yes"?>日本三级在线观看网站,精品国产乱码久久久久软件,国新精品乱码一区二区三区18 http://www.aygfsteel.com/wanghao/category/34267.html向前q?/description>zh-cnMon, 01 Sep 2008 19:06:28 GMTMon, 01 Sep 2008 19:06:28 GMT60hibernate入门 - Transaction http://www.aygfsteel.com/wanghao/articles/226176.html中间开?/dc:creator>中间开?/author>Mon, 01 Sep 2008 12:04:00 GMThttp://www.aygfsteel.com/wanghao/articles/226176.htmlhttp://www.aygfsteel.com/wanghao/comments/226176.htmlhttp://www.aygfsteel.com/wanghao/articles/226176.html#Feedback0http://www.aygfsteel.com/wanghao/comments/commentRss/226176.htmlhttp://www.aygfsteel.com/wanghao/services/trackbacks/226176.html
Hibernate可以配置为JDBCTransaction或者是JTATransactionQ这取决于你在hibernate.properties中的配置:

引用
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory


如果你什么都不配|,默认情况下用JDBCTransactionQ如果你配置为:

引用
hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory


用JTATransaction

不管你准备让Hibernate使用JDBCTransactionQ还是JTATransactionQ我的忠告就是什么都不配Q将让它保持默认状态,如下Q?

引用
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory


在下面的分析中我会给出原因?

一、JDBC Transaction

看看使用JDBC Transaction的时候我们的代码例子Q?

[code:1]Session session = sf.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();[/code:1]

q是默认的情况,当你在代码中使用Hibernate的Transaction的时候实际上是JDBCTransaction。那么JDBCTransactionI竟是什么东西呢Q来看看源代码就清楚了:

Hibernate2.0.3源代码中的类[code:1]net.sf.hibernate.transaction.JDBCTransaction:

public void begin() throws HibernateException {

log.debug("begin");
try {
toggleAutoCommit = session.connection().getAutoCommit();
if (toggleAutoCommit) session.connection().setAutoCommit(false);
}
catch (SQLException e) {
log.error("Begin failed", e);
throw new TransactionException("Begin failed with SQL exception: ", e);
}
begun = true;
}[/code:1]
q是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗Q是不是很熟悉?

再来?

[code:1]public void commit() throws HibernateException {
if (!begun) throw new TransactionException("Transaction not successfully started");
log.debug("commit");
try {
if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
try {
session.connection().commit();
committed = true;
}
catch (SQLException e) {
log.error("Commit failed", e);
throw new TransactionException("Commit failed with SQL exception: ", e);
}
}
finally {
session.afterTransactionCompletion();
}
toggleAutoCommit();
}[/code:1]
q是提交ҎQ看到connection().commit() 了吗Q下面就不用我多说了Q这个类代码非常单易懂,通过阅读使我们明白Hibernate的Transaction都在q了些什么?我现在把? Hibernate写的例子译成JDBCQ大家就一目了然了Q?

[code:1]Connection conn = ...; <--- session = sf.openSession();

conn.setAutoCommit(false); <--- tx = session.beginTransactioin();

... <--- ...

conn.commit(); <--- tx.commit(); (对应左边的两?
conn.setAutoCommit(true);

conn.close(); <--- session.close();[/code:1]
看明白了吧,Hibernate的JDBCTransactionҎ是conn.commit而已Q根本毫无神U可aQ只不过? Hibernate中,Session打开的时候,׃自动conn.setAutoCommit(false)Q不像一般的JDBCQ默认都? trueQ所以你最后不写commit也没有关p,׃Hibernate已经把AutoCommitl关掉了Q所以用Hibernate的时候,你在E? 序中不写Transaction的话Q数据库Ҏ没有反应?


二、JTATransaction

如果你在EJB中用HibernateQ或者准备用JTA来管理跨Session的长事务Q那么就需要用JTATransactionQ先看一个例子:

[code:1]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();[/code:1]
q是标准的用JTA的代码片断,Transaction是跨Session的,它的生命周期比Session要长。如果你在EJB中? HibernateQ那么是最单不q的了,你什么Transaction代码l统都不要写了,直接在EJB的部|描q符上配|某某方法是否用事务就? 以了?

现在我们来分析一下JTATransaction的源代码Q?net.sf.hibernate.transaction.JTATransaction:

[code:1]public void begin(InitialContext context, ...
...
ut = (UserTransaction) context.lookup(utName);
...[/code:1]
看清楚了吗? 和我上面写的代码 tx = new InitialContext().lookup("javax.transaction.UserTransaction"); 是不是完全一P

[code:1]public void commit() ...
...
if (newTransaction) ut.commit();
...[/code:1]
JTATransaction的控制稍微复杂,不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的?

但是你现在是否看C什么问题? 仔细想一下,Hibernate Transaction是从Session中获得的Qtx = session.beginTransaction()Q最后要先提交txQ然后再session.closeQ这完全W合JDBC? Transaction的操作顺序,但是q个序是和JTA的Transactioin操作序d矛盾的!Q! JTA是先启动TransactionQ然后启动SessionQ关闭SessionQ最后提交TransactionQ因此当你用JTA? Transaction的时候,那么千万不要用Hibernate的TransactionQ而是应该像我上面的JTA的代码片断那样用才行?

ȝQ?

1、在JDBC上用Hibernate

必须写上Hibernate Transaction代码Q否则数据库没有反应。此时Hibernate的Transaction是Connection.commit而已

2、在JTA上用Hibernate

写JTA的Transaction代码Q不要写Hibernate的Transaction代码Q否则程序会报错

3、在EJB上用Hibernate

什么Transactioin代码都不要写Q在EJB的部|描q符里面配置


[code:1]
|---CMT(Container Managed Transaction)
|
|---BMT(Bean Managed Transaction)
|
|----JDBC Transaction
|
|----JTA Transaction
[/code:1]


robbin:
你说“Hibernate的JDBCTransactionҎ是conn.commit而已Q根本毫无神U可aQ只不过在Hibernate 中,Session打开的时候,׃自动conn.setAutoCommit(false)Q不像一般的JDBCQ默认都是trueQ所以你最后不? commit也没有关p,׃Hibernate已经把AutoCommitl关掉了Q所以用Hibernate的时候,你在E序中不? Transaction的话Q数据库Ҏ没有反?#8221;
但sf.opengSession()Ӟq没有setAutoCommit(false)Q我想问的是Q如果不~写M事务代码Q如Q?
[code:1]Session s = sf.openSession();
......
s.close();[/code:1]数据库会不会有反应(此时应该是默认AutoCommit为trueQ?

另外Q我想问一下:
1. s.flush()是不是必ȝ
2. s.close()是不是一定要关闭
比如你上面提到的Q?
[code:1]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();[/code:1]

s1不关闭,使用s2q行操作的代码中使用s1可不可以Q我觉得q样更加节约资源Q不需要反复的q接、关闭)



引用
但sf.opengSession()Ӟq没有setAutoCommit(false)Q我想问的是Q如果不~写M事务代码Q如Q?
Session s = sf.openSession();
......
s.close();
数据库会不会有反应(此时应该是默认AutoCommit为trueQ?/div>

不会有反应。在sf.openSession() 创徏Session实例的时候,已l调用了conn.setAutoCommit(false)了?


引用
另外Q我想问一下:
1. s.flush()是不是必ȝ
2. s.close()是不是一定要关闭


s.flush不是必须的,s.close()会调用一ơs.flush()

s.close()正常情况下应该关闭,除非你是用ThreadLocal理Session?


引用
s1不关闭,使用s2q行操作的代码中使用s1可不可以Q我觉得q样更加节约资源Q不需要反复的q接、关闭)


在这个例子中看不出来JTA的作用?
假设
[code:1]Class A {
find() {
Session s1 = sf.openSession();
...
s1.flush();
s1.close();
}
}[/code:1]

[code:1]Class B {
find() {
Session s2 = sf.openSession();
...
s2.flush();
s2.close();
}
}[/code:1]

[code:1]Main {

tx = ...;
A.find();
B.find();
tx.commit();
}[/code:1]

看明白了吗?JTA的Transaction理是跨c调用的?

]]>update和saveOrUpdate详解http://www.aygfsteel.com/wanghao/articles/226167.html中间开?/dc:creator>中间开?/author>Mon, 01 Sep 2008 11:31:00 GMThttp://www.aygfsteel.com/wanghao/articles/226167.htmlhttp://www.aygfsteel.com/wanghao/comments/226167.htmlhttp://www.aygfsteel.com/wanghao/articles/226167.html#Feedback0http://www.aygfsteel.com/wanghao/comments/commentRss/226167.htmlhttp://www.aygfsteel.com/wanghao/services/trackbacks/226167.html
在Hibernate中,最核心的概念就是对PO的状态管理。一个PO有三U状态:

1、未被持久化的VO
此时是一个内存对象VOQ由JVM理生命周期

2、已被持久化的POQƈ且在Session生命周期?
此时映射数据库数据,由数据库理生命周期

3、曾被持久化q,但现在和Session已经detached了,以VO的n份在q行
q种和Session已经detached的POq能够进入另一个SessionQl进行PO状态管理,此时它就成ؓPO的第二种状态了?span style="color: red;">q种PO实际上是跨了Sessionq行了状态维护的?/span>

在传l的JDO1.x中,PO只有前面两种状态,一个PO一旦脱PMQ就丧失了状态了Q不再和数据库数据关联,成ؓ一个纯_的内存VOQ它即ɘq入一个新的PMQ也不能恢复它的状态了?

Hibernate强的地方在于,一个POqSession之后Q还能保持状态,再进入一个新的Session之后Q就恢复状态管理的能力Q? 但此时状态管理需要用session.update或者session.saveOrUpdateQ这是Hibernate Reference中提到的“requires a slightly different programming model ”

现在正式q入本话题:

单的来说Qupdate和saveOrUpdate是用来对跨Session的POq行状态管理的?/span>

假设你的PO不需要跨Session的话Q那么就不需要用刎ͼ例如你打开一个SessionQ对POq行操作Q然后关闭,之后q个PO你也不会再用CQ那么就不需要用update?

因此Q我们来看看Q?
[code:1]Foo foo=sess.load(Foo.class,id);
foo.setXXX(xxx);
sess.flush();
sess.commit(); [/code:1]

PO对象foo的操作都在一个Session生命周期内完成,因此不需要显式的q行sess.update(foo)q样的操作? Hibernate会自动监到foo对象已经被修改过Q因此就向数据库发送一个update的sql。当然如果你非要加上 sess.update(foo)也不会错Q只不过q样做没有Q何必要?

而跨Session的意思就是说q个PO对象在Session关闭之后Q你q把它当做一个VO来用Q后来你在Session外面又修改了它的属性,然后你又x开一个SessionQ把VO的属性修改保存到数据库里面,那么你就需要用update了?

[code:1]// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);

// in a higher tier of the application
cat.setMate(potentialMate);

// later, in a new session
secondSession.update(cat); // update cat
secondSession.update(mate); // update mate[/code:1]

cat和mate对象是在W一个session中取得的Q在W一个session关闭之后Q他们就成了PO的第三种状态,和Session已经 detached的POQ此时他们的状态信息仍然被保留下来了。当他们q入W二个session之后Q立d可以q行状态的更新。但是由于对cat的修? 操作Qcat.setMate(potentialMate); 是在Session外面q行的,Hibernate不可能知道cat对象已经被改q了Q第二个Sessionq不知道q种修改Q因此一定要昑ּ的调? secondSession.update(cat); 通知HibernateQcat对象已经修改了,你必d送update的sql了?

所以update的作用就在于此,它只会被用于当一个PO对象跨Sessionq行状态同步的时候才需要写。而一个PO对象当它不需要跨Sessionq行状态管理的时候,是不需要写update的?

再谈谈saveOrUpdate的用场:

saveOrUpdate和update的区别就在于在跨Session的PO状态管理中QHibernate对PO采取何种{略?

例如当你写一个DAOImpl的时候,让cat对象增加一个mateQ如下定义:
[code:1]public void addMate(Cat cat, Mate mate) {
Session session = ...;
Transacton tx = ...;
session.update(cat);
cat.addMate(mate);
tx.commit();
session.close();
};[/code:1]

昄你是需要把Hibernate的操作封装在DAO里面的,让业务层的程序员和Web层的E序员不需要了解HibernateQ直接对DAOq行调用?

此时问题来了:上面的代码运行正有一个必要的前提Q那是Ҏ调用参数cat对象必须是一个已l被持久化过的POQ也是来说Q它应该首先? 数据库查询出来,然后才能q样用。但是业务层的程序员昄不知道这U内部的玄妙Q如果他的业务是现在增加一个catQ然后再增加它的mateQ他昄会这 栯用,new一个cat对象出来Q然后就addMateQ?

[code:1]Cat cat = new Cat();
cat.setXXX();
daoimpl.addMate(cat,mate);[/code:1]

但是h意看Q这个cat对象只是一个VOQ它没有被持久化q,它还不是POQ它没有资格调用addMateҎQ因此调用addMateҎ? 会真正往数据库里面发送update的sqlQ这个cat对象必须先被save到数据库Q在真正成ؓ一个PO之后Q才具备addMate的资根{?

你必这h操作Q?

[code:1]Cat cat = new Cat();
cat.setXXX();
daoimpl.addCat(cat);
daoimpl.addMate(cat, mate);[/code:1]

先持久化catQ然后才能对catq行其他的持久化操作。因此要求业务层的程序员必须清楚cat对象处于何种状态,到底是第一U,q是W三U。如果是W一U,p先saveQ再addMateQ如果是W三U,q接addMate?

但是最致命的是Q如果整个Y件分层很多,业务层的E序员他拿到q个cat对象也可能是上层Web应用层传递过来的catQ他自己也不知道q个catI竟是VOQ没有被持久化过Q还是已l被持久化过Q那么他Ҏ没有办法写E序了?

所以这LDAOImpl昄是有问题的,它会对业务层的程序员造成很多~程上的陷阱Q业务层的程序员必须深刻的了解他调用的每个DAO对PO? 象进行了何种状态管理,必须深刻的了解他的PO对象在Q何时候处于什么确切的状态,才能保证~程的正性,昄q是做不到的Q但是有? saveOrUpdateQ这些问题就q刃而解了?

现在你需要修改addMateҎQ?

[code:1]public void addMate(Cat cat, Mate mate) {
Session session = ...;
Transacton tx = ...;
session.saveOrUpdate(cat);
cat.addMate(mate);
tx.commit();
session.close();
};[/code:1]

如上Q如果业务层的程序员传进来的是一个已l持久化q的PO对象Q那么Hibernate会更新cat对象(假设业务层的E序员在Session外面修改qcat的属?Q如果传q来的是一个新new出来的对象,那么向数据库saveq个PO对象?

BTW: Hibernate此时I竟采取更新cat对象Q还是save cat对象Q取决于unsave-value的设定?

q样Q业务层的程序员׃必再操心PO的状态问题了Q对于他们来_不管cat是new出来的对象,只是一个VO也好Q还是从数据库查询出来的的PO对象也好Q全部都是直接addMateOK了:

[code:1]daoimple.addMate(cat, mate);[/code:1]

q便是saveOrUpdate的作用?

]]>
վ֩ģ壺 ־| ߰| | | | | | | | | ̩| | | | ϲ| | | | ɽ| | | °Ͷ| | | | ½| | | ̶| Ȫ| ѧ| Ͷ| | Ϫ| ¡| ̶| ľ˹| | | | |