??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产综合精品中文字幕 ,亚洲成人午夜在线,久久久无码精品亚洲日韩软件http://www.tkk7.com/ltc603/category/14100.html<font size="3">学无止境</font> <br> <script type="text/javascript" src="http://wujunlove.googlepages.com/bigstaticeyes.js"></script>zh-cnTue, 27 Feb 2007 21:18:19 GMTTue, 27 Feb 2007 21:18:19 GMT60Hibernate配置文g在单元测试中的灵z运?/title><link>http://www.tkk7.com/ltc603/archive/2006/08/31/66778.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Thu, 31 Aug 2006 01:47:00 GMT</pubDate><guid>http://www.tkk7.com/ltc603/archive/2006/08/31/66778.html</guid><wfw:comment>http://www.tkk7.com/ltc603/comments/66778.html</wfw:comment><comments>http://www.tkk7.com/ltc603/archive/2006/08/31/66778.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ltc603/comments/commentRss/66778.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ltc603/services/trackbacks/66778.html</trackback:ping><description><![CDATA[转蝲Q?a >http://blog.csdn.net/ufoer23/archive/2005/02/24/299619.aspx</a><br /><br /><p>2005 q?1 ?</p><blockquote>Hibernate 是一个流行的开源对象关pL工P单元试和持l集成的重要性也得到了广泛的推广和认同,在采用了Hibernate的项目中如何保证试的自动化和持l性呢Q本文讨ZHibernate加蝲光|文件hibernate.properties和hibernate.cfg.xml的过E,以及怎么样将hibernate提供的配|文件的讉KҎ(gu)灉|q用到单元测试中?/blockquote><p><a name="IDA3RYV"><span id="000woc0" class="atitle2">1 介绍</span></a><br />Hibernate 是一个流行的开源对象关pL工P单元试和持l集成的重要性也得到了广泛的推广和认同,在采用了Hibernate的项目中如何保证试的自动化和持l性呢Q本文讨ZHibernate加蝲光|文件hibernate.properties和hibernate.cfg.xml的过E,以及怎么样将hibernate提供的配|文件的讉KҎ(gu)灉|q用到单元测试中。注意:本文以hibernate2.1作ؓ讨论的基Q不保证本文的观炚w合于其他版本?/p><p><a name="IDADSYV"><span id="868eu0s" class="atitle2">2 读?/span></a><br />Java开发h员,要求熟?zhn)JUnit和掌握Hibernate的基知识</p><p><a name="IDAJSYV"><span id="cgsk00u" class="atitle2">3 内容</span></a><br /></p><p><a name="IDAOSYV"><span id="8iqswc0" class="atitle3">3.1.准备</span></a><br />对于hibernate的初学者来_W一ơ用hibernate的经验通常是:</p><p>1Q?安装配置好HibernateQ我们后面将%HIBERNATE_HOME%作ؓ对Hibernate安装目录的引用,</p><p>2Q?开始创建好自己的第一个例子,例如hibernate手册里面的类CatQ?/p><p>3Q?配置好hbm映射文gQ例如Cat.hbm.xmlQ本文不讨论q个文g内配|项的含义)和数据库Q如hsqldbQ,</p><p>4Q?在项目的classpath路径下添加一个hibernate.cfg.xml文gQ如?W一ơ用hibernate最常见的配|内?Q?/p><a name="IDAYSYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.url">jdbc:hsqldb:hsql://localhost</property> <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="connection.username">sa</property> <property name="connection.password"></property> <property name="dialect">net.sf.hibernate.dialect.HSQLDialect</property> <property name="hibernate.show_sql">false</property> <mapping resource="Cat.hbm.xml"/> </session-factory> </hibernate-configuration> </code></pre></td></tr></tbody></table><p>5Q?然后q需要提供一个类来测试一下创建,更新Q删除和查询CatQ对于熟(zhn)JUnit的开发h员,可以创徏一个单元测试类来进行测试,如下Q?/p><a name="IDAATYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> import junit.framework.TestCase; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; import net.sf.hibernate.cfg.Configuration; public class CatTest extends TestCase { private Session session; private Transaction tx; protected void setUp() throws Exception { Configuration cfg = new Configuration().configure();////注意q一行,q是本文重点讨论研究的地斏V? session = cfg.buildSessionFactory().openSession(); tx = session.beginTransaction(); } protected void tearDown() throws Exception { tx.commit(); session.close(); } public void testCreate() { //请在此方法内d相关的代码,本文不讨论怎么样用Hibernate API? } public void testUpdate() { //请在此方法内d相关的代码,本文不讨论怎么样用Hibernate API? } public void testDelete() { //请在此方法内d相关的代码,本文不讨论怎么样用Hibernate API? } public void testQuery() { //请在此方法内d相关的代码,本文不讨论怎么样用Hibernate API? } } </code></pre></td></tr></tbody></table><p><a name="IDAHTYV"><span id="ymkuw8c" class="atitle3">3.2 new Configuration()都做了什么?</span></a><br />对于W一ơ用hibernate的新手来_下面的这D代码可以说是最常见的用Configuration方式?/p><a name="IDANTYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> Configuration cfg = new Configuration().configure(); </code></pre></td></tr></tbody></table><p>Configuration是hibernate的入口,在新Z个Configuration的实例的时候,hibernate会在classpath里面查找hibernate.properties文gQ如果该文g存在Q则该文g的内容加载到一个Properties的实例GLOBAL_PROPERTIES里面Q如果不存在Q将打印信息</p><a name="IDAVTYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> hibernate.properties not found </code></pre></td></tr></tbody></table><p>然后是将所有系l环境变量(System.getProperties()Q也d到GLOBAL_PROPERTIES里面Q?a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">?</a>Q。如果hibernate.properties文g存在Q系l还会验证一下这个文仉|的有效性,对于一些已l不支持的配|参敎ͼpȝ打印警告信息?/p><p><a name="IDACUYV"><span id="c0qe0y0" class="atitle3">3.3. configure()在做什么?</span></a><br />new Configuration()讨论xQ下面讨论configure()Ҏ(gu)?/p><p>configure()Ҏ(gu)默认会在classpath下面Lhibernate.cfg.xml文gQ如果没有找到该文gQ系l会打印如下信息q抛出HibernateException异常?/p><a name="IDAJUYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> hibernate.cfg.xml not found </code></pre></td></tr></tbody></table><p>如果扑ֈ该文Ӟconfigure()Ҏ(gu)会首先访?lt; session-factory >Qƈ获取该元素的name属性,如果非空Q将用这个配|的值来覆盖hibernate.properties的hibernate.session_factory_name的配|的|从这里我们可以看出,hibernate.cfg.xml里面的配|信息可以覆盖hibernate.properties的配|信息?/p><p>接着configure()Ҏ(gu)讉K<session-factory>的子元素Q首先将使用所有的<property>元素配置的信息(<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">?</a>Q,如前面我们用的配置文g</p><a name="IDAXUYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> <property name="connection.url">jdbc:hsqldb:hsql://localhost</property> <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="connection.username">sa</property> <property name="connection.password"></property> <property name="dialect">net.sf.hibernate.dialect.HSQLDialect</property> </code></pre></td></tr></tbody></table><p>会覆盖hibernate.properties里面对应的配|,hibernate2.1发布包里面自带的hibernate.properties文gQ位?HIBERNATE_HOME%/etc下面Q里面的|如下Q?/p><a name="IDA5UYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> hibernate.dialect net.sf.hibernate.dialect.HSQLDialect hibernate.connection.driver_class org.hsqldb.jdbcDriver hibernate.connection.username sa hibernate.connection.password hibernate.connection.url jdbc:hsqldb:hsql://localhost </code></pre></td></tr></tbody></table><p>然后configure()会顺序访问以下几个元素的内容</p><a name="IDAHVYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> <mapping> <jcs-class-cache> <jcs-collection-cache> <collection-cache> </code></pre></td></tr></tbody></table><p>其中<mapping>是必不可的Q必通过配置<mapping>Qconfigure()才能讉K到我们定义的java对象和关pL据库表的映射文gQhbm.xmlQ,例如Q?/p><a name="IDAPVYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> <mapping resource="Cat.hbm.xml"/> </code></pre></td></tr></tbody></table><p>通过以上的分析,我们对hibernate配置文ghibernate.properties和hibernate.cfg.xml的默认的加蝲q程比较清楚了?/p><p><a name="IDAXVYV"><span id="agq8uyu" class="atitle3">3.4 Configuration的其他用?/span></a><br />Configuration的configure ()Ҏ(gu)q支持带参数的访问方式,你可以指定hbm.xml文g的位|,而不是用默认的classpath下面的hibernate.cfg.xmlq种方式Q例如:</p><a name="IDA3VYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> Configuration cfg = new Configuration().configure("myexample.xml"); </code></pre></td></tr></tbody></table><p>同时Configurationq提供了一pdҎ(gu)用来定制hibernate的加载配|文件的q程Q让你的应用更加灉|Q常用的是以下几U:</p><a name="IDAFWYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> addProperties(Element) addProperties(Properties) setProperties(Properties) setProperty(String, String) </code></pre></td></tr></tbody></table><p>通过以上几个Ҏ(gu)Q除了用默认的hibernate.properties文gQ你q可以提供多?properties配置文gQ用Hibernate的时候根据不同的情况使用不同的配|文Ӟ例如Q?/p><a name="IDANWYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> Properties properties = Properties.load("my.properties"); Configuration config = new Configuration().setProperties(properties).configure(); </code></pre></td></tr></tbody></table><p>除了指定.properties文g之外Q还可以指定.hbm.xml文gQ下面列出几个常用的Ҏ(gu)Q?/p><a name="IDAVWYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> addClass(Class) addFile(File) addFile(String) addURL(URL) </code></pre></td></tr></tbody></table><p>前面我们已经讲了Qconfigure()Ҏ(gu)默认是通过讉Khibernate.cfg.xml?lt;mapping>元素来加载我们提供的.hbm.xml文gQ上面列出的Ҏ(gu)可以直接指定hbm.xml文gQ例如addClass()Ҏ(gu)可以直接通过指定class来加载对应的映射文gQhibernate会将提供的class的全名(包括packageQ自动{化ؓ文g路径Q如net.sf.hibernate.examples.quickstart.Cat.class对应了net/sf/hibernate/examples/quickstart/Cat.hbm.xmlQ还可以用addFileҎ(gu)直接指定映射文g?/p><p>例一Q?/p><a name="IDA4WYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> Configuration config = new Configuration().addClass(Cat.class); </code></pre></td></tr></tbody></table><p>例二Q?/p><a name="IDAGXYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> Configuration config = new Configuration().addURL(Configuration.class.getResource ("Cat.hbm.xml")); </code></pre></td></tr></tbody></table><p>例三Q?/p><a name="IDAOXYV"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> Configuration config = new Configuration().addFile("Cat.hbm.xml"); </code></pre></td></tr></tbody></table><p><a name="IDAVXYV"><span id="88g0umw" class="atitle3">3.5 ȝ</span></a><br />Configuration提供的这些方法的好处如下Q?/p><p>1Q?一个应用中往往有很?hbm.xml映射文gQ开发的q程中如果只是ؓ了测试某个或几个Java PO(Persistence Object)Q我们没有必要把所有的.hbm.xml都加载到内存Q这样可以通过addClass或者addFile直接Q显得非常灵zR?/p><p>2Q?学习Hibernate的过E中Q往往需要通过l习来体会Hibernate提供的各U特征,而很多特征是需要修攚w|文件的Q如果要观察相同的代码在不同的特征下的表玎ͼ需要手工改配置文gQ这样太ȝ了,而且Ҏ(gu)出错Q我们可以提供多个配|文Ӟ每个配置文g针对需要的特征而配|,q样我们在调用程序的时候,把不同的配置文g作ؓ参数传递进去,而程序代码里面用setProperties和addFile指定传入的配|文件参数就可以了?/p><p>3Q?在单元测试中Q特别是在集成测试里面,整个q程是自动化的,我们不能手工q预试q程Q往往需要准备多个配|文仉对不同的试案例Q这个时候setProperties和addFileҎ(gu)显得特别有用了Q在不同的测试案例中用这些方法来指定相应的配|文Ӟq样可以做到自动化试Q保证了持箋性?/p><p><a name="IDA4XYV"><span id="8a00cui" class="atitle3">3.6 应用举例</span></a><br />在刚开始学习hibernate的时候,对于hibernate的hbm映射文g里的各种配置参数没有一个感性的认识Q例如inverse="true",lazy="true"q样的配|参敎ͼ不通过实践是无法体会到其作用的Q传l的Ҏ(gu)是每需要测试一U参数的效果更改相应的配置文gQ然后运行测试来观察l果Q如果能够灵zȝq用Configuration提供的定刉|的Ҏ(gu)Q我们可以提供多个配|文Ӟ每个配置文g里面有不同的配置参数Q配合相应的试案例方便多了?/p><p>例如针对ono-to-many和many-to-one的双向关联的映射关系Q我们想试在one-to-many一方用inverse="false"和inverse="true"的不同效果,假设已经正确的配|好了hibernate.propertiesQ那么还需要提供两个不同的hbm.xml文gQ假讑ֈ别名为bidirect.inverse.false.hbm.xml和bidirect.inverse.true.hbm.xml?/p><p>然后需要写两个不同的测试案例,分别针对两个不同的配|文件进行测试就可以了,q样的好处是Q不用针对不同的试案例修改配置文gQ特别是在集成测试的时候,一切都是自动化的,如果每测试一个案例就需要手工去更改配置文gQ这肯定是一个失败的试?/p><p>代码模板如下Q?/p><a name="IDAKY3V"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> FalseInverseTest.java文g import junit.framework.TestCase; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; import net.sf.hibernate.cfg.Configuration; /** * test false inverse */ public class FalseInverseTest extends TestCase { private Session session; private Transaction tx; protected void setUp() throws Exception { Configuration cfg = new Configuration().addFile("bidirect.inverse.false.hbm.xml"); session = cfg.buildSessionFactory().openSession(); tx = session.beginTransaction(); } protected void tearDown() throws Exception { tx.commit(); session.close(); } public void testLogic() { //在此~写试代码 } } </code></pre></td></tr></tbody></table><p>TrueInverseTest.java文g</p><a name="IDASY3V"><b></b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code> import junit.framework.TestCase; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; import net.sf.hibernate.cfg.Configuration; /** * test true inverse */ public class TrueInverseTest extends TestCase { private Session session; private Transaction tx; protected void setUp() throws Exception { Configuration cfg = new Configuration().addFile("bidirect.inverse.true.hbm.xml"); session = cfg.buildSessionFactory().openSession(); tx = session.beginTransaction(); } protected void tearDown() throws Exception { tx.commit(); session.close(); } public void testLogic() { //在此~写试代码 } } </code></pre></td></tr></tbody></table><p><a name="IDAZY3V"><span id="80gugqo" class="atitle2">l束?/span></a><br />通过对Hibernate默认的配|文件的加蝲序和Hibernate提供的加载配|文件的Ҏ(gu)的讨论,我们对在使用到Hibernate的项目的单元试中用多个Hibernate配置文g有了比较清楚的认识?/p><p>持箋集成中的试的特征是自动化和持箋性,不能手工q预其过E,在用到Hibernate的项目如果要实现持箋集成Q就要ؓ不同的测试案例提供不同的配置文gQ而不是针对不同的试案例q行手工调整Q因此,在用到Hibernate的项目中灉|的运用多配置文gQ可以提高测试的效率Q保证自动化和持l性?/p><p><a name="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></a>?Q有关的代码请参考Environmentcȝstatic{}?/p><p><a name="2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></a>?Q如果在hibernate.cfg.xml?lt;property/>配置的name没有以hibernate开_那么configure()内部会自动在前面dhibernateQ例如connection.urlQhibernate会自动将其{化ؓhibernate.connection.url?/p><p><a name="resources"><span id="6coieus" class="atitle2">参考资?</span></a></p><ul><li>官方hibernate reference 地址Q?a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://hibernate.org</a><br /></li></ul><img src ="http://www.tkk7.com/ltc603/aggbug/66778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ltc603/" target="_blank">阿成</a> 2006-08-31 09:47 <a href="http://www.tkk7.com/ltc603/archive/2006/08/31/66778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Hibernate~存的用-Q(ZTQhttp://blog.csdn.net/woshichenxu/archive/2006/01/22/586361.aspxQ?/title><link>http://www.tkk7.com/ltc603/archive/2006/08/22/64954.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Tue, 22 Aug 2006 01:23:00 GMT</pubDate><guid>http://www.tkk7.com/ltc603/archive/2006/08/22/64954.html</guid><wfw:comment>http://www.tkk7.com/ltc603/comments/64954.html</wfw:comment><comments>http://www.tkk7.com/ltc603/archive/2006/08/22/64954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ltc603/comments/commentRss/64954.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ltc603/services/trackbacks/64954.html</trackback:ping><description><![CDATA[     摘要: 1.      关于 hibernate ~存的问题:...  <a href='http://www.tkk7.com/ltc603/archive/2006/08/22/64954.html'>阅读全文</a><img src ="http://www.tkk7.com/ltc603/aggbug/64954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ltc603/" target="_blank">阿成</a> 2006-08-22 09:23 <a href="http://www.tkk7.com/ltc603/archive/2006/08/22/64954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate学习W记http://www.tkk7.com/ltc603/archive/2006/08/16/63913.html阿成阿成Wed, 16 Aug 2006 07:37:00 GMThttp://www.tkk7.com/ltc603/archive/2006/08/16/63913.htmlhttp://www.tkk7.com/ltc603/comments/63913.htmlhttp://www.tkk7.com/ltc603/archive/2006/08/16/63913.html#Feedback0http://www.tkk7.com/ltc603/comments/commentRss/63913.htmlhttp://www.tkk7.com/ltc603/services/trackbacks/63913.html1、在映射一对多的双相关联关pLQ应该在oneҎ(gu)inverse属性设为trueQ可以提高应用的性能?br />2、徏立两个对象的双向兌Ӟ应该同时修改兌两端的对象的应用属性,q样使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的E序代码不受hibernate实现的媄响;同理Q当解除双相兌关系Ӟ也应该修改关联两端的对象的相应属性?br />eg://d
customer.getOrders().add(order);
order.setCustomer(customer);
//删除
customer.getOrders().remove(order);
order.setCustomer(null);
3、在定义一对多映射中“一”的POJOcLQ注意要private Set orders = new HashSet();//通常把它初始化ؓ集合实现cȝ一个实例,q样避免讉K取gؓnullQ引发NullPointerException异常Q提高健壮性?br />二、Session三种索方法:
1.load():Ҏ(gu)l定OID从数据库中加载一个持久化对象Q如数据库中没有则抛出net.sf.hibernate.ObjectNotFoundException异常?br />2.get():Ҏ(gu)l定OID从数据库中加载一个持久化对象Q如数据库中没有则返回null?br />3.find():按照参数指定的HQL语句加蝲一个或多个持久化对象,实际是HQL索方式的一U简写Ş式?br />三、hql查询Q?br />在数l和Collection中的查询Q?br />String hql = "select  u from User u where u in (:users)";
query.setParameterList("users", users);
//括号千万别忘写,否则出现如下错误Q?br />2006-07-07 11:07:35 WARN [org.hibernate.util.JDBCExceptionReporter] - SQL Error: 907, SQLState: 42000
2006-07-07 11:07:35 ERROR [org.hibernate.util.JDBCExceptionReporter] - ORA-00907: ~失x?img src ="http://www.tkk7.com/ltc603/aggbug/63913.html" width = "1" height = "1" />

阿成 2006-08-16 15:37 发表评论
]]>
Hibernate入门 - 包作用详?http://www.tkk7.com/ltc603/archive/2006/03/14/35293.html阿成阿成Tue, 14 Mar 2006 12:42:00 GMThttp://www.tkk7.com/ltc603/archive/2006/03/14/35293.htmlhttp://www.tkk7.com/ltc603/comments/35293.htmlhttp://www.tkk7.com/ltc603/archive/2006/03/14/35293.html#Feedback0http://www.tkk7.com/ltc603/comments/commentRss/35293.htmlhttp://www.tkk7.com/ltc603/services/trackbacks/35293.htmlHibernate一共包括了23个jar包,令hD~ؕ。本文将详细讲解Hibernate每个jar包的作用Q便于你在应用中Ҏ(gu)自己的需要进行取舍?

下蝲HibernateQ例?.0.3E_版本Q解压羃Q可以看C个hibernate2.jar和lib目录下有22个jar包:

hibernate2.jar:

Hibernate的库Q没有什么可说的Q必M用的jar?

cglib-asm.jar:

CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心的库Q必M用的jar?

dom4j.jar:

dom4j是一个Java的XML APIQ类gjdomQ用来读写XML文g的。dom4j是一个非帔R怼U的Java XML APIQ具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的YӞ可以在SourceForge上找到它。在IBM developerWorks上面可以扑ֈ一文章,对主的Java XML APIq行的性能、功能和易用性的评测Qdom4j无论在那个方面都是非常出色的。我早在近两年之前开始用dom4jQ直到现在。如今你可以看到来多的Java软g都在使用dom4j来读写XMLQ特别值得一提的是连Sun的JAXM也在用dom4j。这是必M用的jar包,Hibernate用它来读写配|文件?

odmg.jar:

ODMG是一个ORM的规范,Hibernate实现了ODMG规范Q这是一个核心的库,必须使用的jar包?

commons-collections.jarQ?

Apache Commons包中的一个,包含了一些Apache开发的集合c,功能比java.util.*强大。必M用的jar包?

commons-beanutils.jarQ?

Apache Commons包中的一个,包含了一些Bean工具cȝ。必M用的jar包?

commons-lang.jar:

Apache Commons包中的一个,包含了一些数据类型工LQ是java.lang.*的扩展。必M用的jar包?

commons-logging.jar:

Apache Commons包中的一个,包含了日志功能,必须使用的jar包。这个包本n包含了一个Simple LoggerQ但是功能很弱。在q行的时候它会先在CLASSPATH找log4jQ如果有Q就使用log4jQ如果没有,找JDK1.4带的java.util.loggingQ如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾Q当初Apache极力游说Sun把log4j加入JDK1.4Q然而JDK1.4目组已经接近发布JDK1.4产品的时间了Q因此拒l了Apache的要求,使用自己的java.util.loggingQ这个包的功能比log4j差的很远Q性能也一般。后来Apache开发出来了commons-logging.jar用来兼容两个logger。因此用commons-logging.jar写的logE序Q底层的Logger是可以切换的Q你可以选择log4jQjava.util.logging或者它自带的Simple Logger。不q我仍然强烈使用log4jQ因为log4j性能很高Qlog输出信息旉几乎{于System.outQ而处理一条logq_只需?us。你可以在Hibernate的src目录下找到Hibernate已经Z准备好了的log4j的配|文Ӟ你只需要到Apache |站M载log4j可以了。commons-logging.jar也是必须的jar包?

使用Hibernate必须的jar包就是以上的q几个,剩下的都是可选的?



ant.jar:

Ant~译工具的jar包,用来~译Hibernate源代码的。如果你不准备修改和~译Hibernate源代码,那么没有什么用Q可选的jar?

optional.jarQ?

Ant的一个辅助包?



c3p0.jarQ?

C3PO是一个数据库q接池,Hibernate可以配置Z用C3POq接池。如果你准备用这个连接池Q就需要这个jar包?

proxool.jarQ?

也是一个连接池Q同上?

commons-pool.jar, commons-dbcp.jar:

DBCP数据库连接池QApache的Jakartal织开发的QTomcat4的连接池也是DBCP?

实际上Hibernate自己也实C一个非帔R常简单的数据库连接池Q加上上?个,你实际上可以在Hibernate上选择4U不同的数据库连接池Q选择哪一个看个h的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中用HibernateQ一定要用App Server的连接池Q不要用以上4U连接池Q否则容器管理事务不起作用?


connector.jar:

JCA 规范Q如果你在App Server上把Hibernate配置为Connector的话Q就需要这个jar。不q实际上一般App Server肯定会带上这个包Q所以实际上是多余的包?

jaas.jar:

JAAS是用来进行权限验证的Q已l包含在JDK1.4里面了。所以实际上是多余的包?

jcs.jarQ?

如果你准备在Hibernate中用JCS的话Q那么必d括它Q否则就不用?

jdbc2_0-stdext.jar:

JDBC2.0的扩展包Q一般来说数据库q接池会用上它。不qApp Server都会带上Q所以也是多余的?

jta.jarQ?

JTA规范Q当Hibernate使用JTA的时候需要,不过App Server都会带上Q所以也是多余的?

junit.jar:

Junit包,当你q行Hibernate自带的测试代码的时候需要,否则׃用?

xalan.jar, xerces.jar, xml-apis.jar:

Xerces是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般App Server都会带上QJDK1.4也包含了解析器,不过不是XercesQ是CrimsonQ效率比较差Q不qHibernate用XML只不q是d配置文gQ性能没什么紧要的Q所以也是多余的?/span>

阿成 2006-03-14 20:42 发表评论
]]>
hibernate二~存ȝ -------转蝲java视线上Areyouok?的文?/title><link>http://www.tkk7.com/ltc603/archive/2006/03/09/34548.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Thu, 09 Mar 2006 12:56:00 GMT</pubDate><guid>http://www.tkk7.com/ltc603/archive/2006/03/09/34548.html</guid><wfw:comment>http://www.tkk7.com/ltc603/comments/34548.html</wfw:comment><comments>http://www.tkk7.com/ltc603/archive/2006/03/09/34548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ltc603/comments/commentRss/34548.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ltc603/services/trackbacks/34548.html</trackback:ping><description><![CDATA[ <span id="6icuywu" class="postbody">很多人对二~存都不太了解,或者是有错误的认识Q我一直想写一文章介l一下hibernate的二U缓存的Q今天终于忍不住了?<br />我的l验主要来自hibernate2.1版本Q基本原理和3.0?.1是一LQ请原谅我的固不化?<br /><br />hibernate的session提供了一U缓存,每个sessionQ对同一个idq行两次loadQ不会发送两条sqll数据库Q但是session关闭的时候,一U缓存就失效了?<br /><br />二~存是SessionFactoryU别的全局~存Q它底下可以使用不同的缓存类库,比如ehcache、oscache{,需要设|hibernate.cache.provider_classQ我们这里用ehcacheQ在2.1中就?<br />hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider <br />如果使用查询~存Q加?<br />hibernate.cache.use_query_cache=true <br /><br /><br />~存可以单的看成一个MapQ通过key在缓存里面找value?<br /><br /><span style="font-weight: bold;">Class的缓?/span><br />对于一条记录,也就是一个PO来说Q是Ҏ(gu)ID来找的,~存的key是IDQvalue是POJO。无论listQloadq是iterateQ只要读Z个对象,都会填充~存。但是list不会使用~存Q而iterate会先取数据库select id出来Q然后一个id一个id的loadQ如果在~存里面有,׃~存取,没有的话去数据库load。假设是d~存Q需要设|: <br /><cache usage="read-write"/> <br />如果你用的二~存实现是ehcache的话Q需要配|ehcache.xml <br /><cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" /> <br />其中eternal表示~存是不是永q不时QtimeToLiveSeconds是缓存中每个元素Q这里也是一个POJOQ的时旉Q如果eternal="false"Q超q指定的旉Q这个元素就被移C。timeToIdleSeconds是发呆时_是可选的。当往~存里面put的元素超q?00个时Q如果overflowToDisk="true"Q就会把~存中的部分数据保存在硬盘上的时文仉面?<br />每个需要缓存的class都要q样配置。如果你没有配置Qhibernate会在启动的时候警告你Q然后用defaultCache的配|,q样多个class会共享一个配|?<br />当某个ID通过hibernate修改Ӟhibernate会知道,于是U除~存?<br />q样大家可能会想Q同L查询条gQ第一ơ先listQ第二次再iterateQ就可以使用到缓存了。实际上q是很难的,因ؓ你无法判断什么时候是W一ơ,而且每次查询的条仉常是不一LQ假如数据库里面?00条记录,id??00Q第一ơlist的时候出了前50个idQ第二次iterate的时候却查询?0?0号idQ那?0-50是从~存里面取的Q?1?0是从数据库取的,共发?+20条sql。所以我一直认为iterate没有什么用QL会有1+N的问题?<br />Q题外话Q有说法说大型查询用list会把整个l果集装入内存,很慢Q而iterate只select id比较好,但是大型查询L要分|的,谁也不会真的把整个结果集装进来,假如一?0条的话,iterate共需要执?1条语句,list虽然选择若干字段Q比iterateW一条select id语句慢一些,但只有一条语句,不装入整个结果集hibernateq会Ҏ(gu)数据库方a做优化,比如使用mysql的limitQ整体看来应该还是list快。) <br />如果惌对list或者iterate查询的结果缓存,p用到查询~存?<br /><br /><span style="font-weight: bold;">查询~存</span><br />首先需要配|hibernate.cache.use_query_cache=true <br />如果用ehcacheQ配|ehcache.xmlQ注意hibernate3.0以后不是net.sf的包名了 <br /><cache name="net.sf.hibernate.cache.StandardQueryCache" <br />maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600" <br />timeToLiveSeconds="7200" overflowToDisk="true"/> <br /><cache name="net.sf.hibernate.cache.UpdateTimestampsCache" <br />maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/> <br />然后 <br />query.setCacheable(true);//ȀzL询缓?<br />query.setCacheRegion("myCacheRegion");//指定要用的cacheRegionQ可?<br />W二行指定要使用的cacheRegion是myCacheRegionQ即你可以给每个查询~存做一个单独的配置Q用setCacheRegion来做q个指定Q需要在ehcache.xml里面配置它: <br /><cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" /> <br />如果省略W二行,不设|cacheRegion的话Q那么会使用上面提到的标准查询缓存的配置Q也是net.sf.hibernate.cache.StandardQueryCache <br /><br />对于查询~存来说Q缓存的key是根据hql生成的sqlQ再加上参数Q分늭信息Q可以通过日志输出看到Q不q它的输Z是很可读Q最好改一下它的代码)?<br />比如hqlQ?<br />from Cat c where c.name like ? <br />生成大致如下的sqlQ?<br />select * from cat c where c.name like ? <br />参数?tiger%"Q那么查询缓存的key*大约*是这L字符Ԍ我是凭记忆写的,q不_Q不q看了也该明白了Q: <br />select * from cat c where c.name like ? , parameter:tiger% <br />q样Q保证了同样的查询、同L参数{条件下h一Lkey?<br />现在说说~存的valueQ如果是list方式的话Qvalue在这里ƈ不是整个l果集,而是查询出来的这一串ID。也是_不管是listҎ(gu)q是iterateҎ(gu)Q第一ơ查询的时候,它们的查询方式很它们qx的方式是一LQlist执行一条sqlQiterate执行1+N条,多出来的行ؓ是它们填充了~存。但是到同样条gW二ơ查询的时候,都和iterate的行Z样了Q根据缓存的keyȝ存里面查CvalueQvalue是一串idQ然后在到class的缓存里面去一个一个的load出来。这样做是ؓ了节U内存?<br />可以看出来,查询~存需要打开相关cȝclass~存。list和iterateҎ(gu)W一ơ执行的时候,都是既填充查询缓存又填充class~存的?<br /><span style="font-weight: bold;">q里q有一个很Ҏ(gu)被忽视的重要问题Q即打开查询~存以后Q即使是listҎ(gu)也可能遇?+N的问题!</span>相同条gW一ơlist的时候,因ؓ查询~存中找不到Q不class~存是否存在数据QL发送一条sql语句到数据库获取全部数据Q然后填充查询缓存和class~存。但是第二次执行的时候,问题来了,如果你的class~存的超时时间比较短Q现在class~存都超时了Q但是查询缓存还在,那么listҎ(gu)在获取id串以后,会一个一个去数据库loadQ因此,class~存的超时时间一定不能短于查询缓存设|的时旉Q如果还讄了发呆时间的话,保证class~存的发呆时间也大于查询的缓存的生存旉。这里还有其他情况,比如class~存被程序强制evict了,q种情况p自己注意了?<br /><br />另外Q如果hql查询包含select字句Q那么查询缓存里面的value是整个l果集了?<br /><br />当hibernate更新数据库的时候,它怎么知道更新哪些查询~存呢? <br />hibernate在一个地方维护每个表的最后更新时_其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配|里面?<br />当通过hibernate更新的时候,hibernate会知道这ơ更新媄响了哪些表。然后它更新q些表的最后更新时间。每个缓存都有一个生成时间和q个~存所查询的表Q当hibernate查询一个缓存是否存在的时候,如果~存存在Q它q要取出~存的生成时间和q个~存所查询的表Q然后去查找q些表的最后更新时_如果有一个表在生成时间后更新q了Q那么这个缓存是无效的?<br />可以看出Q只要更新过一个表Q那么凡是涉及到q个表的查询~存失效了Q因此查询缓存的命中率可能会比较低?<br /><br /><span style="font-weight: bold;">Collection~存</span><br />需要在hbm的collection里面讄 <br /><cache usage="read-write"/> <br />假如class是CatQcollection叫childrenQ那么ehcache里面配置 <br /><cache name="com.xxx.pojo.Cat.children" <br />maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" <br />overflowToDisk="true" /> <br />Collection的缓存和前面查询~存的list一P也是只保持一串idQ但它不会因个表更新q就失效Q一个collection~存仅在q个collection里面的元素有增删时才失效?<br />q样有一个问题,如果你的collection是根据某个字D|序的Q当其中一个元素更C该字D|Q导致顺序改变时Qcollection~存里面的顺序没有做更新?<br /><br /><span style="font-weight: bold;">~存{略</span><br />只读~存Qread-onlyQ:没有什么好说的 <br />?写缓存(read-writeQ?E序可能要的更新数据 <br />不严格的?写缓存(nonstrict-read-writeQ:需要更新数据,但是两个事务更新同一条记录的可能性很,性能比读写缓存好 <br />事务~存QtransactionalQ:~存支持事务Q发生异常的时候,~存也能够回滚,只支持jta环境Q这个我没有怎么研究q?<br /><br />d~存和不严格d~存在实C的区别在于,d~存更新~存的时候会把缓存里面的数据换成一个锁Q其他事务如果去取相应的~存数据Q发现被锁住了,然后q接取数据库查询?<br />在hibernate2.1的ehcache实现中,如果锁住部分~存的事务发生了异常Q那么缓存会一直被锁住Q直?0U后时?<br />不严D写缓存不锁定~存中的数据?<br /><br /><br /><span style="font-weight: bold;">使用二~存的前|条?/span><br />你的hibernateE序Ҏ(gu)据库有独占的写访问权Q其他的q程更新了数据库Qhibernate是不可能知道的。你操作数据库必需直接通过hibernateQ如果你调用存储q程Q或者自׃用jdbc更新数据库,hibernate也是不知道的。hibernate3.0的大扚w更新和删除是不更CU缓存的Q但是据?.1已经解决了这个问题?<br />q个限制相当的棘手,有时候hibernate做批量更新、删除很慢,但是你却不能自己写jdbc来优化,很郁闷吧?<br />SessionFactory也提供了U除~存的方法,你一定要自己写一些JDBC的话Q可以调用这些方法移除缓存,q些Ҏ(gu)是: <br />void evict(Class persistentClass) <br />Evict all entries from the second-level cache. <br />void evict(Class persistentClass, Serializable id) <br />Evict an entry from the second-level cache. <br />void evictCollection(String roleName) <br />Evict all entries from the second-level cache. <br />void evictCollection(String roleName, Serializable id) <br />Evict an entry from the second-level cache. <br />void evictQueries() <br />Evict any query result sets cached in the default query cache region. <br />void evictQueries(String cacheRegion) <br />Evict any query result sets cached in the named query cache region. <br />不过我不q样做,因ؓq样很难l护。比如你现在用JDBC扚w更新了某个表Q有3个查询缓存会用到q个表,用evictQueries(String cacheRegion)U除?个查询缓存,然后用evict(Class persistentClass)U除了class~存Q看上去好像完整了。不q哪天你d了一个相x询缓存,可能会忘记更新这里的U除代码。如果你的jdbc代码到处都是Q在你添加一个查询缓存的时候,q知道其他什么地方也要做相应的改动吗Q?<br /><br />---------------------------------------------------- <br /><br /><span style="font-weight: bold;">ȝQ?/span><br />不要惛_然的以ؓ~存一定能提高性能Q仅仅在你能够驾驭它q且条g合适的情况下才是这L。hibernate的二U缓存限制还是比较多的,不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下ؕ用,可能会有1+N的问题。不当的使用q可能导致读数据?<br />如果受不了hibernate的诸多限Ӟ那么q是自己在应用程序的层面上做~存吧?<br />在越高的层面上做~存Q效果就会越好。就好像管盘有缓存,数据库还是要实现自己的缓存,管数据库有~存Q咱们的应用E序q是要做~存。因为底层的~存它ƈ不知道高层要用这些数据干什么,只能做的比较通用Q而高层可以有针对性的实现~存Q所以在更高的别上做缓存,效果也要好些吧?/span> <img src ="http://www.tkk7.com/ltc603/aggbug/34548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ltc603/" target="_blank">阿成</a> 2006-03-09 20:56 <a href="http://www.tkk7.com/ltc603/archive/2006/03/09/34548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几个老生常谈的hibernate问题http://www.tkk7.com/ltc603/archive/2006/02/15/30754.html阿成阿成Wed, 15 Feb 2006 02:09:00 GMThttp://www.tkk7.com/ltc603/archive/2006/02/15/30754.htmlhttp://www.tkk7.com/ltc603/comments/30754.htmlhttp://www.tkk7.com/ltc603/archive/2006/02/15/30754.html#Feedback0http://www.tkk7.com/ltc603/comments/commentRss/30754.htmlhttp://www.tkk7.com/ltc603/services/trackbacks/30754.html Hibenate作ؓ一UJava对象持久化技术,在很多大型的多层体系构架中得到应用,比如在开发一套电(sh)子商务系l可以以J2EE作ؓ体系构架QStructs作ؓjava Web应用框架Q以Hibenate实现对象持久化Q务,以EJB或者普通的javabean实现业务逻辑Q其实现q程的复杂度可想而知Q下面收集一些在Hibenate中多对多关系中应用技巧给大家分n

1.cascade="..."Q?/font>

cascade属性ƈ不是多对多关pM定要用的Q有了它只是让我们在插入或删除对像时更方便一些,只要在cascade的源头上插入或是删除Q所有cascade的关pd会被自己动的插入或是删除。便是ؓ了能正确的cascadeQunsaved-value是个很重要的属性?/font>

Hibernate通过q个属性来判断一个对象应该saveq是updateQ如果这龆韵蟮膇d是unsaved-value的话Q那说明q个对象不是persistence object要saveQinsert)Q如果id是非unsaved-value的话Q那说明q个对象是persistence objectQ数据库中已存在Q,只要updatep了。saveOrUpdateҎ(gu)用的也是q个机制?/font>

2.inverse="ture"?

inverse属性默认是false的,是说关pȝ两端都来l护关系。这个意思就是说Q如有一个Student, Teacher和TeacherStudent表,Student和Teacher是多对多对多关系Q这个关pȝTeacherStudentq个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来l护关系呢?在用hibernateӞ我们不会昄的对TeacherStudent表做操作?/font>

对TeacherStudent的操作是hibernate帮我们做的。hibernate是看hbm文g中指定的??l护关系Q那个在插入或删??Ӟ׃处发对关p表的操作。前提是"?q个对象已经知道q个关系了,是说关pd一头的对象已经set或是add??q个对象里来了。前面说qinverse默认是falseQ就是关pȝ两端都维护关p,对其中Q一个操作都会处发对表系表的操作。当在关pȝ一_如Student中的bag或set中用了inverseQ?true"Ӟ那就代表关系是由另一关维护的QTeacherQ。就是说当这插入StudentӞ不会操作TeacherStudent表,即Student已经知道了关pR只有当Teacher插入或删除时才会处发对关p表的操作?/font>

所以,当关pȝ两头都用inverse="true"是不对的Q就会导致Q何操作都不处发对关系表的操作。当两端都是inverse="false"或是default值是Q在代码对关pLC的l护也是不对的,会导致在关系表中插入两次关系。在一对多关系中inverse更有意义了。在多对多中Q在哪端inverse="true"效果差不多(在效率上Q。但是在一对多中,如果要一方维护关p,׃使在插入或是删除"一"Ҏ(gu)去update"?方的每一个与q个"一"的对象有关系的对象?/font>

而如果让"?斚wl护关系时就不会有update操作Q因为关pd是在多方的对象中的,直指插入或是删除多方对象p了。当然这时也要遍??方的每一个对象显C的操作修关pȝ变化体现到DB中。不怎样_q是??方维护关pL直观一些?

3.cascade和inverse有什么区别?

可以q样理解Qcascade定义的是关系两端对象到对象的U联关系Q而inverse定义的是关系和对象的U联关系?/font>

4.net.sf.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): 2, of class: Xxxxx

q个问题出现在要删除关系的一头时。如Q要删除一个已l和Student有关pȝTeacher。当tx.commit();时才会抛个异常。这时一个在关系另一头的Student对象中的Set或是List中把q个Teacher对象昄的remove掉,再session.delete(q个teacher);。这是ؓ了防止在Student端有cascade时把q个Teacher对象再存回DB?/font>

所以,q个异常的只有在Student的关pd义中有cascade="..."Q而且没有像上面说的显C的解除关系时才会出现。所以防止出现这个异常的Ҏ(gu)是Q?Q在Student端不用cascadeQ?Q或是用cascade的话Q就昄的删除对像中的关pR?3Q在Teacher端要用cascade?/font>

5.net.sf.hibernate.HibernateException: identifier of an instance of my.MyObject altered from N to N

q个异常其实不是多对多中帔R到的Q但是这个异常的提示不make senseQ所以提一下,是因为id的java对象中的type和hbm文g中定义的不一P如:java中用longQ而hbm中用type="integer"Qƈ且generator用的是identity时就会出现?/font>



阿成 2006-02-15 10:09 发表评论
]]>
延迟初始化错误(ERROR LazyInitializerQ是如何产生? http://www.tkk7.com/ltc603/archive/2006/02/13/30481.html阿成阿成Mon, 13 Feb 2006 09:24:00 GMThttp://www.tkk7.com/ltc603/archive/2006/02/13/30481.htmlhttp://www.tkk7.com/ltc603/comments/30481.htmlhttp://www.tkk7.com/ltc603/archive/2006/02/13/30481.html#Feedback0http://www.tkk7.com/ltc603/comments/commentRss/30481.htmlhttp://www.tkk7.com/ltc603/services/trackbacks/30481.html延迟初始化错误是q用Hibernate开发项目时最常见的错误。如果对一个类或者集合配|了延迟索策略,那么必须当代理类实例或代理集合处于持久化状态(卛_于Session范围内)Ӟ才能初始化它。如果在游离状态时才初始化它,׃产生延迟初始化错误?/p>

下面把Customer.hbm.xml文g?lt;class>元素的lazy属性设为trueQ表CZ用gq检索策略:

<class name="mypack.Customer" table="CUSTOMERS" lazy="true">

当执行Session的load()Ҏ(gu)ӞHibernate不会立即执行查询CUSTOMERS表的select语句Q仅仅返回Customercȝ代理cȝ实例Q这个代理类L以下特征Q?/p>

Q?Q?由Hibernate在运行时动态生成,它扩展了Customerc,因此它承了Customercȝ所有属性和Ҏ(gu)Q但它的实现对于应用E序是透明的?br />Q?Q?当Hibernate创徏Customer代理cd例时Q仅仅初始化了它的OID属性,其他属性都为nullQ因此这个代理类实例占用的内存很?br />Q?Q?当应用程序第一ơ访问Customer代理cd例时Q例如调用customer.getXXX()或customer.setXXX()Ҏ(gu)Q,Hibernate会初始化代理cd例,在初始化q程中执行select语句Q真正从数据库中加蝲Customer对象的所有数据。但有个例外Q那是当应用程序访问Customer代理cd例的getId()Ҏ(gu)ӞHibernate不会初始化代理类实例Q因为在创徏代理cd例时OID存在了Q不必到数据库中L询?br />
提示QHibernate采用CGLIB工具来生成持久化cȝ代理cRCGLIB是一个功能强大的Java字节码生成工P它能够在E序q行时动态生成扩展JavacL者实现Java接口的代理类。关于CGLIB的更多知识,请参考:http://cglib.sourceforge.net/?/font>

以下代码先通过Session的load()Ҏ(gu)加蝲Customer对象Q然后访问它的name属性:

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
customer.getName();
tx.commit();

在运行session.load()Ҏ(gu)时Hibernate不执行Q何select语句Q仅仅返回Customercȝ代理cȝ实例Q它的OID?Q这是由load()Ҏ(gu)的第二个参数指定的。当应用E序调用customer.getName()Ҏ(gu)ӞHibernate会初始化Customer代理cd例,从数据库中加载Customer对象的数据,执行以下select语句Q?/p>

select * from CUSTOMERS where ID=1;
select * from ORDERS where CUSTOMER_ID=1;

?lt;class>元素的lazy属性ؓtrueQ会影响Session的load()Ҏ(gu)的各U运行时行ؓQ下面D例说明?/p>

1Q如果加载的Customer对象在数据库中不存在QSession的load()Ҏ(gu)不会抛出异常Q只有当q行customer.getName()Ҏ(gu)时才会抛Z下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
mypack.Customer

2Q如果在整个Session范围内,应用E序没有讉KqCustomer对象Q那么Customer代理cȝ实例一直不会被初始化,Hibernate不会执行Mselect语句。以下代码试囑֜关闭Session后访问Customer游离对象Q?/p>

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
tx.commit();
session.close();
customer.getName();

׃引用变量customer引用的Customer代理cȝ实例在Session范围内始l没有被初始化,因此在执行customer.getName()Ҏ(gu)ӞHibernate会抛Z下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

由此可见QCustomer代理cȝ实例只有在当前Session范围内才能被初始化?/p>

3Qnet.sf.hibernate.Hibernatecȝinitialize()静态方法用于在Session范围内显式初始化代理cd例,isInitialized()Ҏ(gu)用于判断代理cd例是否已l被初始化。例如:

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
if(!Hibernate.isInitialized(customer))
Hibernate.initialize(customer);
tx.commit();
session.close();
customer.getName();

以上代码在Session范围内通过Hibernatecȝinitialize()Ҏ(gu)昑ּ初始化了Customer代理cd例,因此当Session关闭后,可以正常讉KCustomer游离对象?/p>

4Q当应用E序讉K代理cd例的getId()Ҏ(gu)Ӟ不会触发Hibernate初始化代理类实例的行为,例如Q?/p>

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
customer.getId();
tx.commit();
session.close();
customer.getName();

当应用程序访问customer.getId()Ҏ(gu)Ӟ该方法直接返回Customer代理cd例的OID|无需查询数据库。由于引用变量customer始终引用的是没有被初始化的Customer代理cd例,因此当Session关闭后再执行customer.getName()Ҏ(gu)QHibernate会抛Z下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed



阿成 2006-02-13 17:24 发表评论
]]>
վ֩ģ壺 AVרһ| 97߹ۿƵ| ޾ƷƵ| Ļձ޾þþ| һĿ޿鶹 | þùӾƷŮ| 91͵߹ۿ| ޹v߹ۿ| ҹѸƬۿ| ޾Ʒ˳߲va| Ů޾Ʒþþۺ| 91鶹˳ѹۿ| ˾ҹƵ| ޳˾Ʒþ| aëƬѧѹۿ| þùɫAVѹۿ| һëƬѹۿ| ޲ӰԺҹ߹ۿ| vvվ| 鶹˳Ƶ| ޾ƷƵ| ֳִִӲ3pƵ | ޾ƷһۺAV| AV뾫Ʒ鶹| ձ˳Ƶ| 91Ƶ| Ƭ| AVһþþƷ| AVպƷþþþþ| AV߹ۿɫ | aѹۿþav| ۺŷ㻨| 77777_ҹþö| ޹Ʒַ| ߹ۿӾѰ | ޾Ʒ| СƵѹۿ| ձһ߹ۿ| þѹۿƷ| һƬɫ | ޾ƷĻӰԺ|