﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-clant-文章分类-Hibernate</title><link>http://www.blogjava.net/clant/category/10316.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 05:53:48 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 05:53:48 GMT</pubDate><ttl>60</ttl><item><title>Weblogic 8.1与Hibernate的结合的解决方案</title><link>http://www.blogjava.net/clant/articles/42194.html</link><dc:creator>BPM </dc:creator><author>BPM </author><pubDate>Thu, 20 Apr 2006 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/clant/articles/42194.html</guid><wfw:comment>http://www.blogjava.net/clant/comments/42194.html</wfw:comment><comments>http://www.blogjava.net/clant/articles/42194.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/clant/comments/commentRss/42194.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/clant/services/trackbacks/42194.html</trackback:ping><description><![CDATA[
		<p>Weblogic 8.1与Hibernate的结合的解决方案   - 2004-10-02  08:17 <br /><br />    基于Hibernate在O/R Mapping方面的优势，目前项目中采用Hibernate实体替代EJB EntityBean, 本人在WebLogic 8.1的环境下做了一个测试，用EJB SessionBean调用Hibernate的数据实体。因为Weblogic和Hibernate都提供了数据库连接池,JNDI,事务等功能。主导思想还是想利用Weblogic Server的在这些服务上的高性能管理。</p>
		<p>设计思想：<br />    使用WebLogic的数据库连接池，而不是Hibernate自带的连接池。<br />    将Hibernate的SessionFactory配置到Weblogic JNDI目录树下。<br />    在SessionBean中直接调用Hibernate的实体访问数据库</p>
		<p>准备条件：<br />1、安装以下软件(都可以免费下载使用)<br />1.1 Mysql 4.0.21 c:\mysql<br />    创建数据库study,创建数据表cat<br />1.2 mysql-connector-java-3.0.15-ga.zip mysql驱动程序<br />1.3 Weblogic platform 8.1    c:\bea<br />    Weblogic配置完成，域mydomain和服务器myserver，数据池studyjndi,数据源名称mysqldatasource <br />1.4 Hibernate 2.1.2 <br />    参考其它文档编写一个hibernate的实例cat,编写Cat.hbm.xml和hibernate.cfg.xml文件，了解hibernate的基本配置。<br />    注意数据库的差异。</p>
		<p>2.创建目录结构<br />C:\Test\lib 将hibernate解压后lib目录下的全部文件拷贝到此<br />C:\Test\src\com\chenm 源代码存放地(*.java) <br />C:\Test\classes 将hibernate的配置文件(hibernate.properties,log4j.properties,cache.ccf) <br />C:\Test\classes\com\chenm 编译好的代码(*.class) + Cat.hbm.xml + hibernate.cfg.xml</p>
		<p>步骤1:配置hibernate的环境目录到Weblogic的CLASSPATH中。<br />    修改Weblogic启动脚本C:\bea\user_projects\domains\mydomain\startweblogic.cmd，在@REM Call WebLogic Server前加入<br />    @rem set hibernate classpath<br />    set HIBERNATE_LIB=C:\Test\lib<br />    set HIBERNATE_CLASSES=C:\Test\classes<br />    SET CLASSPATH=%HIBERNATE_LIB%\cglib-2.0-rc2.jar;%HIBERNATE_LIB%\commons-collections-2.1.jar;%HIBERNATE_LIB%\commons-lang-1.0.1.jar;%HIBERNATE_LIB%\commons-logging-1.0.3.jar;%HIBERNATE_LIB%\dom4j-1.4.jar;%HIBERNATE_LIB%\hibernate2.jar;%HIBERNATE_LIB%\jcs-1.0-dev.jar;%HIBERNATE_LIB%\log4j-1.2.8.jar;%HIBERNATE_LIB%\odmg-3.0.jar;%HIBERNATE_CLASSES%;%CLASSPATH%</p>
		<p>步骤2:修改hibernat.properties文件<br />2.1 修改以下内容<br />    注释掉mysql缺省数据库连接<br />    ## HypersonicSQL</p>
		<p>    #hibernate.dialect net.sf.hibernate.dialect.HSQLDialect<br />    #hibernate.connection.driver_class org.hsqldb.jdbcDriver<br />    #hibernate.connection.username sa<br />    #hibernate.connection.password<br />    #hibernate.connection.url jdbc:hsqldb:hsql://localhost<br />    #hibernate.connection.url jdbc:hsqldb:test<br />    #hibernate.connection.url jdbc:hsqldb:.<br />    <br />    使用mysql数据库<br />    ## MySQL</p>
		<p>    hibernate.dialect net.sf.hibernate.dialect.MySQLDialect<br />    #hibernate.connection.driver_class org.gjt.mm.mysql.Driver<br />    hibernate.connection.driver_class com.mysql.jdbc.Driver<br />    hibernate.connection.url jdbc:mysql://localhost:3306/study<br />    hibernate.connection.username test<br />    hibernate.connection.password weblogic<br />    <br />    调整数据库查询和插入的性能参数<br />    修改hibernate.jdbc.fetch_size 50<br />    修改hibernate.jdbc.batch_size 25<br />    <br />    调整Transaction API<br />    #hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory<br />    #hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory<br />    为<br />    hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory<br />    hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory</p>
		<p>    使用JCS缓存<br />    hibernate.transaction.manager_lookup_class net.sf.hibernate.transaction.WeblogicTransactionManagerLookup</p>
		<p>2.2 在文件尾增加以下内容<br />    hibernate.dialect net.sf.hibernate.dialect.MySQLDialect<br />    hibernate.connection.datasource studyjndi // 此处为weblogic的数据连接池JNDI名称<br />    hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider<br />    hibernate.session_factory_name hibernate.session_factory // 绑定到weblogic JNDI目录树中的名称</p>
		<p>步骤3. 实现SessionFactory的预创建，使用Weblogic的T3StartUpDef接口创建一个StartUp类，配置成Weblogic<br />启动时自动运行。<br />3.1 创建文件HibernateStartUp.java,并编译成C:\Test\classes\com\chenm\HibernateStartUp.class文件，<br />package com.chenm;</p>
		<p>import java.util.Hashtable;<br />import weblogic.common.T3StartupDef;<br />import weblogic.common.T3ServicesDef;<br />import net.sf.hibernate.cfg.Configuration;<br />import net.sf.hibernate.SessionFactory;</p>
		<p>public class HibernateStartUp implements T3StartupDef {<br />        public void setServices(T3ServicesDef services) {}</p>
		<p>        public String startup(String name,Hashtable args) throws Exception {<br />                Configuration conf = new Configuration().addClass(Cat.class);<br />                SessionFactory sf = conf.buildSessionFactory();<br />                return "Hibernate Startup completed successfully";<br />        }<br />}</p>
		<p>3.2 配置StartUp类<br />    启动Weblogic控制台，打开左边mydomain\部署\启动和关闭节点,选择右边"配置新的 Startup Class..."<br />    填写名称HibernateStartup, 类名com.chenm.HibernateStartUp,然后点击"创建", 如果没有出错信息就算成功。<br />    <br />    确认成功：关闭Weblogic并重启，观察DOS窗口的信息，可以看到在Weblogic启动后显示很多行INFO，如果没有<br />    错误，证明配置成功。再打开weblogic控制台,选择mydomain\服务器\myserver,点右键，选择察看JNDI树，如果<br />    看到Hibernate的JNDI对象，在右边可以看见以下信息：</p>
		<p>    绑定名称: session_factory <br />    对象类: net.sf.hibernate.impl.SessionFactoryImpl <br />    对象散列代码: 45706641 <br />    对象转换成字符串: <a href="mailto:net.sf.hibernate.impl.SessionFactoryImpl@2b96d91">net.sf.hibernate.impl.SessionFactoryImpl@2b96d91</a></p>
		<p>    Config OK!</p>
		<p>4. 编写SessionBean操作Hibernate实体<br />   在SessionBean中定义Remote方法<br />     public void InsertCat(String cat_id,String name, char sex, float weight) {<br />    <a>/**@todo</a> Complete this method*/<br />    try {</p>
		<p>Context ctx = getInitialContext();<br />SessionFactory sf = (SessionFactory)ctx.lookup("hibernate/session_factory");<br />Session s = sf.openSession() ;<br />Transaction t = s.beginTransaction() ;</p>
		<p>Cat myCat = new Cat();<br />myCat.setId(cat_id);<br />myCat.setName(name);<br />myCat.setSex(sex);<br />myCat.setWeight(weight);s.save(myCat);<br />s.save(myCat);<br />t.commit() ;<br />s.close();<br />　　}<br />　　catch( Exception ex ) {<br />　　}</p>
		<p>  }<br />  private Context getInitialContext() throws Exception {<br />    String url = "t3://chenming:7001"; // chenming服务器名称<br />    String user = null;<br />    String password = null;<br />    Properties properties = null;<br />    try {<br />      properties = new Properties();<br />      properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");<br />      properties.put(Context.PROVIDER_URL, url);<br />      if (user != null) {<br />        properties.put(Context.SECURITY_PRINCIPAL, user);<br />        properties.put(Context.SECURITY_CREDENTIALS, password == null ? "" : password);<br />      }<br />      return new InitialContext(properties);<br />    }<br />    catch(Exception e) {<br />      throw e;<br />    }<br />  }<br />  编写测试并运行，在cat表中插入一条纪录<br />  Context context = getInitialContext();</p>
		<p>  //look up jndi name<br />  Object ref = context.lookup("CatSession");<br />  //look up jndi name and cast to Home interface<br />  catSessionHome = (CatSessionHome) PortableRemoteObject.narrow(ref, CatSessionHome.class);<br />  catSession = catSessionHome.create();<br />  catSession.InsertCat("007","Chenm.cat",'1',100);</p>
<img src ="http://www.blogjava.net/clant/aggbug/42194.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/clant/" target="_blank">BPM </a> 2006-04-20 17:00 <a href="http://www.blogjava.net/clant/articles/42194.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的缓存机制介绍</title><link>http://www.blogjava.net/clant/articles/42187.html</link><dc:creator>BPM </dc:creator><author>BPM </author><pubDate>Thu, 20 Apr 2006 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/clant/articles/42187.html</guid><wfw:comment>http://www.blogjava.net/clant/comments/42187.html</wfw:comment><comments>http://www.blogjava.net/clant/articles/42187.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/clant/comments/commentRss/42187.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/clant/services/trackbacks/42187.html</trackback:ping><description><![CDATA[
		<p>　   缓存是介于应用程序和物理数据源之间，其作用是为了降低应用程序对物理数据源访问的频次，从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制，应用程序在运行时从缓存读写数据，在特定的时刻或事件会同步缓存和物理数据源的数据。</p>
		<p> 　　缓存的介质一般是内存，所以读写速度很快。但如果缓存中存放的数据量非常大时，也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质，还要考虑到管理缓存的并发访问和缓存数据的生命周期。</p>
		<p>　　Hibernate的缓存包括Session的缓存和SessionFactory的缓存，其中SessionFactory的缓存又可以分为两类：内置缓存和外置缓存。Session的缓存是内置的，不能被卸载，也被称为Hibernate的第一级缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似，前者是SessionFactory对象的一些集合属性包含的数据，后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句，映射元数据是映射文件中数据的拷贝，而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来，SessionFactory的内置缓存是只读的，应用程序不能修改缓存中的映射元数据和预定义SQL语句，因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下，SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝，外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。</p>
		<p>　　Hibernate的这两级缓存都位于持久化层，存放的都是数据库数据的拷贝，那么它们之间的区别是什么呢？为了理解二者的区别，需要深入理解持久化层的缓存的两个特性：缓存的范围和缓存的并发访问策略。</p>
		<p>　　持久化层的缓存的范围</p>
		<p>　　缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。</p>
		<p>　　1 事务范围：缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期，当事务结束时，缓存也就结束生命周期。在此范围下，缓存的介质是内存。事务可以是数据库事务或者应用事务，每个事务都有独自的缓存，缓存内的数据通常采用相互关联的的对象形式。</p>
		<p>　　2 进程范围：缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存，因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期，进程结束时，缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据，所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据，但是对象分解为松散的算法比对象序列化的算法要求更快。</p>
		<p>　　3 集群范围：在集群环境中，缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点，进程间通过远程通信来保证缓存中的数据的一致性，缓存中的数据通常采用对象的松散数据形式。</p>
		<p>　　对大多数应用来说，应该慎重地考虑是否需要使用集群范围的缓存，因为访问的速度不一定会比直接访问数据库数据的速度快多少。</p>
		<p>　　持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据，还可以到进程范围或集群范围的缓存内查询，如果还是没有查到，那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存，通常它是必需的；进程范围或集群范围的缓存是持久化层的第二级缓存，通常是可选的。</p>
		<p>　　持久化层的缓存的并发访问策略</p>
		<p>　　当多个并发的事务同时访问持久化层的缓存的相同数据时，会引起并发问题，必须采用必要的事务隔离措施。</p>
		<p>　　在进程范围或集群范围的缓存，即第二级缓存，会出现并发问题。因此可以设定以下四种类型的并发访问策略，每一种策略对应一种事务隔离级别。</p>
		<p>　　事务型：仅仅在受管理环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据，可以采用这种隔离类型，因为它可以防止脏读和不可重复读这类的并发问题。</p>
		<p>　　读写型：提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据，可以采用这种隔离类型，因为它可以防止脏读这类的并发问题。</p>
		<p>　　非严格读写型：不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能，必须为该数据配置一个很短的数据过期时间，从而尽量避免脏读。对于极少被修改，并且允许偶尔脏读的数据，可以采用这种并发访问策略。 　　只读型：对于从来不会修改的数据，如参考数据，可以使用这种并发访问策略。</p>
		<p>　　事务型并发访问策略是事务隔离级别最高，只读型的隔离级别最低。事务隔离级别越高，并发性能就越低。</p>
		<p>　　什么样的数据适合存放到第二级缓存中？</p>
		<p>　　1、很少被修改的数据 </p>
		<p>　　2、不是很重要的数据，允许出现偶尔并发的数据</p>
		<p>　　3、不会被并发访问的数据</p>
		<p>　　4、参考数据</p>
		<p>　　不适合存放到第二级缓存的数据？</p>
		<p>　　1、经常被修改的数据</p>
		<p>　　2、财务数据，绝对不允许出现并发</p>
		<p>　　3、与其他应用共享的数据。</p>
		<p>　　Hibernate的二级缓存</p>
		<p>　　如前所述，Hibernate提供了两级缓存，第一级是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务，因此它的缓存是事务范围的缓存。第一级缓存是必需的，不允许而且事实上也无法比卸除。在第一级缓存中，持久化类的每个实例都具有唯一的OID。</p>
		<p>　　第二级缓存是一个可插拔的的缓存插件，它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应，因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题，因此需要采用适当的并发访问策略，该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的，可以在每个类或每个集合的粒度上配置第二级缓存。</p>
		<p>　　Hibernate的二级缓存策略的一般过程如下：</p>
		<p>　　1) 条件查询的时候，总是发出一条select * from table_name where …. （选择所有字段）这样的SQL语句查询数据库，一次获得所有的数据对象。 </p>
		<p>　　2) 把获得的所有数据对象根据ID放入到第二级缓存中。 </p>
		<p>　　3) 当Hibernate根据ID访问数据对象的时候，首先从Session一级缓存中查；查不到，如果配置了二级缓存，那么从二级缓存中查；查不到，再查询数据库，把结果按照ID放入到缓存。 </p>
		<p>　　4) 删除、更新、增加数据的时候，同时更新缓存。</p>
		<p>　　Hibernate的二级缓存策略，是针对于ID查询的缓存策略，对于条件查询则毫无作用。为此，Hibernate提供了针对条件查询的Query缓存。</p>
		<p>　　Hibernate的Query缓存策略的过程如下： </p>
		<p>　　1) Hibernate首先根据这些信息组成一个Query Key，Query Key包括条件查询的请求一般信息：SQL, SQL需要的参数，记录范围（起始位置rowStart，最大记录个数maxRows)，等。 </p>
		<p>　　2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在，那么返回这个结果列表；如果不存在，查询数据库，获取结果列表，把整个结果列表根据Query Key放入到Query缓存中。 </p>
		<p>　　3) Query Key中的SQL涉及到一些表名，如果这些表的任何数据发生修改、删除、增加等操作，这些相关的Query Key都要从缓存中清空。</p>
<img src ="http://www.blogjava.net/clant/aggbug/42187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/clant/" target="_blank">BPM </a> 2006-04-20 16:28 <a href="http://www.blogjava.net/clant/articles/42187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>