??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久久亚洲精品美女,77777亚洲午夜久久多喷,亚洲第一成年免费网站 http://m.tkk7.com/Ericzhang5231/category/29096.htmlzh-cn Sat, 05 Apr 2008 05:51:00 GMT Sat, 05 Apr 2008 05:51:00 GMT 60 Q{QSpring事务传播机制解惑 http://m.tkk7.com/Ericzhang5231/articles/190896.htmlEric5231 Eric5231 Sat, 05 Apr 2008 04:45:00 GMT http://m.tkk7.com/Ericzhang5231/articles/190896.html http://m.tkk7.com/Ericzhang5231/comments/190896.html http://m.tkk7.com/Ericzhang5231/articles/190896.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/190896.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/190896.html Spring事务传播机制解惑
概述
当我们调用一个基于Spring的Service接口Ҏ(gu)Q如UserService#addUser()Q时Q它?yu)运行于Spring理的事务环境中QService接口Ҏ(gu)可能?x)在内部调用其它的Service接口Ҏ(gu)以共同完成一个完整的业务操作Q因此就?x)生服务接口方法嵌套调用的情况QSpring通过事务传播行ؓ(f)控制当前的事务如何传播到被嵌套调用的目标服务接口Ҏ(gu)中?/p>
事务传播是Springq行事务理的重要概念,光要性怎么都不。但是事务传播行Z是被误解最多的地方Q在本文里,我们详l分析不同事务传播行为的表现形式Q掌握它们之间的区别?/p>
事务传播行ؓ(f)U类
Spring在TransactionDefinition接口中规定了7U类型的事务传播行ؓ(f)Q它们规定了事务Ҏ(gu)和事务方法发生嵌套调用时事务如何q行传播Q?/p>
?/a>1事务传播行ؓ(f)cd
事务传播行ؓ(f)cd
说明
PROPAGATION_REQUIRED
如果当前没有事务Q就新徏一个事务,如果已经存在一个事务中Q加入到q个事务中。这是最常见的选择?/p>
PROPAGATION_SUPPORTS
支持当前事务Q如果当前没有事务,׃非事务方式执行?/p>
PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务Q就抛出异常?/p>
PROPAGATION_REQUIRES_NEW
新徏事务Q如果当前存在事务,把当前事务挂赗?/p>
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?/p>
PROPAGATION_NEVER
以非事务方式执行Q如果当前存在事务,则抛出异常?/p>
PROPAGATION_NESTED
如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIREDcM的操作?/p>
当用PROPAGATION_NESTEDӞ底层的数据源必须ZJDBC 3.0Qƈ且实现者需要支持保存点事务机制?/p>
几种Ҏ(gu)引v误解的组合事务传播行?/strong>
当服务接口方法分别用表1中不同的事务传播行ؓ(f)Q且q些接口Ҏ(gu)又发生相互调用的情况下,大部分组合都是一目了?dng)?gu)理解的。但是,也存在一些容易引赯解的l合事务传播方式?/p>
下面Q我们通过两个具体的服务接口的l合调用行ؓ(f)来破解这一隄。这两个服务接口分别是UserService和ForumServiceQUserSerice有一个addCredits()Ҏ(gu)QForumSerivce#addTopic()Ҏ(gu)调用了UserSerice#addCredits()Ҏ(gu)Q发生关联性服务方法的调用Q?/p>
public class ForumService {
private UserService userService;
public void addTopic() {①调用其它服务接口的Ҏ(gu)
//add Topic…
userService.addCredits() ;②被兌调用的业务方?/strong>
}
}
嵌套调用的事务方?/p>
对Spring事务传播行ؓ(f)最常见的一个误解是Q当服务接口Ҏ(gu)发生嵌套调用Ӟ被调用的服务Ҏ(gu)只能声明为PROPAGATION_NESTED。这U观点犯了望文生义的错误Q误认ؓ(f)PROPAGATION_NESTED是专为方法嵌套准备的。这U误解遗害不,执有q种误解的开发者错误地认ؓ(f)Q应量不让Servicecȝ业务Ҏ(gu)发生怺的调用,Servicecd能调用DAO层的DAOc,以避免生嵌套事务?/p>
其实Q这U顾虑是完全没有必要的,PROPAGATION_REQUIRED已经清楚地告诉我们:(x)事务的方法会(x)_“聪明”地判断上下文是否已经存在一个事务中Q如果已l存在,加入到q个事务中,否则创徏一个新的事务?/p>
依照上面的例子,假设我们ForumService#addTopic()和UserSerice#addCredits()Ҏ(gu)的事务传播行为都讄为PROPAGATION_REQUIREDQ这两个Ҏ(gu)运行于同一个事务中?/p>
Z清楚地说明这点,可以Log4J的日志设|ؓ(f)DEBUGU别Q以观察Spring事务理器内部的q行情况。下面将两个业务Ҏ(gu)都设|ؓ(f)PROPAGATION_REQUIREDQSpring所输出的日志信息如下:(x)
Using transaction object
[org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@e3849c]
①ؓ(f) ForumService#addTopic() 新徏一个事?/strong>
Creating new transaction with name [com.baobaotao.service.ForumService.addTopic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5] for JDBC transaction
Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5] to manual commit
Bound value [org.springframework.jdbc.datasource.ConnectionHolder@ee1ede] for key [org.apache.commons.dbcp.BasicDataSource@4204] to thread [main]
Initializing transaction synchronization
Getting transaction for [com.baobaotao.service.ForumService.addTopic]
Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@ee1ede] for key [org.apache.commons.dbcp.BasicDataSource@4204] bound to thread [main]
Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@8b8a47]
?/strong>UserService#addCredits() 单地加入到已存在的事务中Q即①处创徏的事务)(j)
Participating in existing transaction
Getting transaction for [com.baobaotao.service.UserService.addCredits]
Completing transaction for [com.baobaotao.service.UserService.addCredits]
Completing transaction for [com.baobaotao.service.ForumService.addTopic]
Triggering beforeCommit synchronization
Triggering beforeCompletion synchronization
Initiating transaction commit
③调用底?/strong>Connection#commit() Ҏ(gu)提交事务
Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5]
Triggering afterCommit synchronization
Triggering afterCompletion synchronization
Clearing transaction synchronization
嵌套事务
ForumService#addTopic()讄为PROPAGATION_REQUIREDӞUserSerice#addCredits()讄为PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORYӞq行的效果都是一致的Q当?dng)如果单独调用addCredits()另当别ZQ?/p>
当addTopic()q行在一个事务下Q如讄为PROPAGATION_REQUIREDQ,而addCredits()讄为PROPAGATION_NESTEDӞ如果底层数据源支持保存点QSpringؓ(f)内部的addCredits()Ҏ(gu)产生的一个内嵌的事务。如果addCredits()对应的内嵌事务执行失败,事务回滚到addCredits()Ҏ(gu)执行前的点,q不?x)将整个事务回滚。内嵌事务是内层事务的一部分Q所以只有外层事务提交时Q嵌套事务才能一q提交?/p>
嵌套事务不能够提交,它必通过外层事务来完成提交的动作Q外层事务的回滚也会(x)造成内部事务的回滚?/p>
嵌套事务和新事务
PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED也是Ҏ(gu)h的两个传播行为。PROPAGATION_REQUIRES_NEW 启动一个新的、和外层事务无关?#8220;内部”事务。该事务拥有自己的独立隔ȝ别和锁,不依赖于外部事务Q独立地提交和回滚。当内部事务开始执行时Q外部事务将被挂P内务事务l束Ӟ外部事务才l执行?/p>
由此可见Q?PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED 的最大区别在于:(x)PROPAGATION_REQUIRES_NEW 创Z个全新的事务Q它和外层事务没有Q何关p,?PROPAGATION_NESTED 创Z个依赖于外层事务的子事务Q当外层事务提交或回滚时Q子事务也会(x)q带提交和回滚?/p>
其它需要注意问?/p>
以下几个问题值得注意Q?/p>
1) 当业务方法被讄为PROPAGATION_MANDATORYӞ它就不能被非事务的业务方法调用。如ForumService#addTopic()讄为PROPAGATION_MANDATORYQ如果展现层的Action直接调用addTopic()Ҏ(gu)Q将引发一个异常。正的情况是:(x)addTopic()Ҏ(gu)必须被另一个带事务的业务方法调用(如ForumService#otherMethod()Q。所以PROPAGATION_MANDATORY的方法一般都是被其它业务Ҏ(gu)间接调用的?/p>
2) 当业务方法被讄为PROPAGATION_NEVERӞ它将不能被拥有事务的其它业务Ҏ(gu)调用。假设UserService#addCredits()讄为PROPAGATION_NEVERQ当ForumService# addTopic()拥有一个事务时QaddCredits()Ҏ(gu)抛出异常。所以PROPAGATION_NEVERҎ(gu)一般是被直接调用的?/p>
3)当方法被讄为PROPAGATION_NOT_SUPPORTEDӞ外层业务Ҏ(gu)的事务会(x)被挂P当内部方法运行完成后Q外层方法的事务重新q行。如果外层方法没有事务,直接q行Q不需要做M其它的事?/p>
结
在Spring声明式事务管理的配置中,事务传播行ؓ(f)是最Ҏ(gu)被误解的配置,原因在于事务传播行ؓ(f)名称Q如PROPAGATION_NESTEDQ嵌套式事务Q和代码l构的类似性上Q业务类Ҏ(gu)嵌套调用另一个业务类Ҏ(gu)Q。这U误解在很多Spring开发者中q泛存在Q本文深入讲解了Spring事务传播行ؓ(f)对业务方法嵌套调用的真实影响Q希望能帮助读者化解对事务传播行ؓ(f)的困惑?/p>
]]>Q{QSpring事务传播机制解惑 http://m.tkk7.com/Ericzhang5231/articles/190895.htmlEric5231 Eric5231 Sat, 05 Apr 2008 04:43:00 GMT http://m.tkk7.com/Ericzhang5231/articles/190895.html http://m.tkk7.com/Ericzhang5231/comments/190895.html http://m.tkk7.com/Ericzhang5231/articles/190895.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/190895.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/190895.html Spring事务传播机制解惑
概述
当我们调用一个基于Spring的Service接口Ҏ(gu)Q如UserService#addUser()Q时Q它?yu)运行于Spring理的事务环境中QService接口Ҏ(gu)可能?x)在内部调用其它的Service接口Ҏ(gu)以共同完成一个完整的业务操作Q因此就?x)生服务接口方法嵌套调用的情况QSpring通过事务传播行ؓ(f)控制当前的事务如何传播到被嵌套调用的目标服务接口Ҏ(gu)中?/p>
事务传播是Springq行事务理的重要概念,光要性怎么都不。但是事务传播行Z是被误解最多的地方Q在本文里,我们详l分析不同事务传播行为的表现形式Q掌握它们之间的区别?/p>
事务传播行ؓ(f)U类
Spring在TransactionDefinition接口中规定了7U类型的事务传播行ؓ(f)Q它们规定了事务Ҏ(gu)和事务方法发生嵌套调用时事务如何q行传播Q?/p>
?/a>1事务传播行ؓ(f)cd
事务传播行ؓ(f)cd
说明
PROPAGATION_REQUIRED
如果当前没有事务Q就新徏一个事务,如果已经存在一个事务中Q加入到q个事务中。这是最常见的选择?/p>
PROPAGATION_SUPPORTS
支持当前事务Q如果当前没有事务,׃非事务方式执行?/p>
PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务Q就抛出异常?/p>
PROPAGATION_REQUIRES_NEW
新徏事务Q如果当前存在事务,把当前事务挂赗?/p>
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?/p>
PROPAGATION_NEVER
以非事务方式执行Q如果当前存在事务,则抛出异常?/p>
PROPAGATION_NESTED
如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIREDcM的操作?/p>
当用PROPAGATION_NESTEDӞ底层的数据源必须ZJDBC 3.0Qƈ且实现者需要支持保存点事务机制?/p>
几种Ҏ(gu)引v误解的组合事务传播行?/strong>
当服务接口方法分别用表1中不同的事务传播行ؓ(f)Q且q些接口Ҏ(gu)又发生相互调用的情况下,大部分组合都是一目了?dng)?gu)理解的。但是,也存在一些容易引赯解的l合事务传播方式?/p>
下面Q我们通过两个具体的服务接口的l合调用行ؓ(f)来破解这一隄。这两个服务接口分别是UserService和ForumServiceQUserSerice有一个addCredits()Ҏ(gu)QForumSerivce#addTopic()Ҏ(gu)调用了UserSerice#addCredits()Ҏ(gu)Q发生关联性服务方法的调用Q?/p>
public class ForumService {
private UserService userService;
public void addTopic() {①调用其它服务接口的Ҏ(gu)
//add Topic…
userService.addCredits() ;②被兌调用的业务方?/strong>
}
}
嵌套调用的事务方?/p>
对Spring事务传播行ؓ(f)最常见的一个误解是Q当服务接口Ҏ(gu)发生嵌套调用Ӟ被调用的服务Ҏ(gu)只能声明为PROPAGATION_NESTED。这U观点犯了望文生义的错误Q误认ؓ(f)PROPAGATION_NESTED是专为方法嵌套准备的。这U误解遗害不,执有q种误解的开发者错误地认ؓ(f)Q应量不让Servicecȝ业务Ҏ(gu)发生怺的调用,Servicecd能调用DAO层的DAOc,以避免生嵌套事务?/p>
其实Q这U顾虑是完全没有必要的,PROPAGATION_REQUIRED已经清楚地告诉我们:(x)事务的方法会(x)_“聪明”地判断上下文是否已经存在一个事务中Q如果已l存在,加入到q个事务中,否则创徏一个新的事务?/p>
依照上面的例子,假设我们ForumService#addTopic()和UserSerice#addCredits()Ҏ(gu)的事务传播行为都讄为PROPAGATION_REQUIREDQ这两个Ҏ(gu)运行于同一个事务中?/p>
Z清楚地说明这点,可以Log4J的日志设|ؓ(f)DEBUGU别Q以观察Spring事务理器内部的q行情况。下面将两个业务Ҏ(gu)都设|ؓ(f)PROPAGATION_REQUIREDQSpring所输出的日志信息如下:(x)
Using transaction object
[org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@e3849c]
①ؓ(f) ForumService#addTopic() 新徏一个事?/strong>
Creating new transaction with name [com.baobaotao.service.ForumService.addTopic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5] for JDBC transaction
Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5] to manual commit
Bound value [org.springframework.jdbc.datasource.ConnectionHolder@ee1ede] for key [org.apache.commons.dbcp.BasicDataSource@4204] to thread [main]
Initializing transaction synchronization
Getting transaction for [com.baobaotao.service.ForumService.addTopic]
Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@ee1ede] for key [org.apache.commons.dbcp.BasicDataSource@4204] bound to thread [main]
Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@8b8a47]
?/strong>UserService#addCredits() 单地加入到已存在的事务中Q即①处创徏的事务)(j)
Participating in existing transaction
Getting transaction for [com.baobaotao.service.UserService.addCredits]
Completing transaction for [com.baobaotao.service.UserService.addCredits]
Completing transaction for [com.baobaotao.service.ForumService.addTopic]
Triggering beforeCommit synchronization
Triggering beforeCompletion synchronization
Initiating transaction commit
③调用底?/strong>Connection#commit() Ҏ(gu)提交事务
Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5]
Triggering afterCommit synchronization
Triggering afterCompletion synchronization
Clearing transaction synchronization
嵌套事务
ForumService#addTopic()讄为PROPAGATION_REQUIREDӞUserSerice#addCredits()讄为PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORYӞq行的效果都是一致的Q当?dng)如果单独调用addCredits()另当别ZQ?/p>
当addTopic()q行在一个事务下Q如讄为PROPAGATION_REQUIREDQ,而addCredits()讄为PROPAGATION_NESTEDӞ如果底层数据源支持保存点QSpringؓ(f)内部的addCredits()Ҏ(gu)产生的一个内嵌的事务。如果addCredits()对应的内嵌事务执行失败,事务回滚到addCredits()Ҏ(gu)执行前的点,q不?x)将整个事务回滚。内嵌事务是内层事务的一部分Q所以只有外层事务提交时Q嵌套事务才能一q提交?/p>
嵌套事务不能够提交,它必通过外层事务来完成提交的动作Q外层事务的回滚也会(x)造成内部事务的回滚?/p>
嵌套事务和新事务
PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED也是Ҏ(gu)h的两个传播行为。PROPAGATION_REQUIRES_NEW 启动一个新的、和外层事务无关?#8220;内部”事务。该事务拥有自己的独立隔ȝ别和锁,不依赖于外部事务Q独立地提交和回滚。当内部事务开始执行时Q外部事务将被挂P内务事务l束Ӟ外部事务才l执行?/p>
由此可见Q?PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED 的最大区别在于:(x)PROPAGATION_REQUIRES_NEW 创Z个全新的事务Q它和外层事务没有Q何关p,?PROPAGATION_NESTED 创Z个依赖于外层事务的子事务Q当外层事务提交或回滚时Q子事务也会(x)q带提交和回滚?/p>
其它需要注意问?/p>
以下几个问题值得注意Q?/p>
1) 当业务方法被讄为PROPAGATION_MANDATORYӞ它就不能被非事务的业务方法调用。如ForumService#addTopic()讄为PROPAGATION_MANDATORYQ如果展现层的Action直接调用addTopic()Ҏ(gu)Q将引发一个异常。正的情况是:(x)addTopic()Ҏ(gu)必须被另一个带事务的业务方法调用(如ForumService#otherMethod()Q。所以PROPAGATION_MANDATORY的方法一般都是被其它业务Ҏ(gu)间接调用的?/p>
2) 当业务方法被讄为PROPAGATION_NEVERӞ它将不能被拥有事务的其它业务Ҏ(gu)调用。假设UserService#addCredits()讄为PROPAGATION_NEVERQ当ForumService# addTopic()拥有一个事务时QaddCredits()Ҏ(gu)抛出异常。所以PROPAGATION_NEVERҎ(gu)一般是被直接调用的?/p>
3)当方法被讄为PROPAGATION_NOT_SUPPORTEDӞ外层业务Ҏ(gu)的事务会(x)被挂P当内部方法运行完成后Q外层方法的事务重新q行。如果外层方法没有事务,直接q行Q不需要做M其它的事?/p>
结
在Spring声明式事务管理的配置中,事务传播行ؓ(f)是最Ҏ(gu)被误解的配置,原因在于事务传播行ؓ(f)名称Q如PROPAGATION_NESTEDQ嵌套式事务Q和代码l构的类似性上Q业务类Ҏ(gu)嵌套调用另一个业务类Ҏ(gu)Q。这U误解在很多Spring开发者中q泛存在Q本文深入讲解了Spring事务传播行ؓ(f)对业务方法嵌套调用的真实影响Q希望能帮助读者化解对事务传播行ؓ(f)的困惑?/p>
]]>Transaction always commits even if marked readOnly http://m.tkk7.com/Ericzhang5231/articles/Transaction.htmlEric5231 Eric5231 Sat, 05 Apr 2008 04:36:00 GMT http://m.tkk7.com/Ericzhang5231/articles/Transaction.html http://m.tkk7.com/Ericzhang5231/comments/190892.html http://m.tkk7.com/Ericzhang5231/articles/Transaction.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/190892.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/190892.html
So in your scenario, I would assume that you do the setRollbackOnly within an inner transaction scope. Since you're using <tx:advice>, this could mean that your pointcut is too broad and applies transaction demarcation at multiple levels: for example, at the Controller level as well as at the service level, with the setRollbackOnly call happening in a service - this would lead to an UnexpectedRollbackException at the Controller level.
That said, I would actually argue that you should virtually never be using a programmatic setRollbackOnly call in the first place, or more specifically, a rollback without exception thrown to the caller. This usually indicates inappropriate transaction scopes.
In particular, web data binding should *not* happen within a transaction. Rather, perform data binding without transaction first, then start transactions at the service level *once you decided to process the bound data*, with the bound data brought into the transaction through a merge operation. This way, validation errors don't require a transaction rollback in the first place...
Aside from avoiding programmatic setRollbackOnly calls in your application code, the above approach to validation and transactions also avoids excessive rollbacks in your transaction statistics. Such rollbacks for frequent and perfectly normal user interactions should in particular be avoided in administered environments like a J2EE server installation - with transaction monitoring and (potentially) escalation messages generated for rollbacks.
]]> 利用ThreadLocal理session http://m.tkk7.com/Ericzhang5231/articles/186097.htmlEric5231 Eric5231 Thu, 13 Mar 2008 09:04:00 GMT http://m.tkk7.com/Ericzhang5231/articles/186097.html http://m.tkk7.com/Ericzhang5231/comments/186097.html http://m.tkk7.com/Ericzhang5231/articles/186097.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/186097.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/186097.html
在利用Hibernate开发DAO模块Ӟ我们和Session打的交道最多,所以如何合理的理SessionQ避免Session的频J创?
和销毁,对于提高pȝ的性能来说是非帔R要的Q以往是通过eclipse的插件来自动完成q些代码的,当然效果是不错的Q但是L觉得不爽(没有L那些
冗长的代?Q所以现在打自己实现Session理的代码?
我们知道Session是由SessionFactory负责创徏的,而SessionFactory的实现是U程安全的,多个q发?
U程可以同时讉K一个SessionFactoryq从中获取Session实例Q那么Session是否是线E安全的呢?很遗憾,{案是否定的?
Session中包含了数据库操作相关的状态信息,那么说如果多个线E同时用一个Session实例q行CRUDQ就很有可能D数据存取的乱,你能
够想像那些你Ҏ(gu)不能预测执行序的线E对你的一条记录进行操作的情Ş吗?
在Session的众多管理方案中Q我们今天来认识一U名ThreadLocal模式的解x案?
早在Java1.2推出之时QJavaq_中就引入了一个新的支持:(x)java.lang.ThreadLocalQ给我们在编写多U程E序
时提供了一U新的选择。ThreadLocal是什么呢Q其实ThreadLocalq是一个线E的本地实现版本Q它q不是一个ThreadQ而是
thread local
variable(U程局部变?。也许把它命名ؓ(f)ThreadLocalVar更加合适。线E局部变?ThreadLocal)其实的功用非常简单,
是为每一个用某变量的线E都提供一个该变量值的副本Q是每一个线E都可以独立地改变自q副本Q而不?x)和其它U程的副本冲H。从U程的角度看Q就好像
每一个线E都完全拥有一个该变量?
ThreadLocal是如何做Cؓ(f)每一个线E维护变量的副本的呢Q其实实现的思\很简单,在ThreadLocalcM有一个MapQ用于存储每一个线E的变量的副本。比如下面的CZ实现(Z单,没有考虑集合的泛?Q?
public class ThreadLocal {
private Map values = Collections.synchronizedMap(new HashMap());
public Object get() {
Thread currentThread = Thread.currentThread();
Object result = values.get(currentThread);
if(result == null&&!values.containsKey(currentThread)) {
result = initialValue();
values.put(currentThread, result);
}
return result;
}
public void set(Object newValue) {
values.put(Thread.currentThread(), newValue);
}
public Object initialValue() {
return null;
}
}
那麽具体如何利用ThreadLocal来管理Session呢?Hibernate官方文档手册的示例之中,提供了一个通过ThreadLocall护Session的好榜样Q?
public class HibernateUtil {
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static final ThreadLocal<Session>session=new ThreadLocal<Session>();
public static Session currentSession() throws HibernateException {
Session s = session.get();
if(s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = session.get();
if(s != null) {
s.close();
}
session.set(null);
}
}
只要借助上面的工L(fng)获取Session实例Q我们就可以实现U程范围内的Session׃nQ从而避免了U程中频J的创徏和销毁Session?
例。当?dng)不要忘记在用完后关闭Session。写到这里,惛_多说一些,也许大多数时候我们的DAOq不?x)涉及(qing)到多线E的情ŞQ比如我们不?x)将DAO?
代码写在Servlet之中Q那样不是良好的设计Q我自己通常?x)在service层的代码里访问DAO的方法。但是我q是采用以上的工L(fng)来管?
SessionQ毕竟我们不能仅仅考虑今天己做什么,q应该考虑明天己做什么!
]]>Spring的Hibernate事务理 http://m.tkk7.com/Ericzhang5231/articles/184414.htmlEric5231 Eric5231 Fri, 07 Mar 2008 02:13:00 GMT http://m.tkk7.com/Ericzhang5231/articles/184414.html http://m.tkk7.com/Ericzhang5231/comments/184414.html http://m.tkk7.com/Ericzhang5231/articles/184414.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/184414.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/184414.html
我们在用Spring声明式事务时Q有一个非帔R要的概念是事务属性。事务属性通常׃务的传播行ؓ(f)Q事务的隔离U别Q事务的时值和事务只读标志l成。我们在q行事务划分Ӟ
需要进行事务定义,也就是配|事务的属性?
Spring ?gt;TransactionDefinition 接口中定义这些属?以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务理的核心接口?
代码
TransactionDefinition publicinterfaceTransactionDefinition {
intgetPropagationBehavior();
intgetIsolationLevel();
intgetTimeout();
booleanisReadOnly();
}
getTimeout()Ҏ(gu)Q它q回事务必须在多秒内完成?
isReadOnly(),事务是否只读Q事务管理器能够Ҏ(gu)q个q回D行优化,保事务是只ȝ?
getIsolationLevel()Ҏ(gu)q回事务的隔ȝ别,事务理器根据它来控制另外一个事务可以看到本事务内的哪些数据?
在TransactionDefinition接口中定义了五个不同的事务隔ȝ?
1) ISOLATION_DEFAULT q是一?PlatfromTransactionManager默认的隔ȝ别,使用数据库默认的事务隔离U别.另外四个与JDBC的隔ȝ别相对应 < br />
2) ISOLATION_READ_UNCOMMITTEDq是事务最低的隔离U别Q它充许别外一个事务可以看到这个事务未提交的数据。这U隔ȝ别会(x)产生脏读Q不可重复读和像读?br />
3) ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这U事务隔ȝ别可以避免脏d玎ͼ但是?
能会(x)出现不可重复dqd诅R?
4) ISOLATION_REPEATABLE_READ q种事务隔离U别可以防止脏读Q不可重复读。但是可能出现像读。它除了保证一个事务不能读取另一个事务未提交的数据外Q还保证了避免下?
的情况?不可重复?
在TransactionDefinition接口中定义了七个事务传播行ؓ(f):
1) < span style="color: #000000;"> PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事?
2) PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执?
3) PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务Q则抛出?
4)PROPAGATION_REQUIRES_NEW L开启一个新的事务。如果一个事务已l存在,则将q个存在的事务挂?
5) PROPAGATION_NOT_SUPPORTEDL非事务地执行Qƈ挂vM存在的事?
6) PROPAGATION_NEVERL非事务地执行Q如果存在一个活动事务,则抛出异?
7) PROPAGATION_NESTED如果一个活动的事务存在Q则q行在一个嵌套的事务? 如果没有zd事务, 则按
TransactionDefinition.PROPAGATION_REQUIRED 属性执?
]]> Hibernate的Load和getҎ(gu)区别 http://m.tkk7.com/Ericzhang5231/articles/184412.htmlEric5231 Eric5231 Fri, 07 Mar 2008 01:55:00 GMT http://m.tkk7.com/Ericzhang5231/articles/184412.html http://m.tkk7.com/Ericzhang5231/comments/184412.html http://m.tkk7.com/Ericzhang5231/articles/184412.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/184412.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/184412.html 1.d时机不同Q当lazy=true的时候)(j)
load是采用gq机?load语句不读库,{用非主键时才去读?/font>)Q而get不采用gq机?get语句旉上读?/font>)Q?br />
2.搜烦(ch)不到数据时的情况
当搜索的数据不存在的时候,load依然?x)返回一个对象,在你使用该对象的非主键数据时Q会(x)抛出异常Q?br />
当搜索的数据不存在的时候,get?x)返回一个nullQ?br />
备注Q?/strong> |上看来说load比get更节省资源;
我做q一个例子,即两个线E,1L(fng)E把数据d来,把sessionx。过几秒2L(fng)E也去读相同的记录,q时2L(fng)Eƈ没有搜烦(ch)?没有昄出HQL语句)Q不你用loadq是get
l论Q我觉得它们两个都有使用到缓存,至于更深入的我没有去研究?
]]> W十三章 理Hibernate的缓?/title> http://m.tkk7.com/Ericzhang5231/articles/180726.htmlEric5231 Eric5231 Tue, 19 Feb 2008 09:34:00 GMT http://m.tkk7.com/Ericzhang5231/articles/180726.html http://m.tkk7.com/Ericzhang5231/comments/180726.html http://m.tkk7.com/Ericzhang5231/articles/180726.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/180726.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/180726.html
~存的范围和~存的ƈ发访问策?br />
1.持久层的~存范围
事务范围: ~存只能被当前事务访?~存的生命周期依赖于事务的生命周?每个事务都有独自的缓?br />
q程范围: ~存被进E内的所有事务共?~存的生命周期依赖于q程的生命周? 因ؓ(f)q程的事务有可能q发讉K~存,所以必d~存采取必要的事务隔L?
集范围: 在群集环境中, ~存被同一个机器或多个机器上的多个q程׃n. ~存中的数据被复制到集群环境中的每个q程节点,q程之间通过q程通信来保证缓存中数据的一致?
~存中的数据通常采用对象的散装数据Ş?
2.~存q发讉K{略
׃可见, q程范围或群集范围缓?即第二~存,?x)出现ƈ发问?对第二~存可以讑֮以下四种cd的ƈ发访问策?每一个策略对应一U事务隔ȝ?
1) 事务? 仅仅在受理环境中适用,对于l常被读但是很少被修改的数据,可以防止脏读和不可重复读的ƈ发问?
2)d? 仅仅在非集的环境中适用,对于l常被读但是很少被修改的数据,可以防止脏读;
3)非严D写型: 不保证缓存与数据库中数据的一致?对于极少被修?q且允许偶尔脏读的数?可以采用q种{略;
4)只读? 对于从来不会(x)被修改的数据,如参考数?可以使用q个{略;
只有W合以下条g的数据才适合于存攑ֈW二U缓存中:
1) 很少被修改的数据;
2) 不是很重要的数据,允许出现偶尔的ƈ发问?
3)不会(x)被ƈ发访问的数据;
4)参考数?
Hibernate的二U缓存SessionFactory是进E范围或集范围的缓?因此需要采用适当的ƈ发访问策?提供事务隔离U别,而且可以在每个类或每个集合的_度上配|第二~存.~存适配?Cache Provider)用于把具体的~存实现软g于Hibernate集成.Hibernateqؓ(f)查询l果提供了一个查询缓?它依赖于W二U缓?
理Hibernate的第一U缓?br />
Session为应用程序提供了两个理~存Ҏ(gu)evict(Object o)和clear()
evict(Object o) : 从缓存中清除参数指定的持久化对象;(适用于不希望session'按照该对象的状态变化来同步更新数据库和扚w更新或批量删除的场合)
clear(): 清空~存中所有持久化对象
*对于更好的批量更新或者批量删除的场合应该直接通过JDBC API讉K数据库的q程, 执行SQL语句来减Hibernate API的多ơsql执行, 或者调用相关的存储q程. q个时候还得注?br />
Transaction接口来声明事务边?
理Hibernate的第二~存
׃W二U缓存是可配|的插g,Hibernate允许选用以下cd的缓存插?
1) EHCache: q程范围内的~存, 对Hibernate的查询缓存提供了支持;(net.sf.hibernate.cache.EhCacheProvider EHCache插g的适配?
2) OpenSymphony OSCache: q程范围内的~存,提供了丰富的~存数据q期{略,对Hibernate的查询缓存提供了支持;(net.sf.hibernate.cache,OSCacheProvider OSCache插g
的适配?;
3) SwarmCache: 集范围的缓?但不支持Hibernate的查询缓?(net.sf.hibernate.cache.SwarmCacheProvider SwarmCache插g的适配?
4) JBossCache: 集范围内的~存,支持事务q发讉K{略,对Hibernate的查询缓存提供了支持;(net.sf.hibernate,cache.TreeCacheProvider JBossCache插g的适配?
配置W二U缓存主要包含以下步?
1) 在各个映文件中为持久化c设|第二~存后者在Hibernate的配|文件hibernate.cfg.xml中集中设|第二~存,讄它的命名~存的ƈ发访问策?
2)选择合适的~存插g,手工~辑配置文g,为每个命名缓存设|数据过期策?
<class name="mypack.Category" table="CATEGORIES">
<cache usage="read-write"/>
<id name="id" type="long" column="ID">
...
</class>
*如果只在category中配|cache,当调用category.getItems().iterate()Ҏ(gu)?Hibernate只会(x)把items集合中的元素存放到缓存中,此时Hibernate仅仅把与Category兌的Item对象的OID存放
到缓存中.如果希望把整个Item对象散装数据存入~存,应该在Item.hbm.xml文g中设|cache元素
***************************************************************************************************************************************************
在默认情况下,Session?x)在下面的时间点清理~存.
1) 当应用程序调用net.sf.hibernate.Transaction的commit()Ҏ(gu)的时?commit()Ҏ(gu)先清理缓? 然后再向数据库提交事?
2) 当应用程序调用Session的find()或者iterate()? 如果~存中持久化对象的属性发生了变化, ׃(x)先清理缓? 以保证查询结果能反映持久化对象的最新状?
3) 当应用程序显式调用Session的flush()Ҏ(gu)的时?
1. Session的save()Ҏ(gu)
saveҎ(gu)q不立即执行SQL insert语句, 只有当Session清理~存的时, 才会(x)执行SQL insert语句.如果在save()Ҏ(gu)之后, 又修改了持久化对象的属? q会(x)使得Session在清理缓
存时, 额外执行SQL update语句.
2. Session的update()Ҏ(gu)
updateҎ(gu)?x)生成或调用一个计划的update语句,q且Session只有在清理缓存的时候才?x)执行update语句,在执行时才会(x)把Customer对象当前的属性值组装到update语句?
**通过update()Ҏ(gu)使游d象被一个Session兌,即没有修改Customer对象的Q何属?Session在清理缓存时也会(x)执行由update()Ҏ(gu)计划的update语句. 如果希望Session仅仅当修
改了Customer对象的属性时, 才执行update语句, 可以把映文件中<class>元素的select-before-update设ؓ(f)true, 该属性的默认gؓ(f)false;
**当update()Ҏ(gu)兌一个游d象时, 如果在Session的缓存中已经存在相同OID的持久化对象,?x)抛出异?
3. Session的saveOrUpdate()Ҏ(gu)
saveOrUpdate()Ҏ(gu)同时包含了save()与update()Ҏ(gu)的功? 如果传入的参数是临时对象p用save()Ҏ(gu); 如果传入的参数是游离对象, p用update()Ҏ(gu); 如果传入的参?br />
是持久化对象, 那就直接q回.
4. Session的load()和get()Ҏ(gu)
Session的load()和get()Ҏ(gu)都能Ҏ(gu)l定的OID从数据库中加载一个持久化对象, q两个方法的区别在于: 当数据库中不存在与OID对应的记录时, load()Ҏ(gu)抛出
net.sf.hibernate.ObjectNotFoundException异常,而get()q回null.
5. Session的delete()Ҏ(gu)
如果传入的参数是持久化对? Sessionp划执行一个delete语句. 如果传入的参数是游离对象, 先游离对象被Session兌, 使它变ؓ(f)持久化对? 然后计划执行一个delete?br />
? Session只有在清理缓存的时候才?x)执行delete语句.
该方法也能删除多个对? 但不推荐,效率??session.delete("from Customer as c where c.id>8");
]]> W十一?Hibernate的检索方?/title> http://m.tkk7.com/Ericzhang5231/articles/query.htmlEric5231 Eric5231 Mon, 18 Feb 2008 08:11:00 GMT http://m.tkk7.com/Ericzhang5231/articles/query.html http://m.tkk7.com/Ericzhang5231/comments/180482.html http://m.tkk7.com/Ericzhang5231/articles/query.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/180482.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/180482.html
CreateQuery()
Query query = session.createQuery("from Customer as c where c.name=:customerName and c.age=:customerAge");
query.setString("customerName","Tom");
query.setInteger("customerAge",21);
createQuery()支持Ҏ(gu)铄E风?br />
QBC:(Criteria,Criterion,Expression)
Criteria criteria = session.createCriteria(Customer.class);
Criterion criterion1 = Expression.like("name", "T%");
Criterion criterion2 = Expression.like("age", new Integer(21));
Criteria = criteria.add(criterion1).add(criterion2);
List result = criteria.list();
HQL&&QBC支持多态和l承查询
HQL&&QBC支持排序和分?br />
HQL: Query query = session.createQuery("from Customer c order by c. name asc, c.age desc"); //排序
query.setFirstResult(10); //讑֮从对象开始检索v始位|ؓ(f)0
query.setMaxResults(10); //讑֮一ơ最多检索出的对象数?br />
QBC: Criteria criteria = session.createCriteria(Customer.class);
criteria.addOrder(Order.asc("name"));
criteria.addOrder(Order.desc("age"));
criteria.setFirstResult(0); //讑֮从对象开始检索v始位|ؓ(f)0
criteria.setMaxResult(10); //讑֮一ơ最多检索出的对象数?br />
参数l定能有效避免一些安全漏z?br />
HIbernateq能在xml文g里面配置HQL或者SQL本地查询语句:
//for HQL
<hibernate-mapping>
<class name="mypack.Customer" table="CUSTOMERS">
...
</class>
<query name="findCustomersByName"><![CDATA[from Customer c where c.name like :name]]></query>
</hibernate-mapping>
//for SQL
<sql-query name="findCustomersByName"><![CDATA[select {c.*} from CUSTOMERS c where c.NAME like :name]]>
<return alias="c" class="Customer"/>
</sql-query>
在程序中使用getNamedQuery()Ҏ(gu)获得查询语句:
Query query = session.getNamedQuery("findCustomersByName");
query.setString("name",name);
List result = query.list();
内连接:(x)利用内连接可获取两表的公共部分的记录Select * from A JOIN B ON A.Aid=B.Bnameid
当查询的只是对象的部分属性的时? 可以采用动态实例化查询l果,把实体的部分属性封装ؓ(f)一个javabean临时对象,不需要创建对?关系映射文g
package mypack;
import java.io.Serializable;
public class CustomerRow implements Serializable{
private Long id;
private String name;
private String orderNumber;
public CustomerRow(Long id, String name, String orderNumber){
this,id=id;
...
}
...
此处省略id,name和orderNumber属性的get和setҎ(gu)
...
}
在程序中可以l合HQL查询语句q样使用,
Iterator it = session.createQuery("select new mypack.CustomerRow(c.id,c.name,o.orderNumber)'
+'from Customer c join c,orders o where o,orderNumber like 'T%'").list().iterator();
此外如果l果集只有一个结?可以用uniqueResult()Ҏ(gu)
Object[] obj = (Object[])session.createQuery("select max(c.age),min(c.age) from Customer c").uniqueResult();
Integer maxAge = (Integer) obj[0];
Integer minAge = (Integer) obj[1];
l果集中可以通过利用set和sql的distinctL
动态查询适宜用QBC(g)索方?可以化编E?
public List findCustomers (String name, int age) throws HibernateException{
Criteria criteria = session,createCriteria(Customer,class);
if(name != null){
criteria.add(Expression.like("name",nam.toLowerCase(),MactchMode.ANYWHWERE));
}
if(age!=0){
crteria.add(Expression.eq("age",new Integer(age)));
}
return criteria.list();
}
集合qo(h): 当orders集合׃使用延迟(g)索策略而没有在开始被初始?当调用get***().iterator()Ҏ(gu)初始化的时候不能对q个集合q行排序或者条件过?通过?br />
用集合过滤就能解册个问?
List result = session.createFilter(customer.getOrders(), "where this.price>100 order by this.price") .list();
集合qo(h)除了用于为集合排序或讄U束条g,q可?
1) 为集合分?br />
List result = session.createFilter(customer.getOrders(), "order by this,price asc")
.setFirstResult(10)
.setMaxResult(50)
.list();
2)只选择集合的某个属?br />
List result = session.createFilter(customer.getOrders(), "select this.orderNumber").list();
]]> W九(ji)?Hibernate的映类?/title> http://m.tkk7.com/Ericzhang5231/articles/hibernateMappingType.htmlEric5231 Eric5231 Thu, 24 Jan 2008 07:57:00 GMT http://m.tkk7.com/Ericzhang5231/articles/hibernateMappingType.html http://m.tkk7.com/Ericzhang5231/comments/177518.html http://m.tkk7.com/Ericzhang5231/articles/hibernateMappingType.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/177518.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/177518.html
1.内置映射cd
1).Java基本cd的Hibernate映射cd
Javacd
Hibernate映射cd
标准SQLcd
大小和取D?/td>
int/Integer
int/integer
INTEGER
4Byte
long/Long
long
BIGINT
8Byte
short/Short
short
SAMLLINT
2Byte
byte/Byte
byte
TINYINT
1Byte
float/Float
float
FLOAT
4Byte
double/Double
double
DOUBLE
8Byte
BigDecimal
big_decimal
NUMBERIC
Numeric(8,2)
char/Character/String
character
CHAR(1)
定长字符
String
string
VARCHAR
变长字符
boolean/Boolean
boolean
BIT
布尔cd
boolean/Boolean
yes/no
CHAR(1)('Y'/'N')
布尔cd
boolean/Boolean
true/false
CHAR(1)('T'/'F')
布尔cd
2). Java旉和日期类型的Hibernate映射cd
Javacd
Hibernate映射cd
标准SQLcd
描述
java.util.Date/java.sql.Date
date
DATE
日期Qyyyy-mm-dd
java.util.Date/java.sql.TIme
time
TIME
旉QhhQmmQss
java.util.Date/java.sql.Timestamp
timestamp
TIMESTAMP
旉戻Iyyyymmddhhmmss
java.util.Calendar
calendar
TIMESTAMP
同上
java.util.Calendar
calendar_date
DATE
日期Qyyyy-mm-dd
* 当程序类型ؓ(f)java.sql.Timestamp, 数据库中表属性类型ؓ(f)timestamp的情况下Q即使用户以I值插入数据,数据库系l仍然会(x)自动填充timestamp的?br />
3). Java 大对象类型的Hibernate映射cd
Javacd
Hibernate映射cd
标准SQLcd
MySqlcd
Oraclecd
byte[]
binary
VARBINARY/BLOB
BLOB
BLOB
String
text
CLOB
TEXT
CLOB
serializable
实现serializable接口的一个javac?/td>
VARBINARY/BLOB
BLOB
BLOB
java.sql.Clob
clob
CLOB
TEXT
CLOB
java.sql.Blob
blob
BLOB
BLOB
BLOB
* 在应用程序中通过Hibernate来保存java.sql.Clob或者java.sql.Blob实例Ӟ必须包含两个步骤Q?br />
a. 在一个数据库事务中先保存一个空的Blob或Clob实例Qb. 接着锁定q条记录Q更新在步骤Q?Q中保存的Blob或Clob实例Q把二进制数据或长文本数据写到Blob或Clob实例中?br />
1
2 Session session = sessionFactory.openSession();
3 Transaction tx = session.beginTransaction();
4 Customer customer = new Customer();
5 customer.setDescription(Hibernate.createClob("" )); // 先保存一个空的clob
6 session.save(customer);
7 session.flush();
8 // 锁定q条记录
9 session.refresh(customer,LockMode.UPGRADE);
10 oracle.sql.CLOB clob = (oracle.sql.CLOB) customer.getDescription();
11 java.io.Writer pw = clob.getCharacterOutStream();
12 pw.write(longText);// longText是一个长度超q?55的字W串
13 pw.close();
14 tx.commit();
15 session.close();
* 一个javacd对应多个Hibernate映射cd的场合。例如,如果持久化类的属性ؓ(f)java.util.DatecdQ对应的Hibernate映射cd可以是date,time
或timestamp。此时必L据对应的数据库表的字D늚SQLcdQ来定Hibernate映射cd。如果字Dؓ(f)DatecdQ则hibernate映射为datgeQ如果ؓ(f)TIME则ؓ(f)timeQ如果ؓ(f)TIMESTAMP则ؓ(f)timestamp?br />
2.客户化映类?br />
Q很ȝ(ch)的一个东西,E微看了看,日后需要再研究qȝQ?
]]> W八?映射l成关系 http://m.tkk7.com/Ericzhang5231/articles/AggregationRelation.htmlEric5231 Eric5231 Wed, 23 Jan 2008 12:47:00 GMT http://m.tkk7.com/Ericzhang5231/articles/AggregationRelation.html http://m.tkk7.com/Ericzhang5231/comments/177362.html http://m.tkk7.com/Ericzhang5231/articles/AggregationRelation.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/177362.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/177362.html
域模型中的聚集aggregation对象关系在关pL据模型中可以通过映射为组成关pL提高代码和数据库讉K质量。比如说一个customerhhomeAddress和comAddress属性,从域模型出发Q应该把homeAddress和comAddress抽取出来成ؓ(f)一个过E对象。而在关系数据模型中可以通过hibernate提供的组成关p进行映。映文件如下:(x)
1 < component name = " homeAddress " class = " com.homeAddress " >
2 < parent name = " customer " />
3 < property name = " street " type = " String " column = " HOME_STREET " />
4 < property name = " city " type = " String " column = " HOME_CITY " />
5
6 </ component >
q样q行映射后,q不需要ؓ(f)homeAddress和comAddress单独讄数据库表Q应该把homeAddress和comAddress的属性都和customer表放在一?br />
而有一点要格外注意的是Q域模型的组成对象homeAddress和comAddress对象除了h一般的属性成员变量外Q需要ؓ(f)hibernate提供一个parent属性,如下所C?br />
1 packge com;
2
3 import java.io.Serializabel;
4
5 public class HomeAddress implements Serializable {
6 private String street;
7 private String city;
8
9 private com.Customer customer;
10
11 public void setCustomer(Customer customer) { }
12 public Customer getCustomer() { }
hibernate提供的这U组成关pL允许嵌套?br />
1 < component >
2 < compoent >
3
4 </ componet >
5
6 </ component >
2. 区分值valuecd和实体Entitycd
Hibernate把持久化cȝ属性分为value和Entitycd。前者没有OIDQ不能被单独持久化,不能单独通过session加蝲Q它的生命周期依赖于所属的持久化类的对象生命周期,lgcd是一U类型;而后者有OIDQ可以被单独持久化。在通过ConfigurationcȝaddClassQ)(j)Ҏ(gu)加蝲映射文gӞ只需要加载与valuecd对应的实体类型,而不需要单独加载组件类。当通过hibernateq行数据库操作的时候,hibernate?x)自动把lgcȝ属性{换ؓ(f)实体cȝ属性,从而和table的列对应h
]]> W六?映射对象标识W?/title> http://m.tkk7.com/Ericzhang5231/articles/OID.htmlEric5231 Eric5231 Mon, 21 Jan 2008 13:45:00 GMT http://m.tkk7.com/Ericzhang5231/articles/OID.html http://m.tkk7.com/Ericzhang5231/comments/176846.html http://m.tkk7.com/Ericzhang5231/articles/OID.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/176846.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/176846.html
标识W生成器
描述
备注
increment
由hibernate通过计算maxQIDQ来获得标识W,q自动以递增的方式增?/td>
只适用于单个hibernate应用q程讉K同一个数据库场合Q在集群环境下不推荐
identity
有底层数据库自动增长支持Q因此必L底层数据库支持的自动增长cd
longQintQshort
sequence
Ҏ(gu)底层数据库的序列来生成标识符
longQintQshort
hilo
Ҏ(gu)high/low法来生成标识符
longQintQshort
native
Ҏ(gu)底层数据库对自动生成标识W的支持能力来选择identityQsequenece或hilo
longQintQshort
uuid.hex
采用128位的UUID生成在网l环境下唯一的字W串标识W,单占I间比较?/td>
longQintQshort
assigned
由javaE序负责生成标识W?/td>
longQintQshort
]]> W七?持久化对?/title> http://m.tkk7.com/Ericzhang5231/articles/persistentObject.htmlEric5231 Eric5231 Mon, 21 Jan 2008 13:25:00 GMT http://m.tkk7.com/Ericzhang5231/articles/persistentObject.html http://m.tkk7.com/Ericzhang5231/comments/176842.html http://m.tkk7.com/Ericzhang5231/articles/persistentObject.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/176842.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/176842.html
<p>1Q与Java对象在JVM中的生命周期cMQJava对象在Hibernate的session中也有生命周期类似的状态。在Hibernate的session中,对象?U状态:(x)临时状态,持久化状态,游离状态?lt;br />
a. 临时状态(transientQ,刚new出来的对象,q没有被session持久化,不处于session的缓存中<br />
b.持久化状态(persistentQ,已经被持久化Q在数据库中有相应的记录Q,q且存在于session的缓存中<br />
c. 游离状态(detachedQ,已经被持久化Q在数据库中可能存在也可能不存在相应的记录)(j)Q不存在于session的缓存中<br />
<br />
单的用个例子描述一下:(x)<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080"> 1</span><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000"><img alt="" src="http://m.tkk7.com/Images/dot.gif" /><br />
</span><span style="color: #008080"> 2</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />tx </span><span style="color: #000000">=</span><span style="color: #000000"> session.beginTransaction();<br />
</span><span style="color: #008080"> 3</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />Customer c1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> Customer(</span><span style="color: #000000">"</span><span style="color: #000000">Tom</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #0000ff">new</span><span style="color: #000000"> HashSet()); //c1 处于临时状?lt;br />
</span><span style="color: #008080"> 4</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />session.save(c1); //c1转换为持久化状?lt;br />
</span><span style="color: #008080"> 5</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />Long id </span><span style="color: #000000">=</span><span style="color: #000000"> c1.getId();<br />
</span><span style="color: #008080"> 6</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />c1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
</span><span style="color: #008080"> 7</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />Customer c2 </span><span style="color: #000000">=</span><span style="color: #000000"> (Customer)session.load(Customer.</span><span style="color: #0000ff">class</span><span style="color: #000000">,id); //c2 处于持久化状?lt;br />
</span><span style="color: #008080"> 8</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />tx.commit();<br />
</span><span style="color: #008080"> 9</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />session.close(); //c1转换为游ȝ?<br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img alt="" src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />c2 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">; //c2转换为游ȝ?lt;/span></div>
<br />
<br />
<br />
2Q对象的状态{?lt;br />
<img height="277" alt="" src="http://m.tkk7.com/images/blogjava_net/ericzhang5231/StateTransform.jpg" width="398" border="0" /><br />
<br />
<table style="width: 1000px; height: 195px" cellspacing="2" cellpadding="2" width="1000" border="0">
<tbody>
<tr>
<td>状态名U?lt;/td>
<td>状态特?lt;/td>
<td>q入条g</td>
<td>备注</td>
</tr>
<tr>
<td>临时对象</td>
<td>
<p>1.不存在Q何一个sessionQ?lt;/p>
<p>2.在数据库没有相应的记录;</p>
</td>
<td>
<p>1. 通过newQ?lt;/p>
<p>2.Session通过delete()把持久化对象和游d象{化ؓ(f)临时对象</p>
</td>
<td></td>
</tr>
<tr>
<td>持久化对?lt;/td>
<td>
<p>1.L被一个Session对象兌Q?lt;/p>
<p>2.在数据库有相应的记录Q?lt;br />
3.session清理~存的时候,?x)根据持久化对象的属性变化(其实Ҏ(gu)快照Q,来同步更新数据库</p>
</td>
<td>
<p>1.session的save()把(f)时对象{化持久化对象Q?lt;br />
2.session的load()或get()q回的对象;<br />
3.session的find()q回的对象;<br />
4.session的update(),saveOrUpdate()和lock()使游d象{变ؓ(f)持久化对象;<br />
5.当一个持久化对象兌一个(f)时对象,当允许联保存的情况下,临时对象也{化ؓ(f)持久化对象;</p>
<p> </p>
</td>
<td>1.避免多个session实例兌一个Java对象</td>
</tr>
<tr>
<td>游离对象 </td>
<td>
<p>1.不被session兌Q?lt;/p>
<p>2.游离对象是由持久化对象{化过来的Q数据库中可能存在也可能不存在相应的记录Q?lt;/p>
</td>
<td>
<p>1.session的close()Q把~存中的所有持久化对象都{变ؓ(f)游离对象Q?lt;/p>
<p>2.session的evict()Q把~存中的一个持久化对象删除Q它变成游ȝ态;</p>
</td>
<td>1.游离对象和(f)时对象的区别在于数据库是否存在相应的记录</td>
</tr>
</tbody>
</table>
<br />
<br />
<br />
3)Session的缓存以?qing)API<br />
1.SessionQ在Session接口的实现类SessionImpl中定义了一pd的Java集合Q这些集合构成了Sessiond~存<br />
2.APIQ?lt;br />
<table style="width: 1005px; height: 270px" cellspacing="2" cellpadding="2" width="1005" border="0">
<tbody>
<tr>
<td>save()</td>
<td>
<p>1.在save一个(f)时对象之前,讄对象的主键IDQ没效果Q?lt;/p>
<p>2.在save一个对象之后,对象主键ID不能修改Q否则抛异常Q?lt;br />
3.如果主键ID是用nactive方式生成的,一旦调用session的saveҎ(gu)Qhibernate?x)立卛_数据库插入数据;<br />
4.save用来持久化一个(f)时对象,若持久一个持久化对象Q没效果Q若持久一个游d象,?x)重新插入数据?lt;/p>
</td>
</tr>
<tr>
<td>update()</td>
<td>
<p>1.session清理~存的时候,才会(x)L行update()产生的sql语句Q因此即使程序多ơ修改对象属性,最后只?x)更新最后的修改Q?lt;/p>
<p>2.通过update()使一个游d象被一个session兌Q即使没有修改对象属性,在清理缓存的时候也?x)执行update()产生sql语句<br />
Q如果希望仅当修改对象属性才q行updateQ可?amp;lt;class>元素的select-before-update讄为trueQ;<br />
3.当update()Ҏ(gu)兌一个游d象,如果session中存在相同OID的持久化对象Q会(x)抛出异常Q?lt;br />
4.当update()Ҏ(gu)兌一个游d象,如果数据库中不存在相应记录,?x)抛出异常?lt;/p>
</td>
</tr>
<tr>
<td>saveOrUpdate()</td>
<td>
<p>1.如果传入的是临时对象Q调用save(); 如果传入的是持久化对象,调用update();</p>
</td>
</tr>
<tr>
<td>load(), get()</td>
<td>1.两者都是根据OID从数据库中加载持久化对象Q区别是Q当数据库不存在与OID对应的记录,load()?x)抛出net.sf.hibernate.ObjectNotFoundExceptionQ而get()Ҏ(gu)q回nullQ?lt;/td>
</tr>
<tr>
<td>delete()</td>
<td>1.对传入的是持久化对象Qsession按照预先的sql语句删除一个记录;如果是一个游L对象,?x)把它关联到sessionQ在按照sql语句删除记录</td>
</tr>
</tbody>
</table>
<br />
3.session的联:(x)因ؓ(f)对象是相互关联,因此在session存放的是一副相互关联的对象图。在对象-兌映射文g中,用于映射持久化类之间兌的元素,?amp;lt;set>,<many-to-one>,<one-to-many>Q都有一个cascade属性。casecade属性值如下:(x)<br />
<table cellspacing="2" cellpadding="2" width="500" border="0">
<tbody>
<tr>
<td>属性?lt;/td>
<td>描述</td>
</tr>
<tr>
<td>none</td>
<td>默认|忽略兌对象</td>
</tr>
<tr>
<td>save-update</td>
<td>session对当前对象调用save(),update(),saveOrUpdate()Q联保存关联的临时对象Q联更新关联的游离对象</td>
</tr>
<tr>
<td>delete</td>
<td>U联删除所有关联的对象</td>
</tr>
<tr>
<td>all</td>
<td>包含save-update(),delelte()行ؓ(f)Q当对当前对象执行evict()或lock()Q联执行关联的对象</td>
</tr>
<tr>
<td>delete-orphan</td>
<td>删除所有和当前对象解除兌关系的对?lt;/td>
</tr>
<tr>
<td>all-delete-orphan</td>
<td>包含all和delete-orphan的行?lt;/td>
</tr>
</tbody>
</table>
]]> 关于hibernate category http://m.tkk7.com/Ericzhang5231/articles/hibernate.htmlEric5231 Eric5231 Mon, 21 Jan 2008 12:03:00 GMT http://m.tkk7.com/Ericzhang5231/articles/hibernate.html http://m.tkk7.com/Ericzhang5231/comments/176821.html http://m.tkk7.com/Ericzhang5231/articles/hibernate.html#Feedback 0 http://m.tkk7.com/Ericzhang5231/comments/commentRss/176821.html http://m.tkk7.com/Ericzhang5231/services/trackbacks/176821.html
很久之前因ؓ(f)评目的缘故,杂七杂八的学了一D|间hibernateQ实操也不多Q在pccw实习(fn)的那D|间一直虽然接触着hibernateQ但是从来都是扮演着木头的角Ԍ没有真正思考过用得对不对,如果不对Q又应该怎么L善或者提?br />
q段旉Q闲着也闲着Q回去pccw是不可能的了Qhq是要有自己的原则的Q破坏了自己的原则,你在别h心中的Ş象也?x)随之而毁的;q脆静下心来Q在学习(fn)C西之前,好好重新复习(fn)一些东西,好好把孙卫琴的《精通Hibernate》复?fn)一?br />
于是hibernateq个Category应运而生
]]>
վ֩ģ壺
ҹƬ̨ |
3pһ |
ҹҹƵۿ |
һ
|
Ʒһ
|
ҹƵѳ |
ѹۿ+ձ |
벻Ƶ߹ۿ |
ձƵ |
ִӲֻˬƵ
|
þWWW˳һƬ |
ѾƷԲ |
ȫaëƬѿ |
Ʒҹѹۿ |
ҹav뾫Ʒ |
ۺϺݺݰ |
AVרAV |
þþƷ |
ްɫɫùۿ |
ۺ߹ۿ |
ëƬ߹ۿ
|
ҳ߹ۿ |
þþþþƷ |
AVպAAVӰ |
JIZZйJIZZѿ |
һƷһAVһ |
Ʒѹۿ |
ձһƬ2019 |
ۺҹ
|
þˮAV뾫Ʒ |
ֱƵ |
ůůձ |
ҰƵ |
һaƬɫëƬ |
avַ |
ĻĻɫ |
պƬѹۿվ |
APPѹۿƵ |
ѿԿƵƵsɫ |
պƷӰһ |
þҹɫƷAV
|