﻿<?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-空间站-文章分类-Hibernate</title><link>http://www.blogjava.net/i369/category/18312.html</link><description>北极心空</description><language>zh-cn</language><lastBuildDate>Tue, 22 Apr 2008 17:06:24 GMT</lastBuildDate><pubDate>Tue, 22 Apr 2008 17:06:24 GMT</pubDate><ttl>60</ttl><item><title>Hibernate 参数设置一览表</title><link>http://www.blogjava.net/i369/articles/194855.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Tue, 22 Apr 2008 10:28:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/194855.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/194855.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/194855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/194855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/194855.html</trackback:ping><description><![CDATA[<table summary="                Hibernate配置属性&#13;&#10;    " border="1">
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.dialect</font></tt></td>
            <td>一个Hibernate <tt class="literal"><font face="新宋体">Dialect</font></tt>类名允许Hibernate针对特定的关系数据库生成优化的SQL. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">full.classname.of.Dialect</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.show_sql</font></tt></td>
            <td>输出所有SQL语句到控制台. 有一个另外的选择是把<tt class="literal"><font face="新宋体">org.hibernate.SQL</font></tt>这个log category设为<tt class="literal"><font face="新宋体">debug</font></tt>。 <span class="strong">eg.</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.format_sql</font></tt></td>
            <td>在log和console中打印出更漂亮的SQL。 <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_schema</font></tt></td>
            <td>在生成的SQL中, 将给定的schema/tablespace附加于非全限定名的表名上. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">SCHEMA_NAME</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_catalog</font></tt></td>
            <td>在生成的SQL中, 将给定的catalog附加于非全限定名的表名上. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">CATALOG_NAME</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.session_factory_name</font></tt></td>
            <td><tt class="literal"><font face="新宋体">SessionFactory</font></tt>创建后，将自动使用这个名字绑定到JNDI中. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">jndi/composite/name</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.max_fetch_depth</font></tt></td>
            <td>为单向关联(一对一, 多对一)的外连接抓取（outer join fetch）树设置最大深度. 值为<tt class="literal"><font face="新宋体">0</font></tt>意味着将关闭默认的外连接抓取. <span class="strong">取值</span> 建议在<tt class="literal"><font face="新宋体">0</font></tt>到<tt class="literal"><font face="新宋体">3</font></tt>之间取值 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_batch_fetch_size</font></tt></td>
            <td>为Hibernate关联的批量抓取设置默认数量. <span class="strong">取值</span> 建议的取值为<tt class="literal"><font face="新宋体">4</font></tt>, <tt class="literal"><font face="新宋体">8</font></tt>, 和<tt class="literal"><font face="新宋体">16</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_entity_mode</font></tt></td>
            <td>为由这个<tt class="literal"><font face="新宋体">SessionFactory</font></tt>打开的所有Session指定默认的实体表现模式. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">dynamic-map</font></tt>, <tt class="literal"><font face="新宋体">dom4j</font></tt>, <tt class="literal"><font face="新宋体">pojo</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.order_updates</font></tt></td>
            <td>强制Hibernate按照被更新数据的主键，为SQL更新排序。这么做将减少在高并发系统中事务的死锁。 <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.generate_statistics</font></tt></td>
            <td>如果开启, Hibernate将收集有助于性能调节的统计数据. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.use_identifer_rollback</font></tt></td>
            <td>如果开启, 在对象被删除时生成的标识属性将被重设为默认值. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.use_sql_comments</font></tt></td>
            <td>如果开启, Hibernate将在SQL中生成有助于调试的注释信息, 默认值为<tt class="literal"><font face="新宋体">false</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
    </tbody>
</table>
<div class="table"><a name="configuration-jdbc-properties"></a>
<p class="title"><strong>表&nbsp;3.4.&nbsp; Hibernate JDBC和连接(connection)属性 </strong></p>
<table summary="                Hibernate JDBC和连接(connection)属性&#13;&#10;    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.fetch_size</font></tt></td>
            <td>非零值，指定JDBC抓取数量的大小 (调用<tt class="literal"><font face="新宋体">Statement.setFetchSize()</font></tt>). </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.batch_size</font></tt></td>
            <td>非零值，允许Hibernate使用JDBC2的批量更新. <span class="strong">取值</span> 建议取<tt class="literal"><font face="新宋体">5</font></tt>到<tt class="literal"><font face="新宋体">30</font></tt>之间的值 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.batch_versioned_data</font></tt></td>
            <td>如果你想让你的JDBC驱动从<tt class="literal"><font face="新宋体">executeBatch()</font></tt>返回正确的行计数 , 那么将此属性设为<tt class="literal"><font face="新宋体">true</font></tt>(开启这个选项通常是安全的). 同时，Hibernate将为自动版本化的数据使用批量DML. 默认值为<tt class="literal"><font face="新宋体">false</font></tt>. <span class="strong">eg.</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.factory_class</font></tt></td>
            <td>选择一个自定义的<tt class="literal"><font face="新宋体">Batcher</font></tt>. 多数应用程序不需要这个配置属性. <span class="strong">eg.</span> <tt class="literal"><font face="新宋体">classname.of.Batcher</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.use_scrollable_resultset</font></tt></td>
            <td>允许Hibernate使用JDBC2的可滚动结果集. 只有在使用用户提供的JDBC连接时，这个选项才是必要的, 否则Hibernate会使用连接的元数据. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.use_streams_for_binary</font></tt></td>
            <td>在JDBC读写<tt class="literal"><font face="新宋体">binary (二进制)</font></tt>或<tt class="literal"><font face="新宋体">serializable (可序列化)</font></tt> 的类型时使用流(stream)(系统级属性). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.use_get_generated_keys</font></tt></td>
            <td>在数据插入数据库之后，允许使用JDBC3 <tt class="literal"><font face="新宋体">PreparedStatement.getGeneratedKeys()</font></tt> 来获取数据库生成的key(键)。需要JDBC3+驱动和JRE1.4+, 如果你的数据库驱动在使用Hibernate的标 识生成器时遇到问题，请将此值设为false. 默认情况下将使用连接的元数据来判定驱动的能力. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.provider_class</font></tt></td>
            <td>自定义<tt class="literal"><font face="新宋体">ConnectionProvider</font></tt>的类名, 此类用来向Hibernate提供JDBC连接. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.ConnectionProvider</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.isolation</font></tt></td>
            <td>设置JDBC事务隔离级别. 查看<tt class="literal"><font face="新宋体">java.sql.Connection</font></tt>来了解各个值的具体意义, 但请注意多数数据库都不支持所有的隔离级别. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">1, 2, 4, 8</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.autocommit</font></tt></td>
            <td>允许被缓存的JDBC连接开启自动提交(autocommit) (不建议). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.release_mode</font></tt></td>
            <td>指定Hibernate在何时释放JDBC连接. 默认情况下,直到Session被显式关闭或被断开连接时,才会释放JDBC连接. 对于应用程序服务器的JTA数据源, 你应当使用<tt class="literal"><font face="新宋体">after_statement</font></tt>, 这样在每次JDBC调用后，都会主动的释放连接. 对于非JTA的连接, 使用<tt class="literal"><font face="新宋体">after_transaction</font></tt>在每个事务结束时释放连接是合理的. <tt class="literal"><font face="新宋体">auto</font></tt>将为JTA和CMT事务策略选择<tt class="literal"><font face="新宋体">after_statement</font></tt>, 为JDBC事务策略选择<tt class="literal"><font face="新宋体">after_transaction</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">on_close</font></tt> | <tt class="literal"><font face="新宋体">after_transaction</font></tt> | <tt class="literal"><font face="新宋体">after_statement</font></tt> | <tt class="literal"><font face="新宋体">auto</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.<span class="emphasis"><em>&lt;propertyName&gt;</em></span></font></tt></td>
            <td>将JDBC属性<tt class="literal"><font face="新宋体">propertyName</font></tt>传递到<tt class="literal"><font face="新宋体">DriverManager.getConnection()</font></tt>中去. </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jndi.<span class="emphasis"><em>&lt;propertyName&gt;</em></span></font></tt></td>
            <td>将属性<tt class="literal"><font face="新宋体">propertyName</font></tt>传递到JNDI <tt class="literal"><font face="新宋体">InitialContextFactory</font></tt>中去. </td>
        </tr>
    </tbody>
</table>
</div>
<div class="table"><a name="configuration-cache-properties"></a>
<p class="title"><strong>表&nbsp;3.5.&nbsp; Hibernate缓存属性 </strong></p>
<table summary="                Hibernate缓存属性&#13;&#10;    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.provider_class</font></tt></td>
            <td>自定义的<tt class="literal"><font face="新宋体">CacheProvider</font></tt>的类名. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.CacheProvider</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_minimal_puts</font></tt></td>
            <td>以频繁的读操作为代价, 优化二级缓存来最小化写操作. 在Hibernate3中，这个设置对的集群缓存非常有用, 对集群缓存的实现而言，默认是开启的. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_query_cache</font></tt></td>
            <td>允许查询缓存, 个别查询仍然需要被设置为可缓存的. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_second_level_cache</font></tt></td>
            <td>能用来完全禁止使用二级缓存. 对那些在类的映射定义中指定<tt class="literal"><font face="新宋体">&lt;cache&gt;</font></tt>的类，会默认开启二级缓存. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.query_cache_factory</font></tt></td>
            <td>自定义实现<tt class="literal"><font face="新宋体">QueryCache</font></tt>接口的类名, 默认为内建的<tt class="literal"><font face="新宋体">StandardQueryCache</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.QueryCache</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.region_prefix</font></tt></td>
            <td>二级缓存区域名的前缀. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">prefix</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_structured_entries</font></tt></td>
            <td>强制Hibernate以更人性化的格式将数据存入二级缓存. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
    </tbody>
</table>
</div>
<div class="table"><a name="configuration-transaction-properties"></a>
<p class="title"><strong>表&nbsp;3.6.&nbsp; Hibernate事务属性 </strong></p>
<table summary="                Hibernate事务属性&#13;&#10;    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.factory_class</font></tt></td>
            <td>一个<tt class="literal"><font face="新宋体">TransactionFactory</font></tt>的类名, 用于Hibernate <tt class="literal"><font face="新宋体">Transaction</font></tt> API (默认为<tt class="literal"><font face="新宋体">JDBCTransactionFactory</font></tt>). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.TransactionFactory</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">jta.UserTransaction</font></tt></td>
            <td>一个JNDI名字，被<tt class="literal"><font face="新宋体">JTATransactionFactory</font></tt>用来从应用服务器获取JTA <tt class="literal"><font face="新宋体">UserTransaction</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">jndi/composite/name</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.manager_lookup_class</font></tt></td>
            <td>一个<tt class="literal"><font face="新宋体">TransactionManagerLookup</font></tt>的类名 - 当使用JVM级缓存，或在JTA环境中使用hilo生成器的时候需要该类. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.TransactionManagerLookup</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.flush_before_completion</font></tt></td>
            <td>如果开启, session在事务完成后将被自动清洗(flush)。 现在更好的方法是使用自动session上下文管理。<span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.auto_close_session</font></tt></td>
            <td>如果开启, session在事务完成后将被自动关闭。 现在更好的方法是使用自动session上下文管理。<span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
    </tbody>
</table>
</div>
<div class="table"><a name="configuration-misc-properties"></a>
<p class="title"><strong>表&nbsp;3.7.&nbsp; 其他属性 </strong></p>
<table summary="                其他属性&#13;&#10;    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.current_session_context_class</font></tt></td>
            <td>为"当前" <tt class="literal"><font face="新宋体">Session</font></tt>指定一个(自定义的)策略。<span class="strong">eg.</span> <tt class="literal"><font face="新宋体">jta</font></tt> | <tt class="literal"><font face="新宋体">thread</font></tt> | <tt class="literal"><font face="新宋体">custom.Class</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.query.factory_class</font></tt></td>
            <td>选择HQL解析器的实现. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">org.hibernate.hql.ast.ASTQueryTranslatorFactory</font></tt> or <tt class="literal"><font face="新宋体">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.query.substitutions</font></tt></td>
            <td>将Hibernate查询中的符号映射到SQL查询中的符号 (符号可能是函数名或常量名字). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.hbm2ddl.auto</font></tt></td>
            <td>在<tt class="literal"><font face="新宋体">SessionFactory</font></tt>创建时，自动检查数据库结构，或者将数据库schema的DDL导出到数据库. 使用 <tt class="literal"><font face="新宋体">create-drop</font></tt>时,在显式关闭<tt class="literal"><font face="新宋体">SessionFactory</font></tt>时，将drop掉数据库schema. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">validate</font></tt> | <tt class="literal"><font face="新宋体">update</font></tt> | <tt class="literal"><font face="新宋体">create</font></tt> | <tt class="literal"><font face="新宋体">create-drop</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cglib.use_reflection_optimizer</font></tt></td>
            <td>开启CGLIB来替代运行时反射机制(系统级属性). 反射机制有时在除错时比较有用. 注意即使关闭这个优化, Hibernate还是需要CGLIB. 你不能在<tt class="literal"><font face="新宋体">hibernate.cfg.xml</font></tt>中设置此属性. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
    </tbody>
</table>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="configuration-optional-dialects"></a>3.4.1.&nbsp; SQL方言 </h3>
</div>
</div>
</div>
<p>你应当总是为你的数据库将<tt class="literal"><font face="新宋体">hibernate.dialect</font></tt>属性设置成正确的 <tt class="literal"><font face="新宋体">org.hibernate.dialect.Dialect</font></tt>子类. 如果你指定一种方言, Hibernate将为上面列出的一些属性使用合理的默认值, 为你省去了手工指定它们的功夫. </p>
<div class="table"><a name="sql-dialects"></a>
<p class="title"><strong>表&nbsp;3.8.&nbsp; Hibernate SQL方言 (<tt class="literal"><font face="新宋体">hibernate.dialect</font></tt>) </strong></p>
<table summary="                    Hibernate SQL方言 (hibernate.dialect)&#13;&#10;    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>RDBMS</th>
            <th>方言 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>DB2</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.DB2Dialect</font></tt></td>
        </tr>
        <tr>
            <td>DB2 AS/400</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.DB2400Dialect</font></tt></td>
        </tr>
        <tr>
            <td>DB2 OS390</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.DB2390Dialect</font></tt></td>
        </tr>
        <tr>
            <td>PostgreSQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.PostgreSQLDialect</font></tt></td>
        </tr>
        <tr>
            <td>MySQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MySQLDialect</font></tt></td>
        </tr>
        <tr>
            <td>MySQL with InnoDB</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MySQLInnoDBDialect</font></tt></td>
        </tr>
        <tr>
            <td>MySQL with MyISAM</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MySQLMyISAMDialect</font></tt></td>
        </tr>
        <tr>
            <td>Oracle (any version)</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.OracleDialect</font></tt></td>
        </tr>
        <tr>
            <td>Oracle 9i/10g</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.Oracle9Dialect</font></tt></td>
        </tr>
        <tr>
            <td>Sybase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SybaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>Sybase Anywhere</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SybaseAnywhereDialect</font></tt></td>
        </tr>
        <tr>
            <td>Microsoft SQL Server</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SQLServerDialect</font></tt></td>
        </tr>
        <tr>
            <td>SAP DB</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SAPDBDialect</font></tt></td>
        </tr>
        <tr>
            <td>Informix</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.InformixDialect</font></tt></td>
        </tr>
        <tr>
            <td>HypersonicSQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.HSQLDialect</font></tt></td>
        </tr>
        <tr>
            <td>Ingres</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.IngresDialect</font></tt></td>
        </tr>
        <tr>
            <td>Progress</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.ProgressDialect</font></tt></td>
        </tr>
        <tr>
            <td>Mckoi SQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MckoiDialect</font></tt></td>
        </tr>
        <tr>
            <td>Interbase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.InterbaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>Pointbase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.PointbaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>FrontBase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.FrontbaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>Firebird</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.FirebirdDialect</font></tt></td>
        </tr>
    </tbody>
</table>
</div>
</div>
<div>
<p class="title"><strong>表&nbsp;3.9.&nbsp; Hibernate日志类别 </strong></p>
<table summary="                    Hibernate日志类别&#13;&#10;    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>类别 </th>
            <th>功能 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.SQL</font></tt></td>
            <td>在所有SQL DML语句被执行时为它们记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.type</font></tt></td>
            <td>为所有JDBC参数记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.tool.hbm2ddl</font></tt></td>
            <td>在所有SQL DDL语句执行时为它们记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.pretty</font></tt></td>
            <td>在session清洗(flush)时，为所有与其关联的实体(最多20个)的状态记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.cache</font></tt></td>
            <td>为所有二级缓存的活动记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction</font></tt></td>
            <td>为事务相关的活动记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.jdbc</font></tt></td>
            <td>为所有JDBC资源的获取记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.hql.AST</font></tt></td>
            <td>在解析查询的时候,记录HQL和SQL的AST分析日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.secure</font></tt></td>
            <td>为JAAS认证请求做日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate</font></tt></td>
            <td>为任何Hibernate相关信息做日志 (信息量较大, 但对查错非常有帮助) </td>
        </tr>
    </tbody>
</table>
</div>
<p class="title"><strong>表&nbsp;3.10.&nbsp;JTA TransactionManagers</strong></p>
<table summary="JTA TransactionManagers" border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>Transaction工厂类 </th>
            <th align="center">应用程序服务器 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JBossTransactionManagerLookup</font></tt></td>
            <td align="center">JBoss</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.WeblogicTransactionManagerLookup</font></tt></td>
            <td align="center">Weblogic</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.WebSphereTransactionManagerLookup</font></tt></td>
            <td align="center">WebSphere</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</font></tt></td>
            <td align="center">WebSphere 6</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.OrionTransactionManagerLookup</font></tt></td>
            <td align="center">Orion</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.ResinTransactionManagerLookup</font></tt></td>
            <td align="center">Resin</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JOTMTransactionManagerLookup</font></tt></td>
            <td align="center">JOTM</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JOnASTransactionManagerLookup</font></tt></td>
            <td align="center">JOnAS</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JRun4TransactionManagerLookup</font></tt></td>
            <td align="center">JRun4</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.BESTransactionManagerLookup</font></tt></td>
            <td align="center">Borland ES</td>
        </tr>
    </tbody>
</table>
<br />
<img src ="http://www.blogjava.net/i369/aggbug/194855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2008-04-22 18:28 <a href="http://www.blogjava.net/i369/articles/194855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate性能优化</title><link>http://www.blogjava.net/i369/articles/194579.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 21 Apr 2008 10:22:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/194579.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/194579.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/194579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/194579.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/194579.html</trackback:ping><description><![CDATA[有很多人认为Hibernate天生效率比较低，确实，在普遍情况下，需要将执行转换为SQL语句的Hibernate的效率低于直接JDBC存取，然而，在经过比较好的性能优化之后，Hibernate的性能还是让人相当满意的，特别是应用二级缓存之后，甚至可以获得比较不使用缓存的JDBC更好的性能，下面介绍一些通常的Hibernate的优化策略：<br />
&nbsp;&nbsp;&nbsp;&nbsp;1.抓取优化<br />
&nbsp;&nbsp;&nbsp;&nbsp;抓取是指Hibernate如何在关联关系之间进行导航的时候，Hibernate如何获取关联对象的策略，其主要定义了两个方面：如何抓取和何时抓取<br />
&nbsp;&nbsp;&nbsp;&nbsp;1）如何抓取。<br />
&nbsp;&nbsp;&nbsp;&nbsp;Hibernate3主要有两种种抓取方式，分别应用于对象关联实例(many-to-one、one-to-one)和对象关联集合(set、map等)，总共是四种变种<br />
&nbsp;&nbsp;&nbsp;&nbsp;JOIN抓取：&nbsp;通过在SELECT语句中使用OUTER&nbsp;JOIN来获得对象的关联实例或者关联集合）<br />
&nbsp;&nbsp;&nbsp;&nbsp;SELECT抓取：&nbsp;另外发送一条SELECT语句来抓取当前对象的关联实体和集合<br />
&nbsp;&nbsp;&nbsp;&nbsp;在我的开发经历中，此处对性能的优化是比较有限的，并不值得过多关注<br />
&nbsp;&nbsp;&nbsp;&nbsp;例：<br />
&nbsp;&nbsp;&nbsp;&nbsp;A.应用于对象关联实例（默认是false）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;many-to-one&nbsp;name=".."&nbsp;outer-join="true/false/auto"&nbsp;&nbsp;.../&gt;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;B.应用于对象关联集合（默认是auto）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;set&nbsp;name=".."&nbsp;fetch="join/select"&nbsp;...&nbsp;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;2）何时抓取<br />
&nbsp;&nbsp;&nbsp;&nbsp;主要分为延迟加载和立即抓取，默认的情况下Hibernate3对对象关联实采用延迟加载，普通属性采用立即抓取，通过延迟加载和采用适当的抓取粒度，与不采用优化相比往往可以将性能提升数倍<br />
&nbsp;&nbsp;&nbsp;&nbsp;立即抓取：当抓取宿主对象时，同时抓取其关联对象和关联集以及属性<br />
&nbsp;&nbsp;&nbsp;&nbsp;延迟加载：当抓取宿主对象时，并不抓取其关联对象，而是当对其对象进行调用时才加载<br />
&nbsp;&nbsp;&nbsp;&nbsp;例：<br />
&nbsp;&nbsp;&nbsp;&nbsp;A.应用于对象关联实例（默认是延迟加载）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;many-to-one&nbsp;name=".."&nbsp;&nbsp;lazy="true/false"&nbsp;.../&gt;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;B.应用于对象关联集合（默认是延迟加载）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;set&nbsp;name=".."&nbsp;lazy="true/false"&nbsp;...&nbsp;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;对于延迟加载，需要注意的时，对延迟对象的使用必须在Session关闭之前进行，Hibernate的LazyInitalizationException往往就是由于在Session的生命期外使用了延迟加载的对象。当我们进行Web开发时，可以使用OpenSessionInView模式，当请求开始时打开session，当请求响应结束时才关闭session，不过，在使用OpenSessionInView模式时，需要注意如果响应时间比较长（业务比较复杂或者客户端是低速网络），将Session资源(也就是数据库的连接)占用太久的话可以会导致资源耗尽<br />
&nbsp;&nbsp;&nbsp;&nbsp;3）抓取粒度<br />
&nbsp;&nbsp;&nbsp;&nbsp;抓取粒度指的是对象在关联关系之间被导航时一次预先加载的数量，Hibernate程序的性能比较差往往就在于没有对抓取粒度仔细考虑，当加载一个列表并在列表中的每个对象中对其关联进行导航时，往往导致N+1条SQL语句查询。<br />
&nbsp;&nbsp;&nbsp;&nbsp;例：<br />
&nbsp;&nbsp;&nbsp;&nbsp;A.应用于对象关联实例（默认为1），注意，对对象关<span class="noted" id="note_879">联实例的设</span>置是在被关联的对象之上的，譬如<br />
&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;User<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Group&nbsp;g;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;那么抓取粒度应该在Group的配置文件之上，见下<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&nbsp;name="Group"&nbsp;table="group"&nbsp;batch-size=".."&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;对该值并没有一个约定俗成的值，根据情况而定，如果被关联表数据比较少，则可以设置地小一些，3-20，如果比较大则可以设到30-50，注意的时候，并不是越多越好，当其值超过50之后，对性能并没有多大改善但却无谓地消耗内存<br />
&nbsp;&nbsp;&nbsp;&nbsp;假设有如下例子：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;User&gt;&nbsp;users&nbsp;=&nbsp;query.list();<br />
&nbsp;&nbsp;&nbsp;&nbsp;如果有20个User，并对这20个User及其Group进行遍历，如果不设置batch-size（即batch-size="1"），则在最糟糕的情况<br />
&nbsp;&nbsp;&nbsp;&nbsp;下，需要1&nbsp;+&nbsp;20条SQL语句，如果设置batch-size="10"，则最好的情况下只需要1&nbsp;+&nbsp;2条SQL语句<br />
&nbsp;&nbsp;&nbsp;&nbsp;B.应用于对象关联集合（默认为1）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;set&nbsp;name=".."&nbsp;batch-size=""&nbsp;...&nbsp;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;2.二级缓存<br />
&nbsp;&nbsp;&nbsp;&nbsp;Hibernate对数据的缓存包括两个级：一级缓存，在Session的级别上进行，主要是对象缓存，以其id为键保存对象，在Session的生命期间存在；二级缓存，在SessionFactory的级别上进行，有对象缓存和查询缓存，查询缓存以查询条件为键保存查询结果，在SessionFactory的生命期间存在。默认地，Hibernate只启用一级缓存，通过正确地使用二级缓存，往往可以获得意想不到的性能。<br />
&nbsp;&nbsp;&nbsp;&nbsp;1）对象缓存：<br />
&nbsp;&nbsp;&nbsp;&nbsp;当抓取一个对象之后，Hiberate将其以id为键缓存起来，当下次碰到抓取id相同的对象时，可以使用如下配置<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法1：在缓存对象上配置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&nbsp;...&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cache&nbsp;useage="read-only/write/...."&nbsp;regions="group"&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;useage表示使用什么类型的缓存，譬如只读缓存、读写缓存等等（具体参见Hibernate参考指南），值得注意的时，有部分缓存在Hibernate的实现中不支持读写缓存，譬如JBossCache在Hibernate的实现中只是一种只读缓存，具体缓存实现对缓存类型的支持情况，可以参见org.hibernate.cache包<br />
&nbsp;&nbsp;&nbsp;&nbsp;regions表示缓存分块，大部分的缓存实现往往对缓存进行分块，该部分是可选的，详细参见各缓存实现<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法2：在hibernate.cfg.xml中配置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;cache&nbsp;class=".."&nbsp;useage=".."&nbsp;regions=".."/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;我认为第二种更好，可以统一管理<br />
&nbsp;&nbsp;&nbsp;&nbsp;2)查询缓存<br />
&nbsp;&nbsp;&nbsp;&nbsp;查询时候将查询结果以查询条件为键保存起来，需要配置如下<br />
&nbsp;&nbsp;&nbsp;&nbsp;A.在hibernate.cfg.xml中配置（启用查询缓存）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="hibernate.cache.use_query_cache"&gt;true&lt;/property&gt;&nbsp;&nbsp;（前面的属性名可参见常量<br />
org.hibernate.cfg.Enviroment.USE_QUERY_CACHE）<br />
&nbsp;&nbsp;&nbsp;&nbsp;B.程序<br />
&nbsp;&nbsp;&nbsp;&nbsp;query.setCacheable(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;query.setCacheRegions(...);<br />
&nbsp;&nbsp;&nbsp;&nbsp;需要注意的是,查询缓存与对象缓存要结合更有效,因为查询缓存仅缓存查询结果列表的主键数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;一般情况下在开发中，对一些比较稳定而又被频繁引用的数据，譬如数据字典之类的，将其进行二级缓存，对一些查询条件和查询数据变化不频繁而又常常被使用的查询，将其进行二级缓存。由于二级缓存是放在内存中，而且Hibernate的缓存不是弱引用缓存（WeekReference），所以注意不要将大块的数据放入其中，否则可能会被内存造成比较大的压力。<br />
&nbsp;&nbsp;&nbsp;&nbsp;3.批量数据操作<br />
&nbsp;&nbsp;&nbsp;&nbsp;当进行大批量数据操作（几万甚至几十几百万）时，需要注意两点，一，批量提交，二，及时清除不需要的一级缓存数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;1）所谓的批量提交，就是不要频繁使用session的flush，每一次进行flush，Hibernate将PO数据于数据库进行同步，对于海量级数据操作来说是性能灾难（同时提交几千条数据和提交一条数据flush一次性能差别可能会是几十倍的差异）。一般将数据操作放在事务中，当事务提交时Hibernate自动帮你进行flush操作。<br />
&nbsp;&nbsp;&nbsp;&nbsp;2）及时清除不需要的一级缓存数据：由于Hibernate默认采用一级缓存，而在session的生命期间，所有数据抓取之后会放入一级缓存中，而当数据规模比较庞大时，抓取到内存中的数据会让内存压力非常大，一般分批操作数据，被一次操作之后将一级缓存清除，譬如<br />
&nbsp;&nbsp;&nbsp;&nbsp;session.clear(User.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;4.杂项<br />
&nbsp;&nbsp;&nbsp;&nbsp;dynamic-insert，dynamic-update，动态插入和动态更新，指的是让Hibernate插入数据时仅插入非空数据，当修改数据时只修改变化的数据，譬如对于&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;User<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;password<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;如果u.id=1,&nbsp;u.username="ayufox",u.password=null，那么如果不设置动态插入，则其sql语句是insert&nbsp;into&nbsp;users(id,&nbsp;username,&nbsp;password)&nbsp;values&nbsp;(1,&nbsp;'ayufox',&nbsp;')，如果设置则其sql语句是insert&nbsp;into&nbsp;users(username)&nbsp;valeus('ayufox')<br />
&nbsp;&nbsp;&nbsp;&nbsp;在如上的情况下，如果修改u.password='11'，那么如果不设置动态更新，则sql语句为update&nbsp;users&nbsp;set&nbsp;username='ayufox',&nbsp;password='11'&nbsp;where&nbsp;id&nbsp;=&nbsp;1，如果设置则为update&nbsp;user&nbsp;set&nbsp;password='11'&nbsp;where&nbsp;d&nbsp;=&nbsp;1<br />
&nbsp;&nbsp;&nbsp;&nbsp;设置是在class的映射文件中，如下<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&nbsp;name="User"&nbsp;table="users"&nbsp;dynamic=insert="true/false"&nbsp;dynamic-update="true/false"&nbsp;...&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/class&gt;<br />
　　该设置对性能的提升比较有限<br />
<!-- google_ad_section_end -->
<img src ="http://www.blogjava.net/i369/aggbug/194579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2008-04-21 18:22 <a href="http://www.blogjava.net/i369/articles/194579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏] Java数据类型，Hibernate数据类型，标准sql数据类型之间的对应表 </title><link>http://www.blogjava.net/i369/articles/190588.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Thu, 03 Apr 2008 04:39:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/190588.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/190588.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/190588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/190588.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/190588.html</trackback:ping><description><![CDATA[<table style="border-right: #f3f3f3 5px solid; border-top: #f3f3f3 5px solid; border-left: #f3f3f3 5px solid; border-bottom: #f3f3f3 5px solid" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td style="padding-left: 10px; padding-top: 5px" width="560" colspan="2"><span style="font-size: 13px; line-height: 22px">
            <div class="postTitle"><a class="postTitle2" id="viewpost1_TitleUrl" href="http://www.blogjava.net/haoqingshi/articles/10912.html">Java数据类型，Hibernate数据类型，标准sql数据类型之间的对应表</a></div>
            <table style="width: 100%; text-align: left" cellspacing="2" cellpadding="2" border="1">
                <tbody>
                    <tr>
                        <td style="background-color: rgb(204,204,204)"><small><font size="2">Java数据类型</font></small></td>
                        <td style="background-color: rgb(204,204,204)"><small><font size="2">Hibernate数据类型</font></small></td>
                        <td style="background-color: rgb(204,204,204)"><small><font size="2">标准SQL数据类型<br />
                        (PS:对于不同的DB可能有所差异)</font></small></td>
                    </tr>
                    <tr>
                        <td>byte、java.lang.Byte</td>
                        <td>byte</td>
                        <td>TINYINT</td>
                    </tr>
                    <tr>
                        <td>short、java.lang.Short</td>
                        <td>short</td>
                        <td>SMALLINT</td>
                    </tr>
                    <tr>
                        <td>int、java.lang.Integer</td>
                        <td>integer</td>
                        <td>INGEGER</td>
                    </tr>
                    <tr>
                        <td>long、java.lang.Long</td>
                        <td>long</td>
                        <td>BIGINT</td>
                    </tr>
                    <tr>
                        <td>float、java.lang.Float</td>
                        <td>float</td>
                        <td>FLOAT</td>
                    </tr>
                    <tr>
                        <td>double、java.lang.Double</td>
                        <td>double</td>
                        <td>DOUBLE</td>
                    </tr>
                    <tr>
                        <td>java.math.BigDecimal</td>
                        <td>big_decimal</td>
                        <td>NUMERIC</td>
                    </tr>
                    <tr>
                        <td>char、java.lang.Character</td>
                        <td>character</td>
                        <td>CHAR(1)</td>
                    </tr>
                    <tr>
                        <td>boolean、java.lang.Boolean</td>
                        <td>boolean</td>
                        <td>BIT</td>
                    </tr>
                    <tr>
                        <td>java.lang.String</td>
                        <td>string</td>
                        <td>VARCHAR</td>
                    </tr>
                    <tr>
                        <td>boolean、java.lang.Boolean</td>
                        <td>yes_no</td>
                        <td>CHAR(1)('Y'或'N')</td>
                    </tr>
                    <tr>
                        <td>boolean、java.lang.Boolean</td>
                        <td>true_false</td>
                        <td>CHAR(1)('Y'或'N')</td>
                    </tr>
                    <tr>
                        <td>java.util.Date、java.sql.Date</td>
                        <td>date</td>
                        <td>DATE</td>
                    </tr>
                    <tr>
                        <td>java.util.Date、java.sql.Time</td>
                        <td>time</td>
                        <td>TIME</td>
                    </tr>
                    <tr>
                        <td>java.util.Date、java.sql.Timestamp</td>
                        <td>timestamp</td>
                        <td>TIMESTAMP</td>
                    </tr>
                    <tr>
                        <td>java.util.Calendar</td>
                        <td>calendar</td>
                        <td>TIMESTAMP</td>
                    </tr>
                    <tr>
                        <td>java.util.Calendar</td>
                        <td>calendar_date</td>
                        <td>DATE</td>
                    </tr>
                    <tr>
                        <td>byte[]</td>
                        <td>binary</td>
                        <td>VARBINARY、BLOB</td>
                    </tr>
                    <tr>
                        <td>java.lang.String</td>
                        <td>text</td>
                        <td>CLOB</td>
                    </tr>
                    <tr>
                        <td>java.io.Serializable</td>
                        <td>serializable</td>
                        <td>VARBINARY、BLOB</td>
                    </tr>
                    <tr>
                        <td>java.sql.Clob</td>
                        <td>clob</td>
                        <td>CLOB</td>
                    </tr>
                    <tr>
                        <td>java.sql.Blob</td>
                        <td>blob</td>
                        <td>BLOB</td>
                    </tr>
                    <tr>
                        <td>java.lang.Class</td>
                        <td>class</td>
                        <td>VARCHAR</td>
                    </tr>
                    <tr>
                        <td>java.util.Locale</td>
                        <td>locale</td>
                        <td>VARCHAR</td>
                    </tr>
                    <tr>
                        <td>java.util.TimeZone</td>
                        <td>timezone</td>
                        <td>VARCHAR</td>
                    </tr>
                    <tr>
                        <td>java.util.Currency</td>
                        <td>currency</td>
                        <td>VARCHAR</td>
                    </tr>
                </tbody>
            </table>
            </span></td>
        </tr>
        <tr>
            <td valign="bottom" colspan="2" height="40">文章来源:<a href="http://www.blogjava.net/haoqingshi/articles/10912.html" target="_blank">http://www.blogjava.net/haoqingshi/articles/10912.html</a></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/i369/aggbug/190588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2008-04-03 12:39 <a href="http://www.blogjava.net/i369/articles/190588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让Hibernate输出SQL语句以便更加深入调试程序----参数配置</title><link>http://www.blogjava.net/i369/articles/180461.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 18 Feb 2008 06:33:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/180461.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/180461.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/180461.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/180461.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/180461.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
在J2ee应用中，如果采用Hibernate框架，可以自动建立数据库实体与Java实体类的映射关系，大大方便Java程序进行持久化对象访问和操作，从而明显提高企业应用开发效率，减轻Java程序与后台数据库的依赖性。<br />
<br />
但是，有时候如果操作不慎，可能造成映射关系不完整（特别是存在外键链接的时候），造成访问数据库对象时程序有Bug。这时，可以通过参数配置，让Hibernate在每次需要从数据库查询记录或者每次插入、更新数据库记录时，将相应的SQL语句输出到控制台，从而了解具体的数据库操作，更好地进行程序调试。<br />
<br />
方法是：<br />
1、打开<strong>hibernate.cfg.xml</strong>文件编辑界面，在Properties窗口处，点击<strong>Add</strong>按钮，选择<strong>Show_SQL</strong>参数，输入值为<strong>True</strong>。如下图：<br />
<div forimg="1"><img class="blogimg" src="http://hiphotos.baidu.com/panqf/pic/item/71da8c11a3e8c77bcb80c44d.jpg" border="0" small="0"  alt="" /></div>
<br />
<br />
2、保存<strong>hibernate.cfg.xml。<br />
<br />
</strong>这时，再次运行你的程序，在控制台视图中将会显示相应的SQL语句。<br />
<br />
另外，如果按照同样的步骤，分别加入以下参数，可以让SQL语句更加完美：<br />
1）参数：format_sql=true&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 使SQL语句格式更加美观统一；<br />
2）参数：use_sql_comments=true &nbsp;&nbsp; &nbsp;&nbsp; 使SQL语句中自动注入注释，增加可读性<br />
下图是输出结果的例子：<br />
<div forimg="1"><img class="blogimg" src="http://hiphotos.baidu.com/panqf/pic/item/23297208870a65900a7b825f.jpg" border="0" small="0"  alt="" /></div>
<br />
<br />
除此之外，Hibernate还有很多参数，通过合理配置这些参数，可以对提高Hibernate框架下对象的效率，从而实现对J2ee应用的优化。<br />
这些参数如下：<br />
<font color="#ffffff">Java,IdeaGrace,web,开发,技术,交流,教程 - http://www.ideagrace.com </font><br />
<table summary="Hibernate配置属性    " border="1">
    <thead>
        <tr>
            <th>参数 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.dialect</font></tt></td>
            <td>一个Hibernate <tt class="literal"><font face="新宋体">Dialect</font></tt>类名允许Hibernate针对特定的关系数据库生成优化的SQL. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">full.classname.of.Dialect</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.show_sql</font></tt></td>
            <td>输出所有SQL语句到控制台. 有一个另外的选择是把<tt class="literal"><font face="新宋体">org.hibernate.SQL</font></tt>这个log category设为<tt class="literal"><font face="新宋体">debug</font></tt>。 <span class="strong">eg.</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.format_sql</font></tt></td>
            <td>在log和console中打印出更漂亮的SQL。 <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_schema</font></tt></td>
            <td>在生成的SQL中, 将给定的schema/tablespace附加于非全限定名的表名上. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">SCHEMA_NAME</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_catalog</font></tt></td>
            <td>在生成的SQL中, 将给定的catalog附加于非全限定名的表名上. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">CATALOG_NAME</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.session_factory_name</font></tt></td>
            <td><tt class="literal"><font face="新宋体">SessionFactory</font></tt>创建后，将自动使用这个名字绑定到JNDI中. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">jndi/composite/name</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.max_fetch_depth</font></tt></td>
            <td>为单向关联(一对一, 多对一)的外连接抓取（outer join fetch）树设置最大深度. 值为<tt class="literal"><font face="新宋体">0</font></tt>意味着将关闭默认的外连接抓取. <span class="strong">取值</span> 建议在<tt class="literal"><font face="新宋体">0</font></tt>到<tt class="literal"><font face="新宋体">3</font></tt>之间取值 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_batch_fetch_size</font></tt></td>
            <td>为Hibernate关联的批量抓取设置默认数量. <span class="strong">取值</span> 建议的取值为<tt class="literal"><font face="新宋体">4</font></tt>, <tt class="literal"><font face="新宋体">8</font></tt>, 和<tt class="literal"><font face="新宋体">16</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.default_entity_mode</font></tt></td>
            <td>为由这个<tt class="literal"><font face="新宋体">SessionFactory</font></tt>打开的所有Session指定默认的实体表现模式. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">dynamic-map</font></tt>, <tt class="literal"><font face="新宋体">dom4j</font></tt>, <tt class="literal"><font face="新宋体">pojo</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.order_updates</font></tt></td>
            <td>强制Hibernate按照被更新数据的主键，为SQL更新排序。这么做将减少在高并发系统中事务的死锁。 <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.generate_statistics</font></tt></td>
            <td>如果开启, Hibernate将收集有助于性能调节的统计数据. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.use_identifer_rollback</font></tt></td>
            <td>如果开启, 在对象被删除时生成的标识属性将被重设为默认值. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.use_sql_comments</font></tt></td>
            <td>如果开启, Hibernate将在SQL中生成有助于调试的注释信息, 默认值为<tt class="literal"><font face="新宋体">false</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
    </tbody>
</table>
<div class="table"><a name="configuration-jdbc-properties"></a>
<p class="title"><strong>表 3.4. Hibernate JDBC和连接(connection)属性 </strong></p>
<table summary="Hibernate JDBC和连接(connection)属性    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.fetch_size</font></tt></td>
            <td>非零值，指定JDBC抓取数量的大小 (调用<tt class="literal"><font face="新宋体">Statement.setFetchSize()</font></tt>). </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.batch_size</font></tt></td>
            <td>非零值，允许Hibernate使用JDBC2的批量更新. <span class="strong">取值</span> 建议取<tt class="literal"><font face="新宋体">5</font></tt>到<tt class="literal"><font face="新宋体">30</font></tt>之间的值 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.batch_versioned_data</font></tt></td>
            <td>如果你想让你的JDBC驱动从<tt class="literal"><font face="新宋体">executeBatch()</font></tt>返回正确的行计数 , 那么将此属性设为<tt class="literal"><font face="新宋体">true</font></tt>(开启这个选项通常是安全的). 同时，Hibernate将为自动版本化的数据使用批量DML. 默认值为<tt class="literal"><font face="新宋体">false</font></tt>. <span class="strong">eg.</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.factory_class</font></tt></td>
            <td>选择一个自定义的<tt class="literal"><font face="新宋体">Batcher</font></tt>. 多数应用程序不需要这个配置属性. <span class="strong">eg.</span> <tt class="literal"><font face="新宋体">classname.of.Batcher</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.use_scrollable_resultset</font></tt></td>
            <td>允许Hibernate使用JDBC2的可滚动结果集. 只有在使用用户提供的JDBC连接时，这个选项才是必要的, 否则Hibernate会使用连接的元数据. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.use_streams_for_binary</font></tt></td>
            <td>在JDBC读写<tt class="literal"><font face="新宋体">binary (二进制)</font></tt>或<tt class="literal"><font face="新宋体">serializable (可序列化)</font></tt> 的类型时使用流(stream)(系统级属性). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jdbc.use_get_generated_keys</font></tt></td>
            <td>在数据插入数据库之后，允许使用JDBC3 <tt class="literal"><font face="新宋体">PreparedStatement.getGeneratedKeys()</font></tt> 来获取数据库生成的key(键)。需要JDBC3+驱动和JRE1.4+, 如果你的数据库驱动在使用Hibernate的标 识生成器时遇到问题，请将此值设为false. 默认情况下将使用连接的元数据来判定驱动的能力. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.provider_class</font></tt></td>
            <td>自定义<tt class="literal"><font face="新宋体">ConnectionProvider</font></tt>的类名, 此类用来向Hibernate提供JDBC连接. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.ConnectionProvider</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.isolation</font></tt></td>
            <td>设置JDBC事务隔离级别. 查看<tt class="literal"><font face="新宋体">java.sql.Connection</font></tt>来了解各个值的具体意义, 但请注意多数数据库都不支持所有的隔离级别. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">1, 2, 4, 8</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.autocommit</font></tt></td>
            <td>允许被缓存的JDBC连接开启自动提交(autocommit) (不建议). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.release_mode</font></tt></td>
            <td>指定Hibernate在何时释放JDBC连接. 默认情况下,直到Session被显式关闭或被断开连接时,才会释放JDBC连接. 对于应用程序服务器的JTA数据源, 你应当使用<tt class="literal"><font face="新宋体">after_statement</font></tt>, 这样在每次JDBC调用后，都会主动的释放连接. 对于非JTA的连接, 使用<tt class="literal"><font face="新宋体">after_transaction</font></tt>在每个事务结束时释放连接是合理的. <tt class="literal"><font face="新宋体">auto</font></tt>将为JTA和CMT事务策略选择<tt class="literal"><font face="新宋体">after_statement</font></tt>, 为JDBC事务策略选择<tt class="literal"><font face="新宋体">after_transaction</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">on_close</font></tt> | <tt class="literal"><font face="新宋体">after_transaction</font></tt> | <tt class="literal"><font face="新宋体">after_statement</font></tt> | <tt class="literal"><font face="新宋体">auto</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.connection.<span class="emphasis"><em>&lt;propertyName&gt;</em></span></font></tt></td>
            <td>将JDBC属性<tt class="literal"><font face="新宋体">propertyName</font></tt>传递到<tt class="literal"><font face="新宋体">DriverManager.getConnection()</font></tt>中去. </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.jndi.<span class="emphasis"><em>&lt;propertyName&gt;</em></span></font></tt></td>
            <td>将属性<tt class="literal"><font face="新宋体">propertyName</font></tt>传递到JNDI <tt class="literal"><font face="新宋体">InitialContextFactory</font></tt>中去. </td>
        </tr>
    </tbody>
</table>
</div>
<div class="table"><a name="configuration-cache-properties"></a>
<p class="title"><strong>表 3.5. Hibernate缓存属性 </strong></p>
<table summary="Hibernate缓存属性    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.provider_class</font></tt></td>
            <td>自定义的<tt class="literal"><font face="新宋体">CacheProvider</font></tt>的类名. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.CacheProvider</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_minimal_puts</font></tt></td>
            <td>以频繁的读操作为代价, 优化二级缓存来最小化写操作. 在Hibernate3中，这个设置对的集群缓存非常有用, 对集群缓存的实现而言，默认是开启的. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_query_cache</font></tt></td>
            <td>允许查询缓存, 个别查询仍然需要被设置为可缓存的. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_second_level_cache</font></tt></td>
            <td>能用来完全禁止使用二级缓存. 对那些在类的映射定义中指定<tt class="literal"><font face="新宋体">&lt;cache&gt;</font></tt>的类，会默认开启二级缓存. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.query_cache_factory</font></tt></td>
            <td>自定义实现<tt class="literal"><font face="新宋体">QueryCache</font></tt>接口的类名, 默认为内建的<tt class="literal"><font face="新宋体">StandardQueryCache</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.QueryCache</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.region_prefix</font></tt></td>
            <td>二级缓存区域名的前缀. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">prefix</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cache.use_structured_entries</font></tt></td>
            <td>强制Hibernate以更人性化的格式将数据存入二级缓存. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true|false</font></tt> </td>
        </tr>
    </tbody>
</table>
</div>
<div class="table"><a name="configuration-transaction-properties"></a>
<p class="title"><strong>表 3.6. Hibernate事务属性 </strong></p>
<table summary="Hibernate事务属性    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.factory_class</font></tt></td>
            <td>一个<tt class="literal"><font face="新宋体">TransactionFactory</font></tt>的类名, 用于Hibernate <tt class="literal"><font face="新宋体">Transaction</font></tt> API (默认为<tt class="literal"><font face="新宋体">JDBCTransactionFactory</font></tt>). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.TransactionFactory</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">jta.UserTransaction</font></tt></td>
            <td>一个JNDI名字，被<tt class="literal"><font face="新宋体">JTATransactionFactory</font></tt>用来从应用服务器获取JTA <tt class="literal"><font face="新宋体">UserTransaction</font></tt>. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">jndi/composite/name</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.manager_lookup_class</font></tt></td>
            <td>一个<tt class="literal"><font face="新宋体">TransactionManagerLookup</font></tt>的类名 - 当使用JVM级缓存，或在JTA环境中使用hilo生成器的时候需要该类. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">classname.of.TransactionManagerLookup</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.flush_before_completion</font></tt></td>
            <td>如果开启, session在事务完成后将被自动清洗(flush)。 现在更好的方法是使用自动session上下文管理。<span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.transaction.auto_close_session</font></tt></td>
            <td>如果开启, session在事务完成后将被自动关闭。 现在更好的方法是使用自动session上下文管理。<span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
    </tbody>
</table>
</div>
<div class="table"><a name="configuration-misc-properties"></a>
<p class="title"><strong>表 3.7. 其他属性 </strong></p>
<table summary="其他属性    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>属性名 </th>
            <th>用途 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.current_session_context_class</font></tt></td>
            <td>为"当前" <tt class="literal"><font face="新宋体">Session</font></tt>指定一个(自定义的)策略。<span class="strong">eg.</span> <tt class="literal"><font face="新宋体">jta</font></tt> | <tt class="literal"><font face="新宋体">thread</font></tt> | <tt class="literal"><font face="新宋体">custom.Class</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.query.factory_class</font></tt></td>
            <td>选择HQL解析器的实现. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">org.hibernate.hql.ast.ASTQueryTranslatorFactory</font></tt> or <tt class="literal"><font face="新宋体">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.query.substitutions</font></tt></td>
            <td>将Hibernate查询中的符号映射到SQL查询中的符号 (符号可能是函数名或常量名字). <span class="strong">取值</span> <tt class="literal"><font face="新宋体">hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.hbm2ddl.auto</font></tt></td>
            <td>在<tt class="literal"><font face="新宋体">SessionFactory</font></tt>创建时，自动检查数据库结构，或者将数据库schema的DDL导出到数据库. 使用 <tt class="literal"><font face="新宋体">create-drop</font></tt>时,在显式关闭<tt class="literal"><font face="新宋体">SessionFactory</font></tt>时，将drop掉数据库schema. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">validate</font></tt> | <tt class="literal"><font face="新宋体">update</font></tt> | <tt class="literal"><font face="新宋体">create</font></tt> | <tt class="literal"><font face="新宋体">create-drop</font></tt> </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">hibernate.cglib.use_reflection_optimizer</font></tt></td>
            <td>开启CGLIB来替代运行时反射机制(系统级属性). 反射机制有时在除错时比较有用. 注意即使关闭这个优化, Hibernate还是需要CGLIB. 你不能在<tt class="literal"><font face="新宋体">hibernate.cfg.xml</font></tt>中设置此属性. <span class="strong">取值</span> <tt class="literal"><font face="新宋体">true</font></tt> | <tt class="literal"><font face="新宋体">false</font></tt> </td>
        </tr>
    </tbody>
</table>
</div>
<div class="sect2">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="configuration-optional-dialects"></a>3.4.1. SQL方言 </h3>
</div>
</div>
</div>
<p>你应当总是为你的数据库将<tt class="literal"><font face="新宋体">hibernate.dialect</font></tt>属性设置成正确的 <tt class="literal"><font face="新宋体">org.hibernate.dialect.Dialect</font></tt>子类. 如果你指定一种方言, Hibernate将为上面列出的一些属性使用合理的默认值, 为你省去了手工指定它们的功夫. </p>
<div class="table"><a name="sql-dialects"></a>
<p class="title"><strong>表 3.8. Hibernate SQL方言 (<tt class="literal"><font face="新宋体">hibernate.dialect</font></tt>) </strong></p>
<table summary="Hibernate SQL方言 (hibernate.dialect)    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>RDBMS</th>
            <th>方言 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>DB2</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.DB2Dialect</font></tt></td>
        </tr>
        <tr>
            <td>DB2 AS/400</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.DB2400Dialect</font></tt></td>
        </tr>
        <tr>
            <td>DB2 OS390</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.DB2390Dialect</font></tt></td>
        </tr>
        <tr>
            <td>PostgreSQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.PostgreSQLDialect</font></tt></td>
        </tr>
        <tr>
            <td>MySQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MySQLDialect</font></tt></td>
        </tr>
        <tr>
            <td>MySQL with InnoDB</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MySQLInnoDBDialect</font></tt></td>
        </tr>
        <tr>
            <td>MySQL with MyISAM</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MySQLMyISAMDialect</font></tt></td>
        </tr>
        <tr>
            <td>Oracle (any version)</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.OracleDialect</font></tt></td>
        </tr>
        <tr>
            <td>Oracle 9i/10g</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.Oracle9Dialect</font></tt></td>
        </tr>
        <tr>
            <td>Sybase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SybaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>Sybase Anywhere</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SybaseAnywhereDialect</font></tt></td>
        </tr>
        <tr>
            <td>Microsoft SQL Server</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SQLServerDialect</font></tt></td>
        </tr>
        <tr>
            <td>SAP DB</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.SAPDBDialect</font></tt></td>
        </tr>
        <tr>
            <td>Informix</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.InformixDialect</font></tt></td>
        </tr>
        <tr>
            <td>HypersonicSQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.HSQLDialect</font></tt></td>
        </tr>
        <tr>
            <td>Ingres</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.IngresDialect</font></tt></td>
        </tr>
        <tr>
            <td>Progress</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.ProgressDialect</font></tt></td>
        </tr>
        <tr>
            <td>Mckoi SQL</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.MckoiDialect</font></tt></td>
        </tr>
        <tr>
            <td>Interbase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.InterbaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>Pointbase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.PointbaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>FrontBase</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.FrontbaseDialect</font></tt></td>
        </tr>
        <tr>
            <td>Firebird</td>
            <td><tt class="literal"><font face="新宋体">org.hibernate.dialect.FirebirdDialect</font></tt></td>
        </tr>
    </tbody>
</table>
</div>
</div>
<div>
<p class="title"><strong>表 3.9. Hibernate日志类别 </strong></p>
<table summary="Hibernate日志类别    " border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>类别 </th>
            <th>功能 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.SQL</font></tt></td>
            <td>在所有SQL DML语句被执行时为它们记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.type</font></tt></td>
            <td>为所有JDBC参数记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.tool.hbm2ddl</font></tt></td>
            <td>在所有SQL DDL语句执行时为它们记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.pretty</font></tt></td>
            <td>在session清洗(flush)时，为所有与其关联的实体(最多20个)的状态记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.cache</font></tt></td>
            <td>为所有二级缓存的活动记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction</font></tt></td>
            <td>为事务相关的活动记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.jdbc</font></tt></td>
            <td>为所有JDBC资源的获取记录日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.hql.AST</font></tt></td>
            <td>在解析查询的时候,记录HQL和SQL的AST分析日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.secure</font></tt></td>
            <td>为JAAS认证请求做日志 </td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate</font></tt></td>
            <td>为任何Hibernate相关信息做日志 (信息量较大, 但对查错非常有帮助) </td>
        </tr>
    </tbody>
</table>
</div>
<p class="title"><strong>表 3.10. JTA TransactionManagers</strong></p>
<table summary="JTA TransactionManagers" border="1">
    <colgroup>
    <col></col>
    <col></col></colgroup>
    <thead>
        <tr>
            <th>Transaction工厂类 </th>
            <th align="center">应用程序服务器 </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JBossTransactionManagerLookup</font></tt></td>
            <td align="center">JBoss</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.WeblogicTransactionManagerLookup</font></tt></td>
            <td align="center">Weblogic</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.WebSphereTransactionManagerLookup</font></tt></td>
            <td align="center">WebSphere</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</font></tt></td>
            <td align="center">WebSphere 6</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.OrionTransactionManagerLookup</font></tt></td>
            <td align="center">Orion</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.ResinTransactionManagerLookup</font></tt></td>
            <td align="center">Resin</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JOTMTransactionManagerLookup</font></tt></td>
            <td align="center">JOTM</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JOnASTransactionManagerLookup</font></tt></td>
            <td align="center">JOnAS</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.JRun4TransactionManagerLookup</font></tt></td>
            <td align="center">JRun4</td>
        </tr>
        <tr>
            <td><tt class="literal"><font face="新宋体">org.hibernate.transaction.BESTransactionManagerLookup</font></tt></td>
            <td align="center">Borland ES</td>
        </tr>
    </tbody>
</table>
<br />
<br />
（完）<br />
<br />
<div class="postTitle"><a class="postTitle2" href="http://www.blogjava.net/qclass/archive/2006/08/21/64692.html">采用p6spy完整显示hibernate的SQL语句</a> </div>
<p>&nbsp;&nbsp;&nbsp; 虽然在hibernate中有show_sql选项，但是显示出来的语句大多类似<br />
&nbsp;&nbsp;&nbsp; select * from xxx where value=?<br />
&nbsp;&nbsp;&nbsp; 但是有时候我们需要得到完整的SQL语句，怎么办呢？使用P6SPY就可以完成这个任务</p>
<p>&nbsp;&nbsp;&nbsp; p6spy是一个开源软件，它可以跟踪任何使用jdbc的应用产生的数据库操作。特别适合于监控ejb服务器产生的 sql statements。<br />
&nbsp;&nbsp;&nbsp; 官方网址：<a href="http://www.p6spy.com/">http://www.p6spy.com/</a><br />
&nbsp;&nbsp;&nbsp; 目前p6spy 适用的应用服务器包括jboss, atg, orion, jonas, iplanet, weblogic, websphere, resin and tomcat.</p>
<p>下面我介绍一下p6spy在tomcat应用程序上安装的步骤：<br />
（1）<a href="http://www.p6spy.com/download.html">http://www.p6spy.com/download.html</a>，下载zip包<br />
（2）解压出p6spy.jar spy.properties两个文件<br />
（3）将p6spy.jar 放入应用程序的WEB-INF/lib目录，将spy.properties放入WEB-INF/classes目录<br />
（4）修改spy.properties</p>
<p>&nbsp;&nbsp;&nbsp; realdriver&nbsp; =com.mysql.jdbc.Driver&nbsp; 将这行前面的#去掉<br />
&nbsp;&nbsp;&nbsp; logfile&nbsp;&nbsp;&nbsp;&nbsp; = c:/spy.log&nbsp; 修改一个你需要的日志文件名<br />
&nbsp;&nbsp;&nbsp; <br />
（5）修改hibernate.xml，修改connection.driver_class的值为com.p6spy.engine.spy.P6SpyDriver<br />
（6）重启tomcat<br />
（7）这样在c:/下的spy.log记录了数据库的访问情况。</p>
<br />
<p><br />
</p>
<p>-----------------------------------------</p>
<p>1.下载附件的p6psy.jar以及spy.properties文件</p>
<p>2.将<span class="hilite1">p6spy</span>.jar放到应用的lib目录下,将spy.properties放到WEB-INF\classes目录下</p>
<p>3.修改spy.properties样本的第41行。改成需要的数据库信息 <br />
修改spy.properties样本的第54行 。改成需要的数据库信息<br />
<br />
修改spy.properties样本的第168行，将spy.log放到比较好找的位置： <br />
例如：logfile = E:/spy.log</p>
<p>4.驱动程序加载先后的问题解决 <br />
　　如果spy.log里出现 <br />
　　你的程序的数据库驱动名称 is a real driver in spy.properties, but it has been loaded before <span class="hilite1">p6spy</span>. <span class="hilite1">p6spy</span> will not wrap these connections. Either prevent the driver from loading, or try setting 'deregisterdrivers' to true in spy.properties <br />
　　请把spy.properties文件里的deregisterdrivers=false改为deregisterdrivers=true，重新运行即可。</p>
<p>5.在<span class="hilite2">spring</span>配置文件中配置如下:</p>
<ol class="dp-xml">
    <li class="alt"><span><span class="comments">&lt;!-- <span class="hilite1">P6SPY</span> dataSource target --&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dataSourceTarget"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.<span class="hilite2">spring</span>framework.jdbc.datasource.DriverManagerDataSource"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"driverClassName"</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">"oracle.jdbc.OracleDriver"</span><span> </span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"url"</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">"jdbc:oracle:thin:@localhost:1521:testdb"</span><span> </span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"username"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"tet"</span><span> </span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"test"</span><span> </span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;&nbsp; dataSource --&gt;</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dataSource4develop"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.<span class="hilite1">p6spy</span>.engine.spy.P6DataSource"</span><span> </span><span class="attribute">destroy-method</span><span>=</span><span class="attribute-value">"close"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">constructor-arg</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">ref</span><span> </span><span class="attribute">local</span><span>=</span><span class="attribute-value">"dataSourceTarget"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">constructor-arg</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;</span></li>
</ol>
<img src ="http://www.blogjava.net/i369/aggbug/180461.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2008-02-18 14:33 <a href="http://www.blogjava.net/i369/articles/180461.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate条件查询(Criteria Query) </title><link>http://www.blogjava.net/i369/articles/154089.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Fri, 19 Oct 2007 01:48:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/154089.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/154089.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/154089.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/154089.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/154089.html</trackback:ping><description><![CDATA[<p><font size="2"><font color="#000000"><strong>1、创建一个Criteria实例</strong><br />
net.sf.hibernate.Criteria这个接口代表对一个特定的持久化类的查询。Session是用来制造Criteria实例的工厂。&nbsp;</font></font></p>
<p><font color="#000000" size="2">Criteria&nbsp;crit&nbsp;=&nbsp;sess.createCriteria(Cat.class);<br />
crit.setMaxResults(50);<br />
List&nbsp;cats&nbsp;=&nbsp;crit.list();</font></p>
<p><font color="#000000" size="2">返回最多50条记录的结果集。</font></p>
<p><font size="2"><font color="#000000"><strong>2、缩小结果集范围</strong><br />
一个查询条件(Criterion)是net.sf.hibernate.expression.Criterion接口的一个实例。类net.sf.hibernate.expression.Expression定义了获得一些内置的Criterion类型。&nbsp;</font></font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"Fritz%")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.between("weight",&nbsp;minWeight,&nbsp;maxWeight)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
表达式（Expressions）可以按照逻辑分组.&nbsp;</font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"Fritz%")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.or(<br />
&nbsp;&nbsp;&nbsp;&nbsp; Expression.eq(&nbsp;"age",&nbsp;new&nbsp;Integer(0)&nbsp;),<br />
&nbsp;&nbsp;&nbsp;&nbsp; Expression.isNull("age")<br />
&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();</font></p>
<p><font color="#000000" size="2">返回（name like "Fritz%" and age 等于0 或者 age 为空）的结果集<br />
<br />
<br />
List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.in(&nbsp;"name",&nbsp;new&nbsp;String[]&nbsp;{&nbsp;"Fritz",&nbsp;"Izi",&nbsp;"Pk"&nbsp;}&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.disjunction()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.isNull("age")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; .add(&nbsp;Expression.eq("age",&nbsp;new&nbsp;Integer(0)&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; .add(&nbsp;Expression.eq("age",&nbsp;new&nbsp;Integer(1)&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; .add(&nbsp;Expression.eq("age",&nbsp;new&nbsp;Integer(2)&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();</font></p>
<p><font color="#000000" size="2">Expression.disjunction()----意思是可以按照逻辑分组<br />
有很多预制的条件类型（Expression的子类）。有一个特别有用，可以让你直接嵌入SQL。&nbsp;</font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.sql("lower($alias.name)&nbsp;like&nbsp;lower(?)",&nbsp;"Fritz%",&nbsp;Hibernate.STRING)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
其中的{alias}是一个占位符，它将会被所查询实体的行别名所替代。(原文:The&nbsp;{alias}&nbsp;placeholder&nbsp;with&nbsp;be&nbsp;replaced&nbsp;by&nbsp;the&nbsp;row&nbsp;alias&nbsp;of&nbsp;the&nbsp;queried&nbsp;entity.)&nbsp;</font></p>
<p><font size="2"><font color="#000000"><strong>3、对结果排序</strong><br />
可以使用net.sf.hibernate.expression.Order对结果集排序.&nbsp;</font></font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"F%")<br />
&nbsp;&nbsp;&nbsp;&nbsp;.addOrder(&nbsp;Order.asc("name")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.addOrder(&nbsp;Order.desc("age")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.setMaxResults(50)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
<strong>4、关联（Associations）</strong><br />
你可以在关联之间使用createCriteria()，很容易地在存在关系的实体之间指定约束。&nbsp;</font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"F%")<br />
&nbsp;&nbsp;&nbsp;&nbsp;.createCriteria("kittens")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"F%")<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
注意，第二个createCriteria()返回一个Criteria的新实例，指向kittens集合类的元素。&nbsp;</font></p>
<p><font color="#000000" size="2">下面的替代形式在特定情况下有用。&nbsp;</font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;</font><font size="2"><font color="#000000"><strong>sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.createAlias("kittens",&nbsp;"kt")<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;.createAlias("mate",&nbsp;"mt")<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.eqProperty("kt.name",&nbsp;"mt.name")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
（createAlias()）并不会创建一个Criteria的新实例。）&nbsp;</font></font></p>
<p><font color="#000000" size="2">请注意，前面两个查询中Cat实例所持有的kittens集合类并没有通过criteria预先过滤！如果你希望只返回满足条件的kittens,你必须使用returnMaps()。&nbsp;</font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.createCriteria("kittens",&nbsp;"kt")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.eq("name",&nbsp;"F%")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.returnMaps()<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
Iterator&nbsp;iter&nbsp;=&nbsp;cats.iterator();<br />
while&nbsp;(&nbsp;iter.hasNext()&nbsp;)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;(Map)&nbsp;iter.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;cat&nbsp;=&nbsp;(Cat)&nbsp;map.get(Criteria.ROOT_ALIAS);<br />
&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;kitten&nbsp;=&nbsp;(Cat)&nbsp;map.get("kt");<br />
}<br />
</font><font size="2"><font color="#000000"><strong>5、动态关联对象获取（Dynamic&nbsp;association&nbsp;fetching）<br />
</strong>可以在运行时通过setFetchMode()来改变关联对象自动获取的策略。&nbsp;</font></font></p>
<p><font color="#000000" size="2">List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"Fritz%")&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.setFetchMode("mate",&nbsp;FetchMode.EAGER)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
这个查询会通过外连接(outer&nbsp;join)同时获得&nbsp;mate和kittens。&nbsp;</font></p>
<p><font size="2"><font color="#000000"><strong>6、根据示例查询（Example&nbsp;queries）</strong><br />
net.sf.hibernate.expression.Example类允许你从指定的实例创造查询条件。&nbsp;</font></font></p>
<p><font color="#000000" size="2">Cat&nbsp;cat&nbsp;=&nbsp;new&nbsp;Cat();<br />
cat.setSex('F');<br />
cat.setColor(Color.BLACK);<br />
List&nbsp;results&nbsp;=&nbsp;session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Example.create(cat)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
版本属性，表示符属性和关联都会被忽略。默认情况下，null值的属性也被排除在外。&nbsp;</font></p>
<p><font color="#000000" size="2">You&nbsp;can&nbsp;adjust&nbsp;how&nbsp;the&nbsp;Example&nbsp;is&nbsp;applied.&nbsp;你可以调整示例(Example)如何应用。&nbsp;</font></p>
<p><font color="#000000" size="2">Example&nbsp;example&nbsp;=&nbsp;Example.create(cat)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.excludeZeroes()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//exclude&nbsp;zero&nbsp;valued&nbsp;properties<br />
&nbsp;&nbsp;&nbsp;&nbsp;.excludeProperty("color")&nbsp;&nbsp;//exclude&nbsp;the&nbsp;property&nbsp;named&nbsp;"color"<br />
&nbsp;&nbsp;&nbsp;&nbsp;.ignoreCase()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//perform&nbsp;case&nbsp;insensitive&nbsp;string&nbsp;comparisons<br />
&nbsp;&nbsp;&nbsp;&nbsp;.enableLike();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//use&nbsp;like&nbsp;for&nbsp;string&nbsp;comparisons<br />
List&nbsp;results&nbsp;=&nbsp;session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(example)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
你甚至可以用示例对关联对象建立criteria。&nbsp;</font></p>
<p><font color="#000000" size="2">List&nbsp;results&nbsp;=&nbsp;session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Example.create(cat)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.createCriteria("mate")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Example.create(&nbsp;cat.getMate()&nbsp;)&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;.list();<br />
</font></p>
<img src ="http://www.blogjava.net/i369/aggbug/154089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-19 09:48 <a href="http://www.blogjava.net/i369/articles/154089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的检索策略小结</title><link>http://www.blogjava.net/i369/articles/153543.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Wed, 17 Oct 2007 05:22:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/153543.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/153543.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/153543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/153543.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/153543.html</trackback:ping><description><![CDATA[Hibernate的检索策略包括类级别检索策略和关联级别检索策略。
<p>　　类级别检索策略有立即检索和延迟检索，默认的检索策略是立即检索。在Hibernate映射文件中，通过在&lt;class&gt;上配置lazy属性来确定检索策略。对于Session的检索方式，类级别检索策略仅适用于load方法；也就说，对于get、qurey检索，持久化对象都会被立即加载而不管lazy是false还是true.一般来说，我们检索对象就是要访问它，因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常（立即检索的情况下），因此我个人并不建议使用load检索；而由于&lt;class&gt;中的lazy属性还影响到多对一及一对一的检索策略，因此使用load方法就更没必要了。</p>
<p>　　关联级别检索策略有立即检索、延迟检索和迫切左外连接检索。对于关联级别检索，又可分为一对多和多对多、多对一和一对一两种情况讨论。</p>
<p>　　一对多和多对多关联关系一般使用&lt;set&gt;配置。&lt;set&gt;有lazy和outer-join属性，它们的不同取值绝对了检索策略。</p>
<p>　　1）立即检索：这是一对多默认的检索策略，此时lazy=false，outer-join=false.尽管这是默认的检索策略，但如果关联的集合是无用的，那么就不要使用这种检索方式。</p>
<p>　　2）延迟检索：此时lazy=true，outer-join=false（outer-join=true是无意义的），这是优先考虑的检索方式。</p>
<p>　　3）迫切左外连接检索：此时 lazy=false，outer-join=true，这种检索策略只适用于依靠id检索方式（load、get），而不适用于query的集合检索（它会采用立即检索策略）。相比于立即检索，这种检索策略减少了一条sql语句，但在Hibernate中，只能有一个&lt;set&gt;配置成 outer-join=true.</p>
<p>　　多对一和一对一检索策略一般使用&lt;many-to-one&gt;、&lt;one-to-one&gt;配置。&lt;many-to-one&gt;中需要配置的属性是 outer-join，同时还需要配置one端关联的&lt;class&gt;的lazy属性（配置的可不是&lt;many-to-one&gt;中的lazy哦），它们的组合后的检索策略如下：</p>
<p>　　1） outer-join=auto：这是默认值，如果lazy=true为延迟检索，如果lazy=false为迫切左外连接检索。</p>
<p>　　2） outer-join=true，无关于lazy，都为迫切左外连接检索。</p>
<p>　　3） outer-join=false，如果lazy=true为延迟检索，否则为立即检索。</p>
<p>　　可以看到，在默认的情况下（outer-join=auto，lazy=false），对关联的one端对象Hibernate采用的迫切左外连接检索。依我看，很多情况下，我们并不需要加载one端关联的对象（很可能我们需要的仅仅是关联对象的id）；另外，如果关联对象也采用了迫切左外连接检索，就会出现select语句中有多个外连接表，如果个数多的话会影响检索性能，这也是为什么Hibernate通过hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索，query的集合检索并不适用，它会采用立即检索策略。</p>
<p>　　对于检索策略，需要根据实际情况进行选择。对于立即检索和延迟检索，它们的优点在于select语句简单（每张表一条语句）、查询速度快，缺点在于关联表时需要多条select语句，增加了访问数据库的频率。因此在选择即检索和延迟检索时，可以考虑使用批量检索策略来减少select语句的数量（配置batch-size属性）。对于切左外连接检索，优点在于select较少，但缺点是select语句的复杂度提高，多表之间的关联会是很耗时的操作。另外，配置文件是死的，但程序是活的，可以根据需要在程序里显示的指定检索策略（可能经常需要在程序中显示指定迫切左外连接检索）。为了清楚检索策略的配置效果如何，可以配置show_sql属性查看程序运行时Hibernate执行的sql语句。</p>
<br />
<br />
<div class="postTitle"><iframe style="margin-top: 0px; float: left" border="0" marginwidth="0" framespacing="0" marginheight="0" src="http://wz.csdn.net/vote.aspx?t=Hibernate%u7684fetch%3D%22join%22%20%u548C%20fetch%3D%22select%22%20%u7684%u4E00%u70B9%u641C%u96C6%20-%20%u6211%u7684%u4E16%u754C%u6211%u7684%u68A6%20-%20CSDNBlog&amp;u=http%3A//blog.csdn.net/daryl715/archive/2007/08/23/1755222.aspx" frameborder="0" noResize width="54" scrolling="no" height="75"></iframe><a href="http://blog.csdn.net/daryl715/archive/2007/08/23/1755222.aspx">Hibernate的fetch="join" 和 fetch="select" 的一点搜集 </a>&nbsp;&nbsp; <script src="http://blog.csdn.net/count.aspx?ID=1755222&amp;Type=Rank"></script><span title="文章指数:36"><img src="http://blog.csdn.net/images/star.gif" border="0"  alt="" /><img src="http://blog.csdn.net/images/star_half.gif" border="0"  alt="" /></span>&nbsp;&nbsp;<img title="CSDN Blog推出文章指数概念，文章指数是对Blog文章综合评分后推算出的，综合评分项分别是该文章的点击量，回复次数，被网摘收录数量，文章长度和文章类型；满分100，每月更新一次。" alt="CSDN Blog推出文章指数概念，文章指数是对Blog文章综合评分后推算出的，综合评分项分别是该文章的点击量，回复次数，被网摘收录数量，文章长度和文章类型；满分100，每月更新一次。" src="http://blog.csdn.net/images/ask.gif" border="0" /> </div>
<div class="postText">
<p>fetch参数指定了关联对象抓取的方式是select查询还是join查询，select方式时先查询返回要查询的主体对象（列表），再根据关联外键id，每一个对象发一个select查询，获取关联的对象，形成n+1次查询； <br />
而join方式，主体对象和关联对象用一句外键关联的sql同时查询出来，不会形成多次查询。 <br />
如果你的关联对象是延迟加载的，它当然不会去查询关联对象。 <br />
另外，在hql查询中配置文件中设置的join方式是不起作用的（而在所有其他查询方式如get、criteria或再关联获取等等都是有效的），会使用select方式，除非你在hql中指定join fetch某个关联对象。</p>
<p>&nbsp;</p>
<p>fetch策略用于定义 get/load一个对象时，如何获取非lazy的对象/集合。 这些参数在Query中无效。</p>
<p>fetch策略用于定义 get/load一个对象时，如何获取非lazy的对象/集合。 这些参数在Query中无效。</p>
<p>在某种特殊的场合下，fetch在hql中还是起作用的。 <br />
例如 <br />
<span style="color: blue">现有message(回帖)--&gt;topic(主贴)--&gt;forum(版块) 的多级many-to-one结构: <br />
第一级:message--&gt;topic many-to-one配置lazy="false" fetch="join" <br />
第二级:topic--&gt;forum many-to-one配置lazy="false" fetch="join"</span> <br />
这时如果"from message",则第二级:topic--&gt;forum中的fetch策略会起作用&nbsp;</p>
<p>&nbsp;</p>
<p>查询抓取（默认的）在N+1查询的情况下是极其脆弱的，因此我们可能会要求在映射文档中定义使用连接抓取： </p>
<p>&nbsp;</p>
<p>&lt;set name="permissions" <br />
fetch="join"&gt; <br />
&lt;key column="userId"/&gt; <br />
&lt;one-to-many class="Permission"/&gt; <br />
&lt;/set <br />
&lt;many-to-one name="mother" class="Cat" fetch="join"/&gt; <br />
在映射文档中定义的抓取策略将会有产生以下影响： </p>
<p>通过get()或load()方法取得数据。 </p>
<p>只有在关联之间进行导航时，才会隐式的取得数据(延迟抓取)。 </p>
<p>条件查询 </p>
<p>在映射文档中显式的声明 连接抓取做为抓取策略并不会影响到随后的HQL查询。 </p>
<p>通常情况下，我们并不使用映射文档进行抓取策略的定制。更多的是，保持其默认值，然后在特定的事务中， 使用HQL的左连接抓取（left join fetch） 对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联（outer join），直接得到其关联数据。 在条件查询 API中，应该调用 setFetchMode(FetchMode.JOIN)语句。 <br />
</p>
<p>其实这并不能说明hql能够按照配置文件设置的join进行抓取，这时 第二级:topic--&gt;forum 的抓取其实已经和hql没有关系了，因为前面已经产生了另一个select方式的抓取语句。 <br />
而是对象的关联获取，假如查询message时topic是设置为延迟加载的，那么在后面获取message.topic时，如topic.forum不延迟加载，那么topic--&gt;forum会实现配置的join方式的抓取，这个显然和hql查询没有关系。</p>
<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1755222</p>
</div>
<div class="postTitle"><iframe style="margin-top: 0px; float: left" border="0" marginwidth="0" framespacing="0" marginheight="0" src="http://wz.csdn.net/vote.aspx?t=hibernate%u96C6%u5408%u6620%u5C04inverse%u548Ccascade%u8BE6%u89E3%20-%20WangSY%20-%20CSDNBlog&amp;u=http%3A//blog.csdn.net/xiandelaji/archive/2007/09/13/1782982.aspx" frameborder="0" noResize width="54" scrolling="no" height="75"></iframe><a href="http://blog.csdn.net/xiandelaji/archive/2007/09/13/1782982.aspx"><img height="13" src="http://blog.csdn.net/images/zhuan.gif" width="15" border="0"  alt="" />&nbsp;hibernate集合映射inverse和cascade详解</a>&nbsp;&nbsp; <script src="http://blog.csdn.net/count.aspx?ID=1782982&amp;Type=Rank"></script><img title="文章指数:0" alt="文章指数:0" src="http://blog.csdn.net/images/star_0.gif" border="0" />&nbsp;&nbsp;<img title="CSDN Blog推出文章指数概念，文章指数是对Blog文章综合评分后推算出的，综合评分项分别是该文章的点击量，回复次数，被网摘收录数量，文章长度和文章类型；满分100，每月更新一次。" alt="CSDN Blog推出文章指数概念，文章指数是对Blog文章综合评分后推算出的，综合评分项分别是该文章的点击量，回复次数，被网摘收录数量，文章长度和文章类型；满分100，每月更新一次。" src="http://blog.csdn.net/images/ask.gif" border="0" /> </div>
<div class="postText"><font size="2">&nbsp; </font>
<h4 class="TextColor1" id="subjcns!3196CAE67CDF2316!149" style="margin-bottom: 0px" align="center"><font size="2">hibernate集合映射inverse和cascade详解</font></h4>
<p><font size="2">１、到底在哪用cascade="..."？</font></p>
<p><font size="2">cascade属性并不是多对多关系一定要用的，有了它只是让我们在插入或删除对像时更方便一些，只要在cascade的源头上插入或是删除，所有cascade的关系就会被自己动的插入或是删除。便是为了能正确的cascade，unsaved-value是个很重要的属性。Hibernate通过这个属性来判断一个对象应该save还是update，如果这个对象的id是unsaved-value的话，那说明这个对象不是persistence object要save（insert)；如果id是非unsaved-value的话，那说明这个对象是persistence object（数据库中已存在），只要update就行了。saveOrUpdate方法用的也是这个机制。</font></p>
<p><font size="2">２、到底在哪用inverse="ture"?</font></p>
<p><font size="2">inverse属性默认是false的，就是说关系的两端都来维护关系。这个意思就是说，如有一个Student, Teacher和TeacherStudent表，Student和Teacher是多对多对多关系，这个关系由TeacherStudent这个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来维护关系呢？在用hibernate时，我们不会显示的对TeacherStudent表做操作。对TeacherStudent的操作是hibernate帮我们做的。hibernate就是看hbm文件中指定的是"谁"维护关系，那个在插入或删除"谁"时，就会处发对关系表的操作。前提是"谁"这个对象已经知道这个关系了，就是说关系另一头的对象已经set或是add到"谁"这个对象里来了。前面说过inverse默认是false，就是关系的两端都维护关系，对其中任一个操作都会处发对表系表的操作。当在关系的一头，如Student中的bag或set中用了inverse＝"true"时，那就代表关系是由另一关维护的（Teacher）。就是说当这插入Student时，不会操作TeacherStudent表，即使Student已经知道了关系。只有当Teacher插入或删除时才会处发对关系表的操作。所以，当关系的两头都用inverse="true"是不对的，就会导致任何操作都不处发对关系表的操作。当两端都是inverse="false"或是default值是，在代码对关系显示的维护也是不对的，会导致在关系表中插入两次关系。</font></p>
<p><font size="2">在一对多关系中inverse就更有意义了。在多对多中，在哪端inverse="true"效果差不多（在效率上）。但是在一对多中，如果要一方维护关系，就会使在插入或是删除"一"方时去update"多"方的每一个与这个"一"的对象有关系的对象。而如果让"多"方面维护关系时就不会有update操作，因为关系就是在多方的对象中的，直指插入或是删除多方对象就行了。当然这时也要遍历"多"方的每一个对象显示的操作修关系的变化体现到DB中。不管怎样说，还是让"多"方维护关系更直观一些。</font></p>
<p><font size="2">３、cascade和inverse有什么区别？</font></p>
<p><font size="2">可以这样理解，cascade定义的是关系两端对象到对象的级联关系；而inverse定义的是关系和对象的级联关系。</font></p>
<p><font size="2"></font></p>
<p><a href="http://welcomejianghome.spaces.msn.com/blog/cns!3196CAE67CDF2316!149.entry" target="blank"><u><font size="2"></font></u></a></p>
<font size="2">all : 所有情况下均进行关联操作。 <br />
none：所有情况下均不进行关联操作。这是默认值。 <br />
save-update:在执行save/update/saveOrUpdate时进行关联操作。 <br />
delete：在执行delete时进行关联操作。 </font>
<p>&nbsp;</p>
<p><font size="2">all的意思是save-update + delete <br />
all-delete-orphan 的意思是当对象图中产生孤儿节点时,在数据库中删除该节点 <br />
all比较好理解,举个例子说一下all-delete-orphan: <br />
Category与Item是一对多的关系,也就是说Category类中有个Set类型的变量items. <br />
举个例子,现items中存两个Item, item1,item2,如果定义关系为all-delete-orphan <br />
当items中删除掉一个item(比如用remove()方法删除item1),那么被删除的Item类实例 <br />
将变成孤儿节点,当执行category.update(),或session.flush()时 <br />
hibernate同步缓存和数据库,会把数据库中item1对应的记录删掉 </font></p>
<p><font size="2">//////////////////////////////////////////////////////////////////////////////////////////////////////////</font></p>
<p><font size="2">///////////////////////////////////////////////////////////////////////////////////////////////////////////</font></p>
<div class="bvMsg"><span dir="ltr"><span><font size="2">﻿4. hibernate如何根据pojo来更新数据库<br />
<br />
4.0&nbsp; 在commit/flush之前，hibernate不会对pojo对象作神秘的处理。<br />
4.0.1 在select查询出pojo时，hibernate根据&#8220;字段--属性&#8221;的对应关系，用字段的值填充pojo的属性；<br />
然后根据&#8220;关系标记&#8221;生成sql语句从relationTable中查询出满足条件的relationPojo，并把这些relatinPojo<br />
放到&#8220;关系属性&#8221;中。这个过程是机械的。<br />
<br />
4.0.2 在pojo对象被查出来后，到commit(或flush)之前，它将是一个普通的java对象，hibernate不会做额外的手脚。<br />
比如，不会限制你设置一个属性的值为null或其它任何值<br />
在集合类Set的add(object)操作时， 不会改变object的值，不会检查参数object是否是一个pojo对象<br />
设置mainPojo的一个&#8220;桥属性&#8221;的值，不会自动设置relationPojo的对应的&#8220;桥属性&#8221;的值。<br />
执行session.delete(pojo)时，pojo本身没有变化，他的属性值也没有变化。<br />
执行session.save(pojo)时，如果pojo的id不是hibernate或数据库生成,则它的值没有变化。<br />
&nbsp; 如果pojo的id是hibernate或数据库生成，则hibernate会把id给pojo设上去。<br />
<br />
extend: 对lazy=true的set，hibernate在进行set的操作(调用java.util.Set中声明的方法)时<br />
会先inialize这个set，仅此而已。而inialize仅仅是从数据库中捞出set的数据。 <br />
如果一个set已经被inialize了，那么对它进行的操作就是java.util.Set接口中定义的语义。<br />
<br />
另外，如果id由hibernate来生成，那么在save(pojo)时，hibernate会改变该pojo，会设置它的id，这<br />
可能改变该pojo的hashCode，详细地讨论见帖《》<br />
<br />
mapping文件中标记的某些属性及pojo对象的操作会对数据库操作产生影响，这些影响都是在commit时才会起作用。<br />
而在commit前pojo的状态不受它们的影响。<br />
<br />
不过，待commit之时，将由hibernate完全掌控，它好像知道pojo对象从创建到commit这中间的所有变化。<br />
<br />
<br />
4.01. 关联更新<br />
"关系标记"对应的属性是一个pojo或一个pojo的集合，修改&#8220;关系属性&#8221;的值能会导致更新mainTable表，也可能会更新relationTable表。<br />
<br />
这种更新暂叫&#8220;关联更新&#8221;。<br />
<br />
<br />
4.1.inverse属性的作用（假定没有设置cascade属性） <br />
4.1.1 &#8220;只有集合标记（set/map/list/array/bag）才有inverse属性&#8221;。<br />
————不妨以标记set为例，具体为&#8220;一个地区（Address表）的学校（School表）&#8221; -- address.schoolSet。<br />
<br />
4.1.2 &#8220;set的inverse属性决定是否把对set的改动反映到数据库中去。<br />
inverse=false————反映；inverse=true————不反映&#8221;<br />
inverse属性默认为false<br />
<br />
对&lt;one-to-many&gt;和&lt;many-to-many&gt;子标记，这两条都适用。<br />
不管是对set做什么操作，4.1.2都适用。<br />
<br />
4.1.3当inverse=false时，hibernate如何将对set的改动反映到数据库中：<br />
<br />
对set的操作主要有：（1）新增元素 address.getSchoolSet().add(oneSchool);<br />
（2）删除元素 address.getSchoolSet().remove(oneSchool);<br />
（3）删除set&nbsp; address.setSchoolSet(null);<br />
（4）设新set&nbsp; address.setSchoolSet( newSchoolSet);<br />
（5）转移set&nbsp; otherSchoolSet = otherAddress.getSchoolSet();<br />
&nbsp; otherAddress.setSchoolSet(null);<br />
&nbsp; address.setSchoolSet(otherSchoolSet);<br />
（6）改变set中元素的属性的值&nbsp; 如果是改变key属性，这会导致异常<br />
&nbsp; 如果改变的是普通的属性，则hibernate认为set没有变化（在后面可以看出缘由）。<br />
&nbsp; 所以这种情形不予考虑。<br />
&nbsp; <br />
改变set后，hibernate对数据库的操作根据是&lt;one-to-many&gt;关系还是&lt;many-to-many&gt;关系而有不同。<br />
<br />
对one-to-many，对school set的改动，会改变表SCHOOL中的数据:<br />
&nbsp; #SCHOOL_ID是school表的主键，SCHOOL_ADDRESS是school表中的地址栏位<br />
&nbsp; #表School的外键为SCHOOL_ADDRESS，它对应表Address的主键ADDRESS_ID<br />
（11）insert oneSchool———— sqlInsertRowString: <br />
update SCHOOL set SCHOOL_ADDRESS=? where SCHOOL_ID=? <br />
(仅仅update foreign-key的值。)<br />
（22）delete oneSchool———— sqlDeleteRowString: <br />
update SCHOOL set SCHOOL_ADDRESS=null where SCHOOL_ID=?<br />
（很奇怪，把foreign-key设置为null不知道有什么实际意义？）<br />
（33）delete 属于某一address的所有school ————sqlDeleteString：<br />
update SCHOOL set SCHOOL_ADDRESS=null where SCHOOL_ADDRESS=?<br />
（44）update ————sqlUpdateRowString：""， no need<br />
<br />
对many-to-many，对school set的改动，会改变关系表ADDRESS_SCHOOL中的数据:<br />
#&#8220;地区————学校&#8221;的关系为多对多的关系有点牵强，只是为了方便与上面的one-to-many作比较<br />
#假设有一个关系表ADDRESS_SCHOOL，有两个字段ADDRESS_ID, SCHOOL_ID，<br />
#这两个字段分别对应ADDRESS和SCHOOL两表的key<br />
（11）insert的SQL语句为： insert into ADDRESS_SCHOOL(ADDRESS_ID, SCHOOL_ID) <br />
values(?,?)<br />
（22）delete的SQL语句为： delete from ADDRESS_SCHOOL <br />
where ADDRESS_ID=? AND SCHOOL_ID=?<br />
（33）delete all的SQL语句为： delete from ADDRESS_SCHOOL<br />
where ADDRESS_ID=?<br />
（44）update的sql语句为 ————sqlUpdateRowString：<br />
update ADDRESS_SCHOOL set ADDRESS_ID=?<br />
where ADDRESS_ID=? AND SCHOOL_ID=?<br />
<br />
对set的操作(1),hibernate会执行(11)sqlInsertRowString<br />
对set的操作(2),hibernate会执行(22)sqlDeleteRowString<br />
对set的操作(3),hibernate会执行(33)sqlDeleteString<br />
对set的操作(4),老的schoolSet因为没有所属的address,所以被全部delete掉，即先执行(33)sqlDeleteString<br />
然后新增新的schoolSet,即再执行sqlInsertRowString<br />
对set的操作(5)，实际上就是将set从一个pojo转移到另一pojo：<br />
首先，执行sqlDeleteString，删除掉otherAddress所属的school<br />
然后，执行sqlDeleteString，删除掉address原先的school<br />
最后，执行sqlInsertRowString，将otherSchoolSet新增给address<br />
<br />
总结：（1）对one-to-many而言，改变set，会让hibernate执行一系列的update语句， 不会delete/insert数据<br />
（2）对many-to-many而言，改变set,只修改关系表的数据，不会影响many-to-many的另一方。<br />
（3）虽然one-to-many和many-to-many的数据库操作不一样，但目的都是一个：维护数据的一致性。执行的sql都<br />
只涉及到&#8220;桥字段&#8221;，不会考虑或改变其他的字段，所以对set的操作(6)是没有效果地。<br />
extend:对list,可能还会维护index字段。<br />
<br />
4.1.4 &#8220;inverse与cascade没有什么关系，互无牵扯。&#8221;<br />
commit后，这两个属性发挥作用的时机不同，hibernate会根据对pojo对象的改动，及cascade属性的设置，<br />
生成一系列的Action，比如UpdateAction,DeleteAction,InsertAction等，每个Action都有execute方法以执行对应的sql语句。<br />
待所有这些Action都生成好了后，hibernate再一起执行它们，在执行sql前，inverse属性起作用，<br />
当inverse=true时，不执行sql；当inverse=false时，执行sql。<br />
<br />
4.1.5 inverse的默认值为false，所以inverse属性默认会进行&#8220;关联更新&#8221;。<br />
<br />
4.1.6 建议：只对set + many-to-many设置inverse=false，其他的标记不考虑inverse属性。<br />
&nbsp;&nbsp; 糟糕的是，不设置inverse属性时，inverse默认为false。<br />
<br />
4.2. 级联（cascade）属性的作用： <br />
4.2.1 只有&#8220;关系标记&#8221;才有cascade属性：many-to-one，one-to-one ，any, <br />
set(map, bag, idbag, list, array) + one-to-many(many-to-many)<br />
<br />
4.2.2 级联指的是当主控方执行操作时，关联对象（被动方）是否同步执行同一操作。<br />
pojo和它的关系属性的关系就是&#8220;主控方 -- 被动方&#8221;的关系，如果关系属性是一个set，那么被动方就是set中的一个一个元素，。<br />
比如：学校（School）有三个属性：地区(Address),校长（TheMaster）和学生(Set， 元素为Student)<br />
执行session.delete(school)时，级联决定是否执行session.delete(Address),session.delete(theMaster)，<br />
是否对每个aStudent执行session.delete(aStudent)。<br />
<br />
extend:这点和inverse属性是有区别的。见4.3.<br />
<br />
4.2.3 一个操作因级联cascade可能触发多个关联操作。前一个操作叫&#8220;主控操作&#8221;，后一个操作叫&#8220;关联操作&#8221;。<br />
cascade属性的可选值：<br />
all : 所有情况下均进行关联操作。<br />
none：所有情况下均不进行关联操作。这是默认值。<br />
save-update:在执行save/update/saveOrUpdate时进行关联操作。<br />
delete：在执行delete时进行关联操作。 <br />
<br />
具体执行什么&#8220;关联操作&#8221;是根据&#8220;主控操作&#8221;来的：<br />
&nbsp; &#8220;主控操作&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;关联操作&#8221;<br />
session.saveOrUpdate --&gt; session.saveOrUpdate (执行saveOrUpdate实际上会执行save或者update)<br />
session.save ----&gt; session.saveOrUpdate<br />
session.udpate --&gt; session.saveOrUpdate<br />
session.delete --&gt; session.delete<br />
<br />
4.2.4 主控操作和关联操作的先后顺序是&#8220;先保存one，再保存many；先删除many，再删除one；先update主控方，再update被动方&#8221;<br />
对于one-to-one，当其属性constrained="false"（默认值）时，它可看作one-to-many关系；<br />
&nbsp;&nbsp; 当其属性constrained="true"时，它可看作many-to-one关系；<br />
对many-to-many，它可看作one-to-many。<br />
<br />
比如：学校（School）有三个属性：地区(Address),校长（TheMaster，其constrained="false"）和学生(Set， 元素为Student) <br />
当执行session.save(school)时，<br />
实际的执行顺序为：session.save(Address);<br />
session.save(school);<br />
session.save(theMaster);<br />
for( 对每一个student ){<br />
session.save(aStudent);<br />
}<br />
<br />
当执行session.delete(school)时，<br />
实际的执行顺序为：session.delete(theMaster);<br />
for( 对每一个student ){<br />
session.delete(aStudent);<br />
}<br />
session.delete(school);<br />
session.delete(Address);<br />
<br />
当执行session.update(school)时，<br />
实际的执行顺序为：session.update(school);<br />
session.saveOrUpdate(Address);<br />
session.saveOrUpdate(theMaster);<br />
for( 对每一个student ){<br />
session.saveOrUpdate(aStudent);<br />
}<br />
注意：update操作因级联引发的关联操作为saveOrUpdate操作，而不是update操作。<br />
saveOrUpdate与update的区别是：前者根据操作对象是保存了还是没有保存，而决定执行update还是save<br />
<br />
extends: 实际中，删除学校不会删除地区，即地区的cascade一般设为false<br />
另外，many-to-many关系很少设置cascade=true，而是设置inverse=false。这个反映了cascade和inverse的区别。见4.3<br />
<br />
4.2.6 cascade的默认值为false，所以inverse属性默认会进行&#8220;关联更新&#8221;。<br />
<br />
4.2.7 总结：级联（cascade）就是操作一个对象时，对它的属性（其cascade=true）也进行这个操作。<br />
<br />
<br />
4.3 inverse和cascade的比较<br />
这两个属性本身互不影响，但起的作用有些类似，都能引发对关系表的更新。<br />
<br />
4.3.1 inverse只对set+one-to-many(或many-to-many)有效，对many-to-one, one-to-one无效。<br />
&nbsp; cascade对关系标记都有效。<br />
&nbsp; <br />
4.3.2 inverse对集合对象整体起作用，cascade对集合对象中的一个一个元素起作用，如果集合为空，那么cascade不会引发关联操作。<br />
比如将集合对象置为null， school.setStudentSet(null)<br />
inverse导致hibernate执行:udpate STUDENT set SCHOOL_ID=null where SCHOOL_ID=?<br />
cascade则不会执行对STUDENT表的关联更新， 因为集合中没有元素。<br />
<br />
再比新增一个school, session.save(school)<br />
inverse导致hibernate执行：<br />
for( 对(school的每一个student ){<br />
udpate STUDENT set SCHOOL_ID=? where STUDENT_ID=? //将学生的school_id改为新的school的id<br />
}<br />
cascade导致hibernate执行：<br />
for( 对school的每一个student ){<br />
session.save(aStudent); //对学生执行save操作<br />
}<br />
<br />
extends:如果改变集合中的部分元素（比如新增一个元素），<br />
inverse: hibernate先判断哪些元素改变了，对改变的元素执行相应的sql<br />
cascade: 它总是对集合中的每个元素执行关联操作。<br />
（在关联操作中，hibernate会判断操作的对象是否改变）<br />
<br />
4.3.2 两个起作用的时机不同：<br />
cascade：在对主控方操作时，级联发生。<br />
inverse: 在flush时（commit会自动执行flush)，对session中的所有set，hibernate判断每个set是否有变化，<br />
对有变化的set执行相应的sql，执行之前，会有个判断：if( inverse == true ) return;<br />
<br />
可以看出cascade在先，inverse在后。<br />
<br />
4.3.3 inverse 对set + one-to-many 和 set + many-to-many 起的作用不同。hibernate生成的sql不同。<br />
&nbsp; 对one-to-many，hibernate对many方的数据库表执行update语句。<br />
&nbsp; 对many-to-many, hibernate对关系表执行insert/update/delte语句，注意不是对many方的数据库表而是关系表。<br />
&nbsp; <br />
&nbsp; cascase 对set都是一致的，不管one-to-many还是many-to-many。都简单地把操作传递到set中的每个元素。所以它总是更新many<br />
方的数据库表。<br />
<br />
4.3.4 建议：只对set + many-to-many设置inverse=false，其他的标记不考虑inverse属性，都设为inverse=true。<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 对cascade，一般对many-to-one，many-to-many，constrained=true的one-to-one 不设置级联删除。</font></span></span></div>
<div class="bvMsg"><span dir="ltr"></span><font size="2">&nbsp;</font></div>
<div class="bvMsg"><span dir="ltr"></span><font size="2">&nbsp;</font></div>
<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1782982</p>
</div>
<img src ="http://www.blogjava.net/i369/aggbug/153543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-17 13:22 <a href="http://www.blogjava.net/i369/articles/153543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibername延迟检索问题!</title><link>http://www.blogjava.net/i369/articles/153198.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Tue, 16 Oct 2007 03:20:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/153198.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/153198.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/153198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/153198.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/153198.html</trackback:ping><description><![CDATA[<p>其实这个异常写的非常之清楚，就是会话关闭，无法对Hibernate实体进行操作。造成这样的情况有很多，什么书写错误啊，逻辑错误啊。</p>
<p>但就此说一下关于lazy机制：</p>
<p><font color="#800080">延迟初始化错误是运用Hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检索策略，那么必须当代理类实例或代理集合处于持久化状态（即处于</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">范围内）时，才能初始化它。如果在游离状态时才初始化它，就会产生延迟初始化错误。<br />
<br />
下面把Customer.hbm.xml文件的&lt;class&gt;元素的lazy属性设为true，表示使用延迟检索策略：<br />
<br />
&lt;class name="mypack.Customer" table="CUSTOMERS" lazy="true"&gt;<br />
<br />
当执行</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">的load()方法时，Hibernate不会立即执行查询CUSTOMERS表的select语句，仅仅返回Customer类的代理类的实例，这个代理类具由以下特征：<br />
<br />
（1） 由Hibernate在运行时动态生成，它扩展了Customer类，因此它继承了Customer类的所有属性和方法，但它的实现对于应用程序是透明的。<br />
（2） 当Hibernate创建Customer代理类实例时，仅仅初始化了它的OID属性，其他属性都为null，因此这个代理类实例占用的内存很少。<br />
（3）当应用程序第一次访问Customer代理类实例时（例如调用customer.getXXX()或customer.setXXX()方法）， Hibernate会初始化代理类实例，在初始化过程中执行select语句，真正从数据库中加载Customer对象的所有数据。但有个例外，那就是当应用程序访问Customer代理类实例的getId()方法时，Hibernate不会初始化代理类实例，因为在创建代理类实例时OID就存在了，不必到数据库中去查询。<br />
<br />
提示：Hibernate采用CGLIB工具来生成持久化类的代理类。CGLIB是一个功能强大的Java字节码生成工具，它能够在程序运行时动态生成扩展 Java类或者实现Java接口的代理类。关于CGLIB的更多知识，请参考：http://cglib.sourceforge.net/。<br />
<br />
以下代码先通过</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">的load()方法加载Customer对象，然后访问它的name属性： <br />
<br />
tx = </font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.beginTransaction();<br />
Customer customer=(Customer)</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.load(Customer.class,new Long(1));<br />
customer.getName();<br />
tx.commit();<br />
<br />
在运行</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.load()方法时Hibernate不执行任何select语句，仅仅返回Customer类的代理类的实例，它的OID为1，这是由load()方法的第二个参数指定的。当应用程序调用customer.getName()方法时，Hibernate会初始化Customer代理类实例，从数据库中加载Customer对象的数据，执行以下select语句：<br />
<br />
select * from CUSTOMERS where ID=1;<br />
select * from ORDERS where CUSTOMER_ID=1;<br />
<br />
当&lt;class&gt;元素的lazy属性为true，会影响</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">的load()方法的各种运行时行为，下面举例说明。<br />
<br />
1．如果加载的Customer对象在数据库中不存在，</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">的load()方法不会抛出异常，只有当运行customer.getName()方法时才会抛出以下异常：<br />
<br />
ERROR LazyInitializer:63 </font><strong style="color: black; background-color: #ff66ff">-</strong><font color="#800080"> Exception initializing </font><strong style="color: black; background-color: #ff9999">proxy</strong><br />
<font color="#800080">net.sf.hibernate.ObjectNotFoundException: No row with </font><strong style="color: white; background-color: #880000">the</strong><font color="#800080"> given identifier exists: 1, of class: <br />
mypack.Customer<br />
<br />
2．如果在整个</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">范围内，应用程序没有访问过Customer对象，那么Customer代理类的实例一直不会被初始化，Hibernate不会执行任何select语句。以下代码试图在关闭</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">后访问Customer游离对象：<br />
<br />
tx = </font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.beginTransaction();<br />
Customer customer=(Customer)</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.load(Customer.class,new Long(1));<br />
tx.commit();<br />
</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.close();<br />
customer.getName();<br />
<br />
由于引用变量customer引用的Customer代理类的实例在</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">范围内始终没有被初始化，因此在执行customer.getName()方法时，Hibernate会抛出以下异常：<br />
<br />
ERROR LazyInitializer:63 </font><strong style="color: black; background-color: #ff66ff">-</strong><font color="#800080"> Exception initializing </font><strong style="color: black; background-color: #ff9999">proxy</strong><br />
<font color="#800080">net.sf.hibernate.HibernateException: </font><strong style="color: black; background-color: #ffff66">Could</strong><font color="#800080"> </font><strong style="color: black; background-color: #a0ffff">not</strong><font color="#800080"> </font><strong style="color: black; background-color: #99ff99">initialize</strong><font color="#800080"> </font><strong style="color: black; background-color: #ff9999">proxy</strong><font color="#800080"> </font><strong style="color: black; background-color: #ff66ff">-</strong><font color="#800080"> </font><strong style="color: white; background-color: #880000">the</strong><font color="#800080"> </font><strong style="color: white; background-color: #00aa00">owning</strong><font color="#800080"> </font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080"> </font><strong style="color: white; background-color: #004699">was</strong><font color="#800080"> </font><strong style="color: white; background-color: #990099">closed</strong><br />
<br />
<font color="#800080">由此可见，Customer代理类的实例只有在当前</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">范围内才能被初始化。<br />
<br />
3．net.sf.hibernate.Hibernate类的</font><strong style="color: black; background-color: #99ff99">initialize</strong><font color="#800080">()静态方法用于在</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">范围内显式初始化代理类实例，isInitialized()方法用于判断代理类实例是否已经被初始化。例如：<br />
<br />
tx = </font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.beginTransaction();<br />
Customer customer=(Customer)</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.load(Customer.class,new Long(1));<br />
if(!Hibernate.isInitialized(customer)) <br />
Hibernate.</font><strong style="color: black; background-color: #99ff99">initialize</strong><font color="#800080">(customer);<br />
tx.commit();<br />
</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.close();<br />
customer.getName();<br />
<br />
以上代码在</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">范围内通过Hibernate类的</font><strong style="color: black; background-color: #99ff99">initialize</strong><font color="#800080">()方法显式初始化了Customer代理类实例，因此当</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">关闭后，可以正常访问Customer游离对象。<br />
<br />
4．当应用程序访问代理类实例的getId()方法时，不会触发Hibernate初始化代理类实例的行为，例如：<br />
<br />
tx = </font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.beginTransaction();<br />
Customer customer=(Customer)</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.load(Customer.class,new Long(1));<br />
customer.getId();<br />
tx.commit();<br />
</font><strong style="color: white; background-color: #886800">session</strong><font color="#800080">.close();<br />
customer.getName();<br />
<br />
当应用程序访问customer.getId()方法时，该方法直接返回Customer代理类实例的OID值，无需查询数据库。由于引用变量 customer始终引用的是没有被初始化的Customer代理类实例，因此当</font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080">关闭后再执行customer.getName()方法， Hibernate会抛出以下异常：</font></p>
<p><font color="#800080">ERROR LazyInitializer:63 </font><strong style="color: black; background-color: #ff66ff">-</strong><font color="#800080"> Exception initializing </font><strong style="color: black; background-color: #ff9999">proxy</strong><br />
<font color="#800080">net.sf.hibernate.HibernateException: </font><strong style="color: black; background-color: #ffff66">Could</strong><font color="#800080"> </font><strong style="color: black; background-color: #a0ffff">not</strong><font color="#800080"> </font><strong style="color: black; background-color: #99ff99">initialize</strong><font color="#800080"> </font><strong style="color: black; background-color: #ff9999">proxy</strong><font color="#800080"> </font><strong style="color: black; background-color: #ff66ff">-</strong><font color="#800080"> </font><strong style="color: white; background-color: #880000">the</strong><font color="#800080"> </font><strong style="color: white; background-color: #00aa00">owning</strong><font color="#800080"> </font><strong style="color: white; background-color: #886800">Session</strong><font color="#800080"> </font><strong style="color: white; background-color: #004699">was</strong><font color="#800080"> </font><strong style="color: white; background-color: #990099">closed</strong></p>
<p><strong><font style="background-color: #990099" color="#ffffff"></font></strong></p>
<p><strong><font style="background-color: #990099" color="#ffffff">解决方法：</font></strong></p>
<p>由于hibernate采用了lazy=true,这样当你用hibernate查询时,返回实际为利用cglib增强的代理类,但其并没有实际填充;当你在前端,利用它来取值(getXXX)时,这时Hibernate才会到数据库执行查询,并填充对象,但此时如果和这个代理类相关的session已关闭掉,就会产生种错误.<br />
在做一对多时，有时会出现"could not initialize proxy - clothe owning Session was sed,这个好像是hibernate的缓存问题.问题解决:需要在&lt;many-to-one&gt;里设置lazy="false". 但有可能会引发另一个异常叫</p>
<p>failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed</p>
<p>此异常解决方案请察看本人博客（http://hi.baidu.com/kekemao1）的Hibernate异常中的《failed to lazily initialize a collection of role异常》<br />
<br />
?<br />
解决方法:在web.xml中加入<br />
&lt;filter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.orm.hibernate3.support.OpenSessionInViewFilter<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/filter-class&gt;<br />
&lt;/filter<br />
&lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;<br />
就可以了;</p>
<p>参考了:<br />
Hibernate与延迟加载：</p>
<p>Hibernate对象关系映射提供延迟的与非延迟的对象初始化。非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来。这有时会导致成百的（如果不是成千的话）select语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候，经常会导致整个数据库都在初始化的阶段被读出来了。当然，你可以不厌其烦地检查每一个对象与其他对象的关系，并把那些最昂贵的删除，但是到最后，我们可能会因此失去了本想在ORM工具中获得的便利。</p>
<p><br />
一个明显的解决方法是使用Hibernate提供的延迟加载机制。这种初始化策略只在一个对象调用它的一对多或多对多关系时才将关系对象读取出来。这个过程对开发者来说是透明的，而且只进行了很少的数据库操作请求，因此会得到比较明显的性能提升。这项技术的一个缺陷是延迟加载技术要求一个Hibernate会话要在对象使用的时候一直开着。这会成为通过使用DAO模式将持久层抽象出来时的一个主要问题。为了将持久化机制完全地抽象出来，所有的数据库逻辑，包括打开或关闭会话，都不能在应用层出现。最常见的是，一些实现了简单接口的DAO实现类将数据库逻辑完全封装起来了。一种快速但是笨拙的解决方法是放弃DAO模式，将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效，但是在大的系统中，这是一个严重的设计缺陷，妨碍了系统的可扩展性。</p>
<p>在Web层进行延迟加载</p>
<p>幸运的是，Spring框架为Hibernate延迟加载与DAO模式的整合提供了一种方便的解决方法。对那些不熟悉Spring与Hibernate集成使用的人，我不会在这里讨论过多的细节，但是我建议你去了解Hibernate与Spring集成的数据访问。以一个Web应用为例，Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我们可以随意选择一个类来实现相同的功能。两种方法唯一的不同就在于interceptor在Spring容器中运行并被配置在web应用的上下文中，而Filter在Spring之前运行并被配置在web.xml中。不管用哪个，他们都在请求将当前会话与当前（数据库）线程绑定时打开Hibernate会话。一旦已绑定到线程，这个打开了的Hibernate会话可以在DAO实现类中透明地使用。这个会话会为延迟加载数据库中值对象的视图保持打开状态。一旦这个逻辑视图完成了，Hibernate会话会在Filter的doFilter方法或者Interceptor的postHandle方法中被关闭。下面是每个组件的配置示例：</p>
<p>&nbsp;</p>
<p><br />
Interceptor的配置:</p>
<p>&nbsp;</p>
<p>&lt;beans&gt; <br />
&lt;bean id="urlMapping" <br />
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt; <br />
&lt;property name="interceptors"&gt; <br />
&lt;list&gt; <br />
&lt;ref bean="openSessionInViewInterceptor"/&gt; <br />
&lt;/list&gt; <br />
&lt;/property&gt; <br />
&lt;property name="mappings"&gt; <br />
<br />
&lt;/bean&gt; <br />
<br />
&lt;bean name="openSessionInViewInterceptor" <br />
class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor"&gt; <br />
&lt;property name="sessionFactory"&gt;&lt;ref bean="sessionFactory"/&gt;&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;/beans&gt; </p>
<p>Filter的配置</p>
<p>&nbsp;</p>
<p>&lt;web-app&gt; <br />
<br />
&lt;filter&gt; <br />
&lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt; <br />
&lt;filter-class&gt; <br />
org.springframework.orm.hibernate.support.OpenSessionInViewFilter <br />
&lt;/filter-class&gt; <br />
&lt;/filter&gt; <br />
<br />
&lt;filter-mapping&gt; <br />
&lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt; <br />
&lt;url-pattern&gt;*. spring &lt;/url-pattern&gt; <br />
&lt;/filter-mapping&gt; <br />
<br />
&lt;/web-app&gt; </p>
<p><br />
实现Hibernate的Dao接口来使用打开的会话是很容易的。事实上，如果你已经使用了Spring框架来实现你的Hibernate Dao,很可能你不需要改变任何东西。方便的HibernateTemplate公用组件使访问数据库变成小菜一碟，而DAO接口只有通过这个组件才可以访问到数据库。下面是一个示例的DAO：</p>
<p><br />
public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO { </p>
<p>public Product getProduct(Integer productId) { <br />
return (Product)getHibernateTemplate().load(Product.class, productId); <br />
} </p>
<p>public Integer saveProduct(Product product) { <br />
return (Integer) getHibernateTemplate().save(product); <br />
} </p>
<p>public void updateProduct(Product product) { <br />
getHibernateTemplate().update(product); <br />
} <br />
} </p>
<p>&nbsp;</p>
<p>在业务逻辑层中使用延迟加载</p>
<p>即使在视图外面，Spring框架也通过使用AOP 拦截器 HibernateInterceptor来使得延迟加载变得很容易实现。这个Hibernate 拦截器透明地将调用配置在Spring应用程序上下文中的业务对象中方法的请求拦截下来，在调用方法之前打开一个Hibernate会话，然后在方法执行完之后将会话关闭。让我们来看一个简单的例子，假设我们有一个接口BussinessObject：</p>
<p><br />
public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; interface&nbsp;&nbsp;&nbsp;&nbsp; BusinessObject&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp; doSomethingThatInvolvesDaos(); <br />
} <br />
类BusinessObjectImpl实现了BusinessObject接口:</p>
<p>public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class&nbsp;&nbsp;&nbsp;&nbsp; BusinessObjectImpl&nbsp;&nbsp;&nbsp;&nbsp; implements&nbsp;&nbsp;&nbsp;&nbsp; BusinessObject&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp; doSomethingThatInvolvesDaos()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
//&nbsp;&nbsp;&nbsp;&nbsp; lots of logic that calls <br />
//&nbsp;&nbsp;&nbsp;&nbsp; DAO classes Which access <br />
//&nbsp;&nbsp;&nbsp;&nbsp; data objects lazily&nbsp;&nbsp;<br />
}&nbsp;&nbsp;<br />
}&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p><br />
通过在Spring应用程序上下文中的一些配置，我们可以让将调用BusinessObject的方法拦截下来，再令它的方法支持延迟加载。看看下面的一个程序片段：</p>
<p>&nbsp;</p>
<p><br />
&lt;beans&gt; <br />
&lt;bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor"&gt; <br />
&lt;property name="sessionFactory"&gt; <br />
&lt;ref bean="sessionFactory"/&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl"&gt; <br />
&lt;property name="someDAO"&gt;&lt;ref bean="someDAO"/&gt;&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean"&gt; <br />
&lt;property name="target"&gt;&lt;ref bean="businessObjectTarget"/&gt;&lt;/property&gt; <br />
&lt;property name="proxyInterfaces"&gt; <br />
&lt;value&gt;com.acompany.BusinessObject&lt;/value&gt; <br />
&lt;/property&gt; <br />
&lt;property name="interceptorNames"&gt; <br />
&lt;list&gt; <br />
&lt;value&gt;hibernateInterceptor&lt;/value&gt; <br />
&lt;/list&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;/beans&gt;</p>
<p>当businessObject被调用的时候，HibernateInterceptor打开一个Hibernate会话，并将调用请求传递给BusinessObjectImpl对象。当BusinessObjectImpl执行完成后，HibernateInterceptor透明地关闭了会话。应用层的代码不用了解任何持久层逻辑，还是实现了延迟加载。</p>
<p><br />
在单元测试中测试延迟加载</p>
<p>最后，我们需要用J-Unit来测试我们的延迟加载程序。我们可以轻易地通过重写TestCase类中的setUp和tearDown方法来实现这个要求。我比较喜欢用这个方便的抽象类作为我所有测试类的基类。</p>
<p><br />
public abstract class MyLazyTestCase extends TestCase { </p>
<p>private SessionFactory sessionFactory; <br />
private Session session; </p>
<p>public void setUp() throws Exception { <br />
super.setUp(); <br />
SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory"); <br />
session = SessionFactoryUtils.getSession(sessionFactory, true); <br />
Session s = sessionFactory.openSession(); <br />
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s)); </p>
<p>} </p>
<p>protected Object getBean(String beanName) { <br />
//Code to get objects from Spring application context <br />
} </p>
<p>public void tearDown() throws Exception { <br />
super.tearDown(); <br />
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); <br />
Session s = holder.getSession(); <br />
s.flush(); <br />
TransactionSynchronizationManager.unbindResource(sessionFactory); <br />
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory); <br />
} <br />
}</p>
<img src ="http://www.blogjava.net/i369/aggbug/153198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-16 11:20 <a href="http://www.blogjava.net/i369/articles/153198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]回复：《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》 </title><link>http://www.blogjava.net/i369/articles/152868.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 15 Oct 2007 01:44:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/152868.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/152868.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/152868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/152868.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/152868.html</trackback:ping><description><![CDATA[<table width="100%">
    <tbody>
        <tr>
            <td>&nbsp;
            <p><span Times Roman?;?2?><a href="http://fangang.javaeye.com/admin/show/47670">如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件</a></font></span>》。昨天和几个朋友讨论问题的时候，谈到通过</span>DaoSupport</p>
            <h3>2<span Times Roman?;?Arial?><font face="Arial">
            <div>java 代码</div>
            </font></font></span>
            <h3><span>
            <div>
            <ol>
                <li>package&nbsp;com.htxx.thps.psb.dao.imp; &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>import&nbsp;com.htxx.service.dao.BasicDao; &nbsp;&nbsp;
                <li>import&nbsp;com.htxx.service.dao.Condition; &nbsp;&nbsp;
                <li>import&nbsp;com.htxx.service.dao.ResultSet; &nbsp;&nbsp;
                <li>import&nbsp;com.htxx.thps.model.PsPsb; &nbsp;&nbsp;
                <li>import&nbsp;com.htxx.thps.model.PsPsjcd; &nbsp;&nbsp;
                <li>import&nbsp;com.htxx.thps.model.PsWtmx; &nbsp;&nbsp;
                <li>import&nbsp;com.htxx.thps.psb.dao.PsbDao; &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>/** &nbsp;
                <li>&nbsp;*&nbsp;@author&nbsp;FanGang &nbsp;
                <li>&nbsp;* &nbsp;
                <li>&nbsp;*/&nbsp;&nbsp;
                <li>public&nbsp;class&nbsp;PsbDaoImp&nbsp;extends&nbsp;BasicDao&nbsp;implements&nbsp;PsbDao&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;(non-Javadoc) &nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;com.htxx.thps.psb.dao.PsbDao#getPsb(java.lang.String) &nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;PsPsb&nbsp;getPsb(String&nbsp;id)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(PsPsb)this.load(PsPsb.class,&nbsp;id); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;(non-Javadoc) &nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;com.htxx.thps.psb.dao.PsbDao#updatePsb(com.htxx.thps.model.PsPsb) &nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;updatePsb(PsPsb&nbsp;vo)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.update(vo); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;(non-Javadoc) &nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;com.htxx.thps.psb.dao.PsbDao#getPsb(com.htxx.service.dao.Condition) &nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ResultSet&nbsp;getPsb(Condition&nbsp;condition)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;this.query("PsPsb",&nbsp;condition); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;PsPsjcd&nbsp;getPsjcd(String&nbsp;id)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(PsPsjcd)this.load(PsPsjcd.class,&nbsp;id); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ResultSet&nbsp;getPsjcd(Condition&nbsp;condition)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;this.query("PsPsjcd",&nbsp;condition); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;PsWtmx&nbsp;getWtmx(String&nbsp;id)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(PsWtmx)this.load(PsWtmx.class,&nbsp;id); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ResultSet&nbsp;getWtmx(Condition&nbsp;condition)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;this.query("PsWtmx",&nbsp;condition); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;updatePsjcd(PsPsjcd&nbsp;vo)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.update(vo); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;updateWtmx(PsWtmx&nbsp;vo)&nbsp;{ &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.update(vo); &nbsp;&nbsp;
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;
                <li>&nbsp;&nbsp;
                <li>}&nbsp;&nbsp; </li>
            </ol>
            </div>
            4</span>&nbsp;
            <p>&nbsp;</p>
            <p><span Times Roman?;?2?><a href="http://fangang.javaeye.com/admin/show/47670">如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件</a></font></span>》中已经给出了这个结构的一个实现，供大家参考。</span></p>
            </h3>
            </h3>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<br />
说明:以上2篇文章均来自:http://fangang.javaeye.com/blog/52883推荐,到原博客阅读,和下载相关代码,此处只是本人收藏,方便查看,在此向作者表示衷心感谢!
<img src ="http://www.blogjava.net/i369/aggbug/152868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-15 09:44 <a href="http://www.blogjava.net/i369/articles/152868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件</title><link>http://www.blogjava.net/i369/articles/152863.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 15 Oct 2007 01:39:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/152863.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/152863.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/152863.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/152863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/152863.html</trackback:ping><description><![CDATA[<strong><font size="4">问题的提出</font></strong>
<p><span style="font-family: 宋体">我常常在思考一个问题，我们如何能设计出高水平、高质量的软件出来。怎样是高水平、高质量的软件？它应当是易于维护、易于适应变更、可重用性好的一个系统。如何做到这一点呢？答案当然是&#8220;低耦合、高内聚&#8221;了。低耦合就是软件在构造的时候，各个模块、各个功能、各个类都不会过度依赖于它周围的环境。只有这样，才能使我们的模块（功能、类）在周围发生变更时不受影响，做到易于维护和易于适应变更。正因为如此，也使它更易于重用到其它功能类似的环境中，提高了重用性。高内聚则使软件中的各个模块（功能、类）能够各尽其能而又充分合作，也就是对于软件问题空间中需求的各个功能，系统可以合理地把它分配给各个模块（功能、类）来共同完成，而不是一个或几个八面玲珑、包打天下的超级类一个人完成。而对于该系统中的某一个模块（功能、类），具有自己高度相关的职责，即该职责中的几个任务是高度相关的。每一个模块（功能、类）都决不去完成与自己无关职责的任务。</span></p>
<p><span style="font-family: 宋体">那么怎样能构造一个低耦合、高内聚的系统能，时下最流行的框架结构之一的</span>struts+spring+hibernate<span Times 宋体;? Roman?;?font-family:>然而我要说的是，即使我们使用了</span>struts+spring+hibernate&nbsp;</p>
<pre><strong><font size="4">分析与决策</font></strong></pre>
<h2><span style="font-size: 14pt; line-height: 173%">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>编写DAO的时候不要直接去使用hibernate或spring对hibernate的支持。</h2>
<p><span style="font-family: 宋体">现在我们在编写</span>DAO<span Times Roman?; ?Times New Courier New?; 宋体;? New?;?font-family:>以上问题，究其原因，是我们项目中的</span>DAO<span Times Roman?; ?Times New Courier New?; New?;??><img height="528" alt="" src="http://www.javaeye.com/topics/download/caeb8220-1b1e-4efe-93d2-eda8a63db6fc" width="551" /></span></p>
<h2><span style="font-size: 14pt; line-height: 173%">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>编写Action的时候不要直接使用spring和spring的继承类</h2>
<p><span style="font-family: 宋体">前面我说了应当避免</span>DAO<span Times Roman?; ?Times New Courier New?; ?Courier>的继承类</span><span ?Courier>然后使用它的</span><span Courier New?; ?Courier>方法。如此的使用，我们的</span><span Courier New?;>Action</span><span ?Courier>将依赖与</span><span Courier New?;>spring</span><span ?Courier>。我们同样可以使用一个叫</span><span Courier New?;>BasicAction</span><span ?Courier>的父类，然后用一个接口来隔离</span><span Courier New?;>spring</span><span ?Courier>。由于</span>Action<span Times Roman?; ?Times New Courier New?;>BasicAction</span><span ?Courier>中，提高系统的可维护性。</span></p>
<h2><span style="font-size: 14pt; line-height: 173%">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>当BUS需要获取别的模块的数据的时候，不要直接去使用该模块的DAO</h2>
<p><span style="color: black; font-family: 宋体">我举一个简单的例子：我需要设计一个软件评审的管理软件，该软件分为评审组织者制订评审计划、评审者分别填写评审表后由评审组织者汇总评审表、评审组织者制作评审报告。这是一个非常简单的项目，分成了三个人来完成。但是项目进行快结束的时候却出现了问题。填写评审表需要获得评审计划中的一些数据，制作评审报告的数据来源于评审表。项目组在开始编程前先开了一次会，大家约定好了各个部分的数据格式及其规则，然后开始工作。然而数天后项目组把各个模块整合以后发现，系统根本跑不起来，为什么呢？设计评审计划的人发现，所有评审计划应当按照产品编号来进行管理而不是项目编号。由于这个变更，填写评审表模块在待评审列表中什么都无法显示；同样，设计评审表的人发现，在一个评审计划中评审表与评审者不是一对多的关系，而是一对一的关系，因而修改了这两个表的关联。因为这样，在制作评审报告时就不能正确得到评审表数据。其实一个软件项目在整个进行过程中总是不断变更。我们需要做的不是去抑制这些变更，而应当是通过软件的结构去适应这些变更，即是降低各模块间的依赖（耦合），提高内聚。</span></p>
<p><span style="color: black; font-family: 宋体">拿这个实例来说，当评审表需要调用评审计划的数据的时候，不应当是自己写一个</span><span Courier New?;>DAO</span><span ?Courier>去调用评审计划的数据，而应当是调用评审计划的接口，将这个任务交给评审计划类来完成。当评审报告需要调用评审表的数据的时候，同样应当去调用评审表的接口，由评审表来实现。同时，这种调用应当是去调用</span><span Courier New?;>BUS</span><span ?Courier>层的接口。为什么呢？比如在评审计划中的一个业务逻辑是只有在评审计划发布以后才能制作评审表，那么怎样才是已发布的评审计划呢？这个业务逻辑应当由谁来定义？当然是评审计划。在什么地方定义？当然是</span><span Courier New?;>BUS</span><span ?Courier>而不是</span><span Courier New?;>DAO</span><span ?Courier>，因为</span><span Courier New?;>DAO</span><span ?Courier>仅仅是实现数据的持久化，而</span><span Courier New?;>BUS</span><span ?Courier>才是实现业务逻辑的地方。既然如此，如果评审表去调用评审计划的</span><span Courier New?;>DAO</span><span ?Courier>，那么已发布评审计划的业务逻辑必然包含在了评审表的业务逻辑里了。我们假设有一天，已发布评审计划的业务逻辑发生变更了（实际上这样的会在你毫不经意间就发生了），编写评审计划的人会很快就修改了评审计划的业务实现并且测试通过了。他不知道评审表里也包含了这样的业务逻辑，因而修改后的程序在运行到评审表的时候就很可能会出错。不幸的是，在实际工作中，同样一个业务逻辑可能包含在无数个你可能知道，但你也可能不知道的代码中。这样的结构就是一个不易于维护的差的结构。</span></p>
<pre><span style="font-size: 16pt; line-height: 240%; font-family: 宋体"><strong>总结：从技术升级和需求变更两方面适应变化</strong></span></pre>
<p><span style="font-family: 宋体">软件开发专家</span>Alistair Cockburn<span Times Roman?; ?Times New Courier 宋体;? New?;?font-family:>相关链接：<a href="http://fangang.javaeye.com/blog/52883">回复：《<font size="2">如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件</font>》</a>。</span></p>
<div style="padding-right: 10px; border-top: gray 1px solid; padding-left: 10px; padding-bottom: 10px; margin: 15px 0px 0px 10px; padding-top: 10px">
<table cellspacing="0" cellpadding="2" width="95%" align="center" border="1">
    <tbody>
        <tr>
            <td style="background: #d1d7dc" align="center" width="100%" colspan="3"><strong>Spring-Hibernate.rar</strong></td>
        </tr>
        <tr>
            <td width="15%">&nbsp;描述:</td>
            <td width="75%">&nbsp; </td>
            <td align="center" width="10%" rowspan="4"><img alt="" src="http://fangang.javaeye.com/images/forum/icon_clip.gif" border="0" /><br />
            <a href="http://fangang.javaeye.com/topics/download/828d7ac5-1922-4104-aecb-0ee888c4e9a0"><strong>下载</strong></a> </td>
        </tr>
        <tr>
            <td width="15%">&nbsp;文件名:</td>
            <td width="75%">&nbsp;Spring-Hibernate.rar</td>
        </tr>
        <tr>
            <td width="15%">&nbsp;文件大小:</td>
            <td width="75%">&nbsp;9 KB</td>
        </tr>
        <tr>
            <td width="15%">&nbsp;下载过的:</td>
            <td width="75%">&nbsp;文件被下载或查看 511 次</td>
        </tr>
    </tbody>
</table>
</div>
<img src ="http://www.blogjava.net/i369/aggbug/152863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-15 09:39 <a href="http://www.blogjava.net/i369/articles/152863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]一个dwr+spring+hibernate的示例</title><link>http://www.blogjava.net/i369/articles/152861.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 15 Oct 2007 01:31:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/152861.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/152861.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/152861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/152861.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/152861.html</trackback:ping><description><![CDATA[<div style="margin-top: 1px; margin-left: 15px">
<h2><a title="永久链接：一个dwr+spring+hibernate的示例" href="http://fangang.javaeye.com/blog/120768">一个dwr+spring+hibernate的示例</a> </h2>
</div>
<div style="margin-top: 5px; margin-left: 15px"><strong>关键字:</strong> JavaScript &nbsp; spring,hibernate&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div style="margin-top: 10px; margin-left: 15px; overflow: auto">
<table width="100%">
    <tbody>
        <tr>
            <td>
            <p>这是一个运用dwr+spring+hibernate这样一个框架编写的示例。它展示了一下内容：</p>
            <p>1、在dwr中尝试编写的一些通用的代码，包括如何编写一个通用的列表显示框并实现分页、如何编写一个通用的单行编辑框、如何编辑一个通用的存盘和删除程序等等。</p>
            <p>2、在dwr中如何与spring兼容，调用bus中的方法；在dwr中如何与hibernate兼容，在页面端操作值对象，以及处理值对象间的各种关系。</p>
            <p>3、如何在spring中实现单dao，使这个单dao既可以与hibernate隔离，使其低耦合高内聚，提高可维护性，又能满足各个bus的业务需要，简化开发的过程。</p>
            <p>不是美工，界面比较外行，见谅了：）</p>
            <p>示例在MyEclipse中安装部署的步骤：</p>
            <p>1、创建一个新的web项目并拷贝示例中的文件到项目中。注意web.xml文件应当是将原文件覆盖。</p>
            <p>2、添加spring和hibernate。点击项目树中的项目名按Alt+Enter键，弹出项目属性对话框。选择&#8220;Java Build Path&#8221;中的&#8220;Libraries&#8221;标签，然后点击&#8220;Add Library&#8221;按钮，选择&#8220;MyEclipse Libraries&#8221;，点击&#8220;Next&#8221;，选择&#8220;Hibernate 3.0 Core Libraries&#8221;、&#8220;Spring 1.2 AOP Libraries&#8221;、&#8220;Spring 1.2&nbsp;Core Libraries&#8221;、&#8220;Spring 1.2&nbsp;ORM/DAO/Hibernate Libraries&#8221;、&#8220;Spring 1.2&nbsp;Web Libraries&#8221;，点击&#8220;Finish&#8221;按钮。</p>
            <p>3、点击&#8220;Add External JARs&#8221;按钮，添加dwr.jar、daosupport.jar、hxtg.jar、hibernate3(必须将hibernate3升级到3.2以上)以及其它数据库相关的jar包到项目中。添加完成以后记得重新部署应用服务器。</p>
            <p>4、创建数据库实例，如果是oracle，在pl/sql中运行示例中的employee.sql创建数据库对象。</p>
            <p>5、修改ApplicationContext-hibernate.xml中datasource的连接属性为你的数据库。部署完成！</p>
            <p>部署完成后运行可能会在部分功能中出错。这些问题的解决我会在《<a title="永久链接：DWR帮助说明－dwr的bug及其解决方法" href="http://fangang.javaeye.com/blog/122445">DWR帮助说明－dwr的bug及其解决方法</a>》中详细讨论。</p>
            <p>相关文档：</p>
            <p><a title="永久链接：如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件" href="http://fangang.javaeye.com/blog/47670">如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件</a> </p>
            <p><a title="永久链接：DWR帮助文档－dwr.xml文件的配置" href="http://fangang.javaeye.com/blog/119767">DWR帮助文档－dwr.xml文件的配置</a> </p>
            <p><a title="永久链接：DWR帮助说明－如何编写通用的列表显示框" href="http://fangang.javaeye.com/blog/119787">DWR帮助说明－如何编写通用的列表显示框</a> </p>
            <p><a title="永久链接：DWR帮助说明－如何编写通用的单行编辑框" href="http://fangang.javaeye.com/blog/119791">DWR帮助说明－如何编写通用的单行编辑框</a> </p>
            <p><a title="永久链接：DWR帮助说明－服务器端程序的编写" href="http://fangang.javaeye.com/blog/121954">DWR帮助说明－服务器端程序的编写</a> </p>
            <p><a title="永久链接：DWR帮助说明－dwr的bug及其解决方法" href="http://fangang.javaeye.com/blog/122445">DWR帮助说明－dwr的bug及其解决方法</a> </p>
            </td>
        </tr>
    </tbody>
</table>
<div style="padding-right: 10px; border-top: gray 1px solid; padding-left: 10px; padding-bottom: 10px; margin: 15px 0px 0px 10px; padding-top: 10px">
<table class="attach" cellspacing="0" cellpadding="2" width="95%" align="center" border="1">
    <tbody>
        <tr>
            <td class="attachrow" style="background: #d1d7dc" align="center" width="100%" colspan="3"><strong><span class="gen">employee.rar</span></strong></td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;描述:</span></td>
            <td class="attachrow" width="75%">&nbsp; </td>
            <td class="attachrow" align="center" width="10%" rowspan="4"><img alt="" src="http://fangang.javaeye.com/images/forum/icon_clip.gif" border="0" /><br />
            <a href="http://fangang.javaeye.com/topics/download/8b49cc76-21db-4b7e-9d9d-e5a6ab42f7cb"><strong>下载</strong></a> </td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;文件名:</span></td>
            <td class="attachrow" width="75%"><span class="genmed">&nbsp;employee.rar</span></td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;文件大小:</span></td>
            <td class="attachrow" width="75%"><span class="genmed">&nbsp;272 KB</span></td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;下载过的:</span></td>
            <td class="attachrow" width="75%"><span class="genmed">&nbsp;文件被下载或查看 236 次</span></td>
        </tr>
    </tbody>
</table>
</div>
<div style="padding-right: 10px; border-top: gray 1px solid; padding-left: 10px; padding-bottom: 10px; margin: 15px 0px 0px 10px; padding-top: 10px">
<table class="attach" cellspacing="0" cellpadding="2" width="95%" align="center" border="1">
    <tbody>
        <tr>
            <td class="attachrow" style="background: #d1d7dc" align="center" width="100%" colspan="3"><strong><span class="gen">employee.rar</span></strong></td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;描述:</span></td>
            <td class="attachrow" width="75%">&nbsp;重新修订了一下 </td>
            <td class="attachrow" align="center" width="10%" rowspan="4"><img alt="" src="http://fangang.javaeye.com/images/forum/icon_clip.gif" border="0" /><br />
            <a href="http://fangang.javaeye.com/topics/download/950ed5c6-01ea-4f19-8ebd-0a42f142a37e"><strong>下载</strong></a> </td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;文件名:</span></td>
            <td class="attachrow" width="75%"><span class="genmed">&nbsp;employee.rar</span></td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;文件大小:</span></td>
            <td class="attachrow" width="75%"><span class="genmed">&nbsp;2 M</span></td>
        </tr>
        <tr>
            <td class="attachrow" width="15%"><span class="genmed">&nbsp;下载过的:</span></td>
            <td class="attachrow" width="75%"><span class="genmed">&nbsp;文件被下载或查看 397 次</span></td>
        </tr>
    </tbody>
</table>
</div>
</div>
<img src ="http://www.blogjava.net/i369/aggbug/152861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-15 09:31 <a href="http://www.blogjava.net/i369/articles/152861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate 3 Annotations 进阶</title><link>http://www.blogjava.net/i369/articles/151028.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 08 Oct 2007 05:21:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/151028.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/151028.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/151028.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/151028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/151028.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Hibernate 3 Annotations 进阶kjj 发表于 2007-04-09 07:39:25作者:kjj&nbsp;&nbsp;&nbsp;&nbsp; 来源:Onjava;Matrix评论数:5 点击数:1,888&nbsp;&nbsp;&nbsp;&nbsp; 投票总得分:0 投票总人次:0关键字:Hibernate Annotations &nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/i369/articles/151028.html'>阅读全文</a><img src ="http://www.blogjava.net/i369/aggbug/151028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-08 13:21 <a href="http://www.blogjava.net/i369/articles/151028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate的一些知识与技巧 </title><link>http://www.blogjava.net/i369/articles/134645.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 06 Aug 2007 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/134645.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/134645.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/134645.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/134645.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/134645.html</trackback:ping><description><![CDATA[<p>1.两种配置文件： <br>&nbsp; A.hibernate.cfg.xml&nbsp;&nbsp; 和&nbsp;&nbsp; B.hibernate.properties</p>
<p>&nbsp; A中可含映射文件的配置，而B中hard codes加映射文件。</p>
<p>&nbsp; A。Configuration config=new Configuration().config();<br>&nbsp; B. Configuration config=new Configuration();<br>&nbsp;&nbsp;&nbsp;&nbsp; config.addClass(TUser.class);</p>
<p><br>2.你不必一定用hibernate.cfg.xml或hibernate.properties这两文件名，<br>&nbsp;&nbsp; 你也不一定非得把配置文件放在Classes下，<br>&nbsp;&nbsp; File file=new File("c:\\sample\\myhibernate.xml");<br>&nbsp;&nbsp; Configuration config=new Configuration().config(file);</p>
<p>3. session.Flush()<br>&nbsp;&nbsp; 强制数据库立即同步，当用事务时，不必用flush,事务提交自动调用flush<br>&nbsp;&nbsp; 在session关闭时也会调用flush</p>
<p><br>4. Hibernate总是使用对象类型作为字段类型</p>
<p>5. XDoclet专门建立了hibernate doclet,就是在java代码上加上一些<br>&nbsp;&nbsp; java docTag，后来再让XDoclet分析该java代码，生成映射文件;</p>
<p>6.HQL子句本身大小写无关，但是其中出现的类名和属性名必须注意大小写区分。</p>
<p>7.关系：<br>&nbsp; Constrained : 约束，表明主控表的主键上是否存在一个外键（foreigh key）<br>&nbsp;&nbsp; 对其进行约束。</p>
<p>&nbsp; property-ref:关联类中用于与主控类相关联的属性名，默认为关联类的主键属性名</p>
<p>&nbsp; 单向一对多需在一方配置，双向一对多需在双方进行配置</p>
<p>8.lazy=false:被动方的记录由hibernate负责记取，之后存放在主控方指定的<br>&nbsp; Collection类型属性中</p>
<p>9. java.util.Set或net.sof.hibernate.collecton.Bag类型的Collection</p>
<p><br>10.重要：inverse:用于标识双向关联中的被动方一端。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inverse=false的一方（主控方）负责维护关联关系.默认值：false</p>
<p>11.batch-size:采用延迟加载特征时，一次读入的数据数昨。</p>
<p>12.一对多通过主控方更新（主控方为一方时）</p>
<p>&nbsp;&nbsp; user.getAddresses().add(addr);<br>&nbsp;&nbsp; session.save(user);//通过主控对象级联更新 &nbsp;</p>
<p>13.在one-to-many 关系中，将many 一方设为主动方（inverse=false）将有助性能<br>&nbsp;&nbsp; 的改善。在一方设置关系时，inverse=true,即将主控权交给多方，<br>&nbsp;&nbsp; 这样多方可主动从一方获得foreign key,然后一次insert即可完工。</p>
<p><br>&nbsp;&nbsp; addr.setUser(user);//设置关联的TUser对象<br>&nbsp;&nbsp; user.getAddresses().add(addr);<br>&nbsp;&nbsp; session.save(user);//级联更新&nbsp;</p>
<p>14.只有设为主控方的一方才关心（访问）对方的属性，被动方是不关心对方的属性的。</p>
<p>15.one-to-many与many-to-one节点的配置属性不同：<br>&nbsp;&nbsp; 一对多关系多了lazy和inverse两个属性<br>&nbsp;&nbsp; 多对多节点属性：column:中间映射表中，关联目标表的关联字段<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class:类名，关联目标类<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outer-join:是否使用外联接&nbsp;&nbsp; &nbsp;</p>
<p>&nbsp;&nbsp; 注意:access是设置属性值的读取方式。</p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column是设置关联字段。</p>
<p><br>16.多对多，注意两方都要设置inverse和lazy,cascade只能设为insert-update<br>&nbsp;&nbsp; 多对多关系中，由于关联关系是两张表相互引用，因此在保存关系状态时必须对双方同时保存。</p>
<p>&nbsp;&nbsp; group1.getRoles().add(role1);<br>&nbsp;&nbsp; role1.getGroups().add(group1);</p>
<p>&nbsp;&nbsp; session.save(role1);<br>&nbsp;&nbsp; session.save(group1);</p>
<p>17.关于vo和po<br>&nbsp;&nbsp; vo经过hibernate容量处理，就变成了po(该vo的引用将被容器保存，并且在session关闭时flush,因此po如果再传到其它地方改变了，就危险了)<br>&nbsp;<br>&nbsp;&nbsp; vo和po相互转换：BeanUtils.copyProperties(anotherUser,user);</p>
<p>18.对于save操作而言，如果对象已经与Session相关联（即已经被加入Session的实体容器中），则无需进行具体的操作。因为之后的Session.flush过程中，Hibernate<br>会对此实体容器中的对象进行遍历，查找出发生变化的实体，生成并执行相应的update<br>语句。</p>
<p>19.如果我们采用了延迟加载机制，但希望在一些情况下，实现非延迟加<br>载时的功能，也就是说，我们希望在Session关闭后，依然允许操作user的addresses<br>属性<br>Hibernate.initialize方法可以通过强制加载关联对象实现这一功能：<br>这也正是我们为什么在编写POJO时，必须用JDK Collection接口（如Set,Map）,<br>而非特定的JDK Collection实现类（如HashSet、HashMap）申明Collection属性的<br>原因。</p>
<p>20.事务：从sessionFactory获得session,其自动提交属性就已经关闭(AutoCommit=false),此时若执行了jdbc操作，如果不显式调用session.BeginTransaction(),是不会执行事务操作的。</p>
<p>&nbsp;&nbsp; jdbc transaction:基于同一个session(就是同一个connection)的事务;<br>&nbsp;&nbsp; jta&nbsp; transaction:跨session（跨connection）事务.</p>
<p>&nbsp;&nbsp; 对于jta事务，有三种实现方法：<br>&nbsp;&nbsp;&nbsp;&nbsp; A。UserTransaction tx=new InitialContext().lookup("...");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx.commit();<br>&nbsp;&nbsp;&nbsp;&nbsp; B. 使用hibernate封装的方法：(不推荐)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transaction tx=session.beginTransaction();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx.commit();<br>&nbsp;&nbsp;&nbsp;&nbsp; C. 使用ejb之sessionBean的事务技持方法，你只要在把需要在发布描述符中，把需要jta事务的方法声明为require即可</p>
<p>21.悲观锁，乐观锁：<br>&nbsp;&nbsp; 乐观锁一般通过version来实现，注意version节点必须出现在id后。</p>
<p><br>22.Hibernate中，可以通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围。<br>&nbsp;&nbsp; Query接口中也提供了与其一致的方法，hibernate主要在dialect类中实现在这个功能。</p>
<p><br>23.cache<br>&nbsp;&nbsp; &lt;hibernate-configuration&gt;<br>&nbsp;&lt;session-factory&gt;<br>&nbsp;&#8230;&#8230;<br>&nbsp;&nbsp;&lt;property name="hibernate.cache.provider_class"&gt;<br>&nbsp;&nbsp;&nbsp;net.sf.ehcache.hibernate.Provider<br>&nbsp;&nbsp;&lt;/property&gt;&nbsp;</p>
<p>&nbsp; 还需对ecache本身进配置<br>&nbsp; &lt;ehcache&gt;<br>&nbsp;&lt;diskStore path="java.io.tmpdir"/&gt;<br>&nbsp;&lt;defaultCache<br>&nbsp;maxElementsInMemory="10000" //Cache中最大允许保存的数据数量<br>&nbsp;eternal="false" //Cache中数据是否为常量<br>&nbsp;timeToIdleSeconds="120" //缓存数据钝化时间<br>&nbsp;timeToLiveSeconds="120" //缓存数据的生存时间<br>&nbsp;overflowToDisk="true" //内存不足时，是否启用磁盘缓存<br>&nbsp;/&gt;<br>&nbsp; &lt;/ehcache&gt;</p>
<p>&nbsp; 之后在映射文件中指定各个映射实体的cache策略<br>&nbsp; &lt;class name=" org.hibernate.sample.TUser" .... &gt;<br>&nbsp;&lt;cache usage="read-write"/&gt;<br>&nbsp;....<br>&nbsp;&lt;set name="addresses" .... &gt;<br>&nbsp;&nbsp;&lt;cache usage="read-only"/&gt;<br>&nbsp;....<br>&nbsp;&lt;/set&gt;<br>&nbsp;&lt;/class&gt;</p>
<p>&nbsp;*****************************************************<br>&nbsp;Query.list()跟Query.iterate()的不同：<br>&nbsp;对于query.list()总是通过一条sql语句获取所有记录,然后将其读出，填入pojo返回;<br>&nbsp;但是query.iterate()，则是首先通过一条Select SQL 获取所有符合查询条件的记录的<br>id，再对这个id 集合进行循环操作，通过单独的Select SQL 取出每个id 所对应的记<br>录，之后填入POJO中返回。</p>
<p>&nbsp;也就是说，对于list 操作，需要一条SQL 完成。而对于iterate 操作，需要n+1<br>条SQL。，list方法将不会从Cache中读取数据。iterator却会。</p>
<p><br>24.ThreadLocal:它会为每个线程维护一个私有的变量空间。实际上，<br>其实现原理是在JVM 中维护一个Map，这个Map的key 就是当前的线程对象，而value则是<br>线程通过ThreadLocal.set方法保存的对象实例。当线程调用ThreadLocal.get方法时，<br>ThreadLocal会根据当前线程对象的引用，取出Map中对应的对象返回。</p>
<p>&nbsp;这样，ThreadLocal通过以各个线程对象的引用作为区分，从而将不同线程的变量隔离开<br>来。</p>
<p><br>25.Hibernate官方开发手册标准示例:<br>&nbsp; public class HibernateUtil {<br>private static SessionFactory sessionFactory;<br>static {<br>try {<br>// Create the SessionFactory<br>sessionFactory = new<br>Configuration().configure().buildSessionFactory();<br>} catch (HibernateException ex) {<br>throw new RuntimeException(<br>"Configuration problem: " + ex.getMessage(),<br>ex<br>);<br>}<br>}<br>public static final ThreadLocal session = new ThreadLocal();<br>public static Session currentSession() throws HibernateException<br>{<br>Session s = (Session) session.get();<br>// Open a new Session, if this Thread has none yet<br>if (s == null) {<br>s = sessionFactory.openSession();<br>session.set(s);<br>}<br>return s;<br>}<br>public static void closeSession() throws HibernateException {<br>Session s = (Session) session.get();<br>session.set(null);<br>if (s != null)<br>s.close();<br>}<br>}&nbsp;</p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp; <br>26.通过filter实现session的重用：<br>&nbsp;&nbsp; public class PersistenceFilter implements Filter<br>{<br>protected static ThreadLocal hibernateHolder = new ThreadLocal();<br>public void doFilter(ServletRequest request, ServletResponse<br>response, FilterChain chain)<br>throws IOException, ServletException<br>{<br>hibernateHolder.set(getSession());<br>try<br>{<br>&#8230;&#8230;<br>chain.doFilter(request, response);<br>&#8230;&#8230;<br>}<br>finally<br>{<br>Session sess = (Session)hibernateHolder.get();<br>if (sess != null)<br>{<br>hibernateHolder.set(null);<br>try<br>{<br>sess.close();<br>}<br>catch (HibernateException ex) {<br>throw new ServletException(ex);<br>}<br>}<br>}<br>}<br>&#8230;&#8230;}</p>
<p>27.Spring的参数化事务管理功能相当强大，笔者建议在基于Spring Framework的应用<br>开发中，尽量使用容器管理事务，以获得数据逻辑代码的最佳可读性。<br>&nbsp;<br>public class UserDAO extends HibernateDaoSupport implements IUserDAO<br>{<br>public void insertUser(User user) {<br>getHibernateTemplate().saveOrUpdate(user);<br>}<br>}</p>
<p><br>&nbsp; 上面的UserDAO实现了自定义的IUserDAO接口，并扩展了抽象类：<br>HibernateDaoSupport<br>HibernateSupport实现了HibernateTemplate和SessionFactory实例的关联。<br>HibernateTemplate对Hibernate Session操作进行了封装，而<br>HibernateTemplate.execute方法则是一封装机制的核心 </p>
<p>&nbsp; *在spring的配置文件里，移植了整个hibernate.cfg.xml的内容。</p>
<br><br>
<p id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=288115</p>
<img src ="http://www.blogjava.net/i369/aggbug/134645.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-08-06 11:05 <a href="http://www.blogjava.net/i369/articles/134645.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibenate中多对多关系中常见问题 </title><link>http://www.blogjava.net/i369/articles/134624.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 06 Aug 2007 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/134624.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/134624.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/134624.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/134624.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/134624.html</trackback:ping><description><![CDATA[<ol>
    <li><strong>到底在哪用cascade="..."？<br></strong>cascade属性并不是多对多关系一定要用的，有了它只是让我们在插入或删除对像时更方便一些，只要在cascade的源头上插入或是删除，所有cascade的关系就会被自己动的插入或是删除。便是为了能正确的cascade，unsaved-value是个很重要的属性。Hibernate通过这个属性来判断一个对象应该save还是update，如果这个对象的id是unsaved-value的话，那说明这个对象不是persistence object要save（insert)；如果id是非unsaved-value的话，那说明这个对象是persistence object（数据库中已存在），只要update就行了。saveOrUpdate方法用的也是这个机制。
    <li><strong>到底在哪用inverse="ture"?<br></strong>inverse属性默认是false的，就是说关系的两端都来维护关系。这个意思就是说，如有一个Student, Teacher和TeacherStudent表，Student和Teacher是多对多对多关系，这个关系由TeacherStudent这个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来维护关系呢？在用hibernate时，我们不会显示的对TeacherStudent表做操作。对TeacherStudent的操作是hibernate帮我们做的。hibernate就是看hbm文件中指定的是"谁"维护关系，那个在插入或删除"谁"时，就会处发对关系表的操作。前提是"谁"这个对象已经知道这个关系了，就是说关系另一头的对象已经set或是add到"谁"这个对象里来了。前面说过inverse默认是false，就是关系的两端都维护关系，对其中任一个操作都会处发对表系表的操作。当在关系的一头，如Student中的bag或set中用了inverse＝"true"时，那就代表关系是由另一关维护的（Teacher）。就是说当这插入Student时，不会操作TeacherStudent表，即使Student已经知道了关系。只有当Teacher插入或删除时才会处发对关系表的操作。所以，当关系的两头都用inverse="true"是不对的，就会导致任何操作都不处发对关系表的操作。当两端都是inverse="false"或是default值是，在代码对关系显示的维护也是不对的，会导致在关系表中插入两次关系。<br>在一对多关系中inverse就更有意义了。在多对多中，在哪端inverse="true"效果差不多（在效率上）。但是在一对多中，如果要一方维护关系，就会使在插入或是删除"一"方时去update"多"方的每一个与这个"一"的对象有关系的对象。而如果让"多"方面维护关系时就不会有update操作，因为关系就是在多方的对象中的，直指插入或是删除多方对象就行了。当然这时也要遍历"多"方的每一个对象显示的操作修关系的变化体现到DB中。不管怎样说，还是让"多"方维护关系更直观一些。
    <li><strong>cascade和inverse有什么区别？<br></strong>可以这样理解，cascade定义的是关系两端对象到对象的级联关系；而inverse定义的是关系和对象的级联关系。
    <li><strong>net.sf.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): 2, of class: Xxxxx<br></strong>这个问题出现在要删除关系的一头时。如，要删除一个已经和Student有关系的Teacher。当tx.commit();时才会抛出这个异常。这时一个在关系另一头的Student对象中的Set或是List中把这个Teacher对象显示的remove掉，再session.delete(这个teacher);。这是为了防止在Student端有cascade时把这个Teacher对象再存回DB。所以，这个异常的只有在Student的关系定义中有cascade="..."，而且没有像上面说的显示的解除关系时才会出现。所以防止出现这个异常的方法就是：1，在Student端不用cascade；2，或是用cascade的话，就显示的删除对像中的关系。
    <li><strong>net.sf.hibernate.HibernateException: identifier of an instance of my.MyObject altered from&nbsp;N to N<br></strong>这个异常其时不是多对多中常遇到的，但是这个异常的提示不make sense，所以提一下，是因为id的java对象中的type和hbm文件中定义的不一样，如：java中用long，而hbm中用type="integer"，并且generator用的是identity时就会出现
    <li>(To be add) 把hibernate遇到常见异常会一点点加上来的</li>
</ol>
<img src ="http://www.blogjava.net/i369/aggbug/134624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-08-06 10:36 <a href="http://www.blogjava.net/i369/articles/134624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己实现ORM </title><link>http://www.blogjava.net/i369/articles/112003.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Thu, 19 Apr 2007 09:40:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/112003.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/112003.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/112003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/112003.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/112003.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这篇文章源自刚开发的一个小项目。项目中并未使用hibernate，但我还是要把它放在hibernate栏下。理由很简单，技术是死的，而人是活的，能熟练的使用一项技术不算什么，但能恰当的选择相应的技术，甚至自己想出办法来优雅的解决实际问题，就需要一定的积累了。而这种积累就来源自项目实践和对各种技术其实质的理解。我记得在某个论坛上某人（名字忘了）说过一句话：如果学习hibernate只是学会了怎么ma...&nbsp;&nbsp;<a href='http://www.blogjava.net/i369/articles/112003.html'>阅读全文</a><img src ="http://www.blogjava.net/i369/aggbug/112003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-04-19 17:40 <a href="http://www.blogjava.net/i369/articles/112003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用open source产品组装你的web应用架构[转贴，只作为收藏，非本人原创] </title><link>http://www.blogjava.net/i369/articles/111363.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Tue, 17 Apr 2007 09:37:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/111363.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/111363.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/111363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/111363.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/111363.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 其实，就算用Java建造一个不是很烦琐的web应用，也不是件轻松的事情。 在构架的一开始就有很多事情要考虑。 从高处看，摆在开发者面前有很多问题：要考虑是怎样建立用户接口？在哪里处理业务逻辑？ 怎样持久化的数据。 而这三层构架中，每一层都有他们要仔细考虑的。 各个层该使用什么技术？ 怎样的设计能松散耦合还能灵活改变？ 怎样替换某个层而不影响整体构架？应用程序如何做各种级别的业务处理（比如事务处理）...&nbsp;&nbsp;<a href='http://www.blogjava.net/i369/articles/111363.html'>阅读全文</a><img src ="http://www.blogjava.net/i369/aggbug/111363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-04-17 17:37 <a href="http://www.blogjava.net/i369/articles/111363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]使用open source产品组装你的web应用架构(struts+spring+hibernate) </title><link>http://www.blogjava.net/i369/articles/101116.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Wed, 28 Feb 2007 04:53:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/101116.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/101116.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/101116.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/101116.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/101116.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td width="100%">
										<p>
												<span class="postdetails">
														<font size="2">本文是</font>我在<span class="maintitle">SpringFramework中文论坛</span>上看到的一篇文章，感觉不错，所以就收藏到Blog上</span>
										</p>
										<p>
												<span class="postdetails">原文地址：<a href="http://spring.jactiongroup.net/viewtopic.php?t=389">http://spring.jactiongroup.net/viewtopic.php?t=389</a></span>
										</p>
										<p>
												<span class="postdetails">
														<font size="2">
														</font>
												</span>
										</p>
								</td>
								<td valign="top" nowrap="">
										<a href="http://spring.jactiongroup.net/posting.php?mode=quote&amp;p=1879&amp;sid=21a15e43c9d628b4ae59578406ab1cdc">
												<font size="2">
												</font>
										</a> </td>
						</tr>
						<tr>
								<td colspan="2">
										<hr />
								</td>
						</tr>
						<tr>
								<td colspan="2">
										<span class="postbody">其实，就算用Java建造一个不是很烦琐的web应用，也不是件轻松的事情。 在构架的一开始就有很多事情要考虑。 从高处看，摆在开发者面前有很多问题：要考虑是怎样建立用户接口？在哪里处理业务逻辑？ 怎样持久化的数据。 而这三层构架中，每一层都有他们要仔细考虑的。 各个层该使用什么技术？ 怎样的设计能松散耦合还能灵活改变？ 怎样替换某个层而不影响整体构架？应用程序如何做各种级别的业务处理（比如事务处理）？ <br /><br /><br /><br />构架一个Web应用需要弄明白好多问题。 幸运的是，已经有不少开发者已经遇到过这类问题，并且建立了处理这类问题的框架。 一个好框架具备以下几点： 减轻开发者处理复杂的问题的负担（“不重复发明轮子”）； 内部有良好的扩展； 并且有一个支持它的强大的用户团体。 好的构架一般有针对性的处理某一类问题，并且能将它做好（Do One Thing well）。 然而，你的程序中有几个层可能需要使用特定的框架，已经完成的UI(用户接口) 并不代表你也可以把你的业务逻辑和持久逻辑偶合到你的UI部分。 举个例子， 你不该在一个Controller(控制器)里面写JDBC代码作为你的业务逻辑， 这不是控制器应该提供的。 一个UI 控制器应该委派给其它给在UI范围之外的轻量级组件。 好的框架应该能指导代码如何分布。 更重要的是，框架能把开发者从编码中解放出来，使他们能专心于应用程序的逻辑（这对客户来说很重要）。 <br /><br /><br /><br />这篇文章将讨论怎样结合几种著名的框架来使得你的应用程序做到松弛耦合。 <br /><br />如何建立你的架构，并且怎样让你的各个应用层保持一致。？如何整合框架以便让每个层在以一种松散偶合的方式彼此作用而不用管低层的技术细节？这对我们来说真是一种挑战。 这里讨论一个整合框架的策略( 使用3 种受欢迎的开源框架) ：表示层我们用Struts； 业务层我们用Spring；而持久层则用Hibernate。 你也可以用其他FrameWork替换只要能得到同样的效果。 见图1 （框架组合示意图） <br /><br /><img alt="" src="http://www.onjava.com/onjava/2004/04/07/graphics/wiring.gif" border="0" /><br /><br /><span style="FONT-WEIGHT: bold">应用程序的分层</span><br /><br />大部分的Web应用在职责上至少能被分成4层。 这四层是：presentation（描述），persistence（持久），business（业务）和domain model（域模块）。每个层在处理程序上都应该有一项明确的责任, 而不应该在功能上与其它层混合，并且每个层要与其它层分开的，但要给他们之间放一个通信接口。 我们就从介绍各个层开始，讨论一下这些层应该提供什么，不应该提供什么。 <br /><br /><br /><br /><span style="FONT-WEIGHT: bold">表示层(The Presentation Layer) </span><br /><br />一般来讲，一个典型的Web应用的的末端应该是表示层。 很多Java发者也理解Struts所提供的。 象业务逻辑之类的被打包到org.apache.struts.Action.， 因此，我们很赞成使用Struts这样的框架。 <br /><br /><br /><br />下面是Struts所负责的： <br /><br />* 管理用户的请求,做出相应的响应。 <br /><br />* 提供一个Controller ,委派调用业务逻辑和其它上层处理。 <br /><br />* 处理异常，抛给Struts Action <br /><br />* 为显示提供一个模型 <br /><br />* UI验证。 <br /><br /><br /><br />以下条款，不该在Struts显示层的编码中经常出现。 它们与显示层无关的。 <br /><br />* 直接的与数据库通信，例如JDBC调用。 <br /><br />* 与你应用程序相关联的业务逻辑以及校验。 <br /><br />* 事物管理。 <br /><br />在表示层引入这些代码，则会带来高偶合和麻烦的维护。 <br /><br /><br /><br /><br /><br /><span style="FONT-WEIGHT: bold">持久层(The Persistence Layer)</span><br /><br />典型的Web应用的另一个末端是持久层。这里通常是程序最容易失控的地方。开发者总是低估构建他们自己的持久框架的挑战性。系统内部的持续层不但需要大量调试时间，而且还经常缺少功能使之变得难以控制，这是持久层的通病。 还好有几个ORM开源框架很好的解决了这类问题。尤其是Hibernate。 Hibernate为java提供了OR持久化机制和查询服务, 它还给已经熟悉SQL和JDBC API 的Java开发者一个学习桥梁，他们学习起来很方便。 Hibernate的持久对象是基于POJO和Java collections。此外，使用Hibernate并不妨碍你正在使用的IDE。 <br /><br /><br /><br />请看下面的条目，你在持久层编码中需要了解的。 <br /><br />* 查询对象的相关信息的语句。 Hibernate通过一个OO查询语言（HQL）或者正则表达的API来完成查询。 HQL非常类似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。 你需要学习一些新的HQL语言； 不管怎样，他们容易理解而文档也做的很好。 HQL是一种对象查询的自然语言，花很小的代价就能学习它。 <br /><br />* 如何存储，更新，删除数据库记录。 <br /><br />* 象Hibernate这类的高级ORM框架支持大部分主流数据库，并且他们支持 Parent/child关系，事物处理，继承和多态。 <br /><br /><br /><br /><span style="FONT-WEIGHT: bold">业务层（The Business Layer）</span><br /><br />一个典型Web应用的中间部分是业务层或者服务层。 从编码的视角来看，这层是最容易被忽视的一层。 而我们却往往在UI层或持久层周围看到这些业务处理的代码，这其实是不正确的，因为它导致了程序代码的紧密偶合，这样一来，随着时间推移这些代码很难维护。幸好，针对这一问题有好几种Frameworks存在。 最受欢迎的两个框架是Spring和PicoContainer。 这些为也被称为microcontainers，他们能让你很好的把对象搭配起来。 这两个框架都着手于‘依赖注射’(dependency injection)(还有我们知道的‘控制反转’Inversion of Control=IoC)这样的简单概念。 这篇文章将关注于Spring的注射（译注：通过一个给定参数的Setter方法来构造Bean,有所不同于Factory）, Spring还提供了Setter Injection(type2)，Constructor Injection(type3)等方式供我们选择。 Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handler（事物管理控制）、Object Factoris(对象工厂)、service objects（服务组件）——都通过XML来配置联系起来。 <br /><br /><br /><br />后面我们会举个例子来揭示一下Spring 是怎样运用这些概念。 <br /><br />业务层所负责的如下： <br /><br />* 处理应用程序的 业务逻辑和业务校验 <br /><br />* 管理事物 <br /><br />* 允许与其它层相互作用的接口 <br /><br />* 管理业务层级别的对象的依赖。 <br /><br />* 在显示层和持久层之间增加了一个灵活的机制，使得他们不直接的联系在一起。 <br /><br />* 通过揭示 从显示层到业务层之间的Context来得到business services。 <br /><br />* 管理程序的执行（从业务层到持久层）。 <br /><br /><br /><br /><br /><br /><span style="FONT-WEIGHT: bold">域模块层（The Domain Model Layer ）</span><br />既然我们致力于的是一个不是很复杂的Web的应用， 我们需要一个对象集合，让它在不同层之间移动的。 域模块层由实际需求中的业务对象组成 比如, OrderLineItem , Product等等。 开发者在这层 不用管那些DTOs，仅关注domain object即可。 例如，Hibernate允许你将数据库中的信息存放入对象（domain objects），这样你可以在连接断开的情况下把这些数据显示到UI层。 而那些对象也可以返回给持续层，从而在数据库里更新。 而且，你不必把对象转化成DTOs（这可能似的它在不同层之间的在传输过程中丢失），这个模型使得Java开发者能很自然运用OO，而不需要附加的编码。 <br /><br />一个简单例子 <br /><br /><br /><br />既然我们已经从全局上理解这些组件。 现在就让我们开始实践吧。 我们还是用 Struts，Spring 和Hibernate。这三个框架已经被描述够多了，这里就不重复介绍了。 这篇文章举例指导你如何使用这三个框架整合开发, 并向你揭示 一个请求是如何贯穿于各个层的。（从用户的加入一个Order到数据库，显示；进而更新、删除）。 <br /><br /><br /><br />从这里可以下载到程序程序原代码（<a class="postlink" href="http://www.onjava.com/onjava/2004/04/07/examples/wiring.zip" target="_blank"><font color="#5493b4">download</font></a>） <br /><br />既然每个层是互相作用的，我们就先来创建domain objects。首先，我们要在这些Object中要确定那些是需要持久化的，哪些是提供给business logic，那些是显示接口的设计。 下一步，我们将配置我们的持久层并且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后，我们将 使用Spring把这些连接起来。 最后，我们提供给Spring一个持久层，从这个持久层里我们可以知道它是如何与业务逻辑层（business service layer）通信的，以及它是怎样处理其他层抛出的异常的。。 <br /><br /><br /><br /><span style="FONT-WEIGHT: bold">域对象层（Domain Object Layer）</span><br /><br /><br />这层是编码的着手点，我们的编码就从这层开始。 例子中Order 与OrderItem 是一个One—To—Many的关系。 下面就是Domain Object Layer的两个对象： <br /><br /><br /><br />· com.meagle.bo.Order.java: 包含了一个Order的概要信息 <br /><br />· com.meagle.bo.OrderLineItem.java: 包含了Order的详细信息 <br /><br />好好考虑怎你的package命名,这反应出了你是怎样分层的。 例如 domain objects在程序中可能打包在com.meagle.bo内。 更详细一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包，而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions的 持久对象（presentation classes） 应该分别放在 com.meagle.action和com.meagle.forms包。 准确的给包命名使得你的classes很好分割并且易于维护，并且在你添加新的classes时，能使得程序结构上保持上下一致。 <br /><br /><span style="FONT-WEIGHT: bold">持久层的配置（Persistence Layer Configuration）</span><br /><br />建立Hibernate的持久层 需要好几个步骤。 第一步让我们把BO持久化。 既然Hibernate是通过POJO工作的， 因此Order和 OrderLineItem对象需要给所有的fileds 加上getter,setter方法。 Hibernate通过XML文件来映射(OR)对象，以下两个xml文件分别映射了Order 和OrderItem对象。（这里有个叫XDoclet工具可以自动生成你的XML影射文件） <br /><br />- Order.hbm.xml <br />- OrderLineItem.hbm.xml <br /><br />你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文件。Hibernate的 [urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程序 应该与哪个数据库通信，该使用哪个连接池或使用了DataSource， 应该加载哪些持久对象。而<a class="postlink" href="http://www.hibernate.org/hib_docs/api/net/sf/hibernate/Session.html" target="_blank"><font color="#006699">Session</font></a>接口是用来完成Selecting，Saving，Delete和Updating这些操作。 后面的我们将讲述SessionFactory和Session是怎样设置的。 <br /><br /><span style="FONT-WEIGHT: bold">业务层的配置（Business Layer Configuration）</span><br /><br />既然我们已经有了domain objects，接下来我们就要business service objects了，用他们来执行程序的logic,调用持久层，得到UI层的requests,处理transactions，并且控制exceptions。 为了将这些连接起来并且易于管理，我们将使用面向方面的 SpringFramework。 Spring 提供了 控制倒置（inversion of control 0==IoC)和注射依赖设置（setter dependency injection）这些方式（可供选择），用XML文件将对象连接起来。 IoC是一个简单概念（它允许一个对象在上层接受其他对象的创建），用IoC这种方式让你的对象从创建中释放了出来，降低了偶合度。 <br /><br /><br /><br /><br />这里是一个没有使用IoC的对象创建的例子，它有很高偶合度。 <br /><br /><br /><img alt="" src="http://www.onjava.com/onjava/2004/04/07/graphics/nonioc.gif" border="0" /><br /><br /><span style="FONT-STYLE: italic">图 2.没有使用 IoC. A 创建了 B 和 C</span><br /><br />而这里是一个使用IoC的例子，这种方式允许对象在高层可以创建并进入另外一个对象，所以这样可以直接被执行。 <br /><img alt="" src="http://www.onjava.com/onjava/2004/04/07/graphics/ioc.gif" border="0" /><br /><br /><span style="FONT-STYLE: italic">图 3. 对象使用了 IoC。 A 包含了接受B,C的 setter方法 , 这同样达到了 由A创建B,C的目的。</span><br /><br />建立我们的业务服务对象（Building Our Business Service Objects） <br /><br /><br />Business Object中的Setter方法接受的是接口，这样我们可以很松散的定义对象实现，然后注入。 在我们的案例中，我们将用一个business service object接收一个DAO,用它来控制domain objects的持久化。 由于在这个例子中使用了Hibernate，我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了。 <br /><br />在面向接口的编程中，你会明白 “注射依赖”模式是怎样松散耦合你的业务逻辑和持久机制的：）。 <br /><br /><br /><br />下面是一个接口business service object，DAO代码片段： <br /><br /><br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">
																		<br />public interface IOrderService { <br /><br />  public abstract Order saveNewOrder(Order order) <br /><br />    throws OrderException, <br /><br />           OrderMinimumAmountException; <br /><br />  <br /><br />  public abstract List findOrderByUser( <br /><br />                                     String user) <br /><br />                           throws OrderException; <br /><br />  <br /><br />  public abstract Order findOrderById(int id) <br /><br />                           throws OrderException; <br /><br />  <br /><br />  public abstract void setOrderDAO( <br /><br />                             IOrderDAO orderDAO); <br /><br />} <br /><br /> </td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />注意到这段代码里有一个 setOrderDao（），它就是一个DAO Object设置方法（注射器）。 但这里并没有一个getOrderDao的方法，这不必要，因为你并不会在外部访问这个orderDao。这个DAO Objecte将被调用，和我们的persistence layer 通信。我们将用Spring把DAO Object 和 business service object搭配起来的。因为我们是面向接口编程的，所以并不需要将实现类紧密的耦合在一起。 <br /><br /><br /><br />接下去我们开始我们的DAO的实现类进行编码。 既然Spring已经有对Hibernate的支持，那这个例子就直接继承<a class="postlink" href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/support/HibernateDaoSupport.html" target="_blank"><font color="#006699">HibernateDaoSupport</font></a>类了，这个类很有用，我们可以参考<a class="postlink" href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/HibernateTemplate.html" target="_blank"><font color="#006699">HibernateTemplate</font></a>（它主要是针对HibernateDaoSupport的一个用法，译注：具体可以查看<a class="postlink" href="http://www.springframework.org/docs/api/index.html" target="_blank"><font color="#006699">Srping 的API</font></a>）。 下面是这个DAO接口代码： <br /><br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">public interface IOrderDAO { <br />  public abstract Order findOrderById( <br />                                    final int id); <br />  <br />  public abstract List findOrdersPlaceByUser( <br />                           final String placedBy); <br />  public abstract Order saveOrder( <br />                               final Order order); <br />}</td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />
												<br />我们仍然要给我们持久层组装很多关联的对象，这里包含了HibernateSessionFactory 和TransactionManager。 Spring 提供了一个 <a class="postlink" href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/HibernateTransactionManager.html" target="_blank"><font color="#006699">HibernateTransactionManager</font></a>，他用线程捆绑了一个Hibernate Session，用它来支持transactions(请查看<a class="postlink" href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html" target="_blank"><font color="#006699">ThreadLocal</font></a>) 。 <br /><br />下面是HibernateSessionFactory 和 HibernateTransactionManager:的配置： <br /><br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">&lt;bean id="mySessionFactory" <br />       class="org.springframework.orm.hibernate. <br />              LocalSessionFactoryBean"&gt; <br />  &lt;property name="mappingResources"&gt; <br />    &lt;list&gt; <br />      &lt;value&gt; <br />        com/meagle/bo/Order.hbm.xml <br />      &lt;/value&gt; <br />      &lt;value&gt; <br />        com/meagle/bo/OrderLineItem.hbm.xml <br />      &lt;/value&gt; <br />    &lt;/list&gt; <br />  &lt;/property&gt; <br />  &lt;property name="hibernateProperties"&gt; <br />    &lt;props&gt; <br />      &lt;prop key="hibernate.dialect"&gt; <br />        net.sf.hibernate.dialect.MySQLDialect <br />      &lt;/prop&gt; <br />      &lt;prop key="hibernate.show_sql"&gt; <br />        false <br />      &lt;/prop&gt; <br />      &lt;prop key="hibernate.proxool.xml"&gt; <br />        C:/MyWebApps/.../WEB-INF/proxool.xml <br />      &lt;/prop&gt; <br />      &lt;prop key="hibernate.proxool.pool_alias"&gt; <br />          spring <br />      &lt;/prop&gt; <br />    &lt;/props&gt; <br />  &lt;/property&gt; <br />&lt;/bean&gt; <br />  <br />&lt;!-- Transaction manager for a single Hibernate <br />SessionFactory (alternative to JTA) --&gt; <br />&lt;bean id="myTransactionManager" <br />         class="org. <br />                springframework. <br />                orm. <br />                hibernate. <br />                HibernateTransactionManager"&gt; <br />  &lt;property name="sessionFactory"&gt; <br />    &lt;ref local="mySessionFactory"/&gt; <br />  &lt;/property&gt; <br />  &lt;/bean&gt;</td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />
												<br />
												<br />可以看出：每个对象都可以在Spring 配置信息中用&lt;bean&gt;标签引用。在这里，mySessionFactory引用了HibernateSessionFactory，而myTransactionManager引用了HibernateTransactionManage。 注意代码中myTransactionManger Bean有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory setter 和 getter方法，这是用来在Spring启动的时候实现“依赖注入” （dependency injection）的。 在sessionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后就被组装了起来了。 这样的搭配让你从 单例（singleton objects）和工厂（factories）中解放了出来，降低了代码的维护代价。 mySessionFactory.的两个属性，分别是用来注入mappingResources 和 hibernatePropertes的。通常，如果你在Spring之外使用Hibernate,这样的设置应该放在hibernate.cfg.xml中的。 不管怎样,Spring提供了一个便捷的方式-----在Spring内部配置中并入了Hibernate的配置。 如果要得到更多的信息，可以查阅Spring API。 <br /><br /><br /><br /><br /><br />既然我们已经组装配置好了Service Beans，就需要把Business Service Object和 DAO也组装起来，并把这些对象配到一个事务管理器（transaction manager）里。 <br /><br /><br /><br />在Spring中的配置信息： <br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">
																		<br />&lt;!-- ORDER SERVICE --&gt; <br />&lt;bean id="orderService" <br />  class="org. <br />         springframework. <br />         transaction. <br />         interceptor. <br />         TransactionProxyFactoryBean"&gt; <br />  &lt;property name="transactionManager"&gt; <br />    &lt;ref local="myTransactionManager"/&gt; <br />  &lt;/property&gt; <br />  &lt;property name="target"&gt; <br />    &lt;ref local="orderTarget"/&gt; <br />  &lt;/property&gt; <br />  &lt;property name="transactionAttributes"&gt; <br />    &lt;props&gt; <br />      &lt;prop key="find*"&gt; <br />     PROPAGATION_REQUIRED,readOnly,-OrderException <br />      &lt;/prop&gt; <br />      &lt;prop key="save*"&gt; <br />     PROPAGATION_REQUIRED,-OrderException <br />      &lt;/prop&gt; <br />    &lt;/props&gt; <br />  &lt;/property&gt; <br />&lt;/bean&gt; <br />  <br />&lt;!-- ORDER TARGET PRIMARY BUSINESS OBJECT: <br />Hibernate implementation --&gt; <br />&lt;bean id="orderTarget" <br />         class="com. <br />                meagle. <br />                service. <br />                spring. <br />                OrderServiceSpringImpl"&gt; <br />  &lt;property name="orderDAO"&gt; <br />    &lt;ref local="orderDAO"/&gt; <br />  &lt;/property&gt; <br />&lt;/bean&gt; <br />  <br />&lt;!-- ORDER DAO OBJECT --&gt; <br />&lt;bean id="orderDAO" <br />         class="com. <br />                meagle. <br />                service. <br />                dao. <br />                hibernate. <br />                OrderHibernateDAO"&gt; <br />  &lt;property name="sessionFactory"&gt; <br />    &lt;ref local="mySessionFactory"/&gt; <br />  &lt;/property&gt; <br />&lt;/bean&gt;</td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />
												<br />
												<br />
												<br />图4 是我们对象搭建的一个提纲。 从中可以看出，每个对象都联系着Spring，并且能通过Spring注入到其他对象。把它与Spring的配置文件比较，观察他们之间的关系 <br /><br /><img alt="" src="http://www.onjava.com/onjava/2004/04/07/graphics/spring_wiring.gif" border="0" /><br /><br /><span style="FONT-STYLE: italic">图 4. Spring就是这样基于配置文件，将各个Bean搭建在一起。</span><br /><br />这个例子使用一个TransactionProxyFactoryBean，它定义了一个setTransactionManager()。 这对象很有用，他能很方便的处理你申明的事物还有Service Object。 你可以通过transactionAttributes属性来定义怎样处理。 想知道更多还是参考TransactionAttributeEditor吧。 <br /><br />TransactionProxyFactoryBean 还有个setter. 这会被我们 Business service object（orderTarget）引用， orderTarget定义了 业务服务层，并且它还有个属性，由setOrderDAO()引用。这个属性 <br /><br /><br /><br />Spring 和Bean 的还有一点要注意的： bean可以以用两种方式创造。 这些都在单例模式（Sington）和原型模式（propotype）中定义了。 默认的方式是singleton,这意味着共享的实例将被束缚。 而原形模式是在Spring用到bean的时候允许新建实例的。当每个用户需要得到他们自己Bean的Copy时，你应该仅使用prototype模式。（更多的请参考设计模式中的单例模式和原形模式） <br /><br /><span style="FONT-WEIGHT: bold">提供一个服务定位器（Providing a Service Locator）</span><br />既然我们已经将我们的Serices和DAO搭配起来了。我们需要把我们的Service显示到其他层。 这个通常是在Struts或者Swing这层里编码。一个简单方法就是用 服务定位器返回给Spring context 。当然，可以通过直接调用Spring中的Bean来做。 <br /><br />下面是一个Struts Actin 中的服务定位器的一个例子。 <br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">
																		<br />public abstract class BaseAction extends Action { <br />  <br />  private IOrderService orderService; <br />  <br />  public void setServlet(ActionServlet <br />                                 actionServlet) { <br />    super.setServlet(actionServlet); <br />    ServletContext servletContext = <br />               actionServlet.getServletContext(); <br />  <br />    WebApplicationContext wac = <br />      WebApplicationContextUtils. <br />         getRequiredWebApplicationContext( <br />                                 servletContext); <br />  <br />      this.orderService = (IOrderService) <br />                     wac.getBean("orderService"); <br />  } <br />  <br />  protected IOrderService getOrderService() { <br />    return orderService; <br />  } <br />} <br /> </td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />
												<span style="FONT-WEIGHT: bold">UI 层配置 （UI Layer Configuration）</span>
												<br />
												<br />这个例子里UI层 使用了Struts framework. 这里我们要讲述一下在给程序分层的时候， 哪些是和Struts部分的。我们就从一个Struts-config.xml文件中的Action的配置信息开始吧。 <br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">
																		<br />struts-config.xml file. <br /><br />&lt;action path="/SaveNewOrder" <br />    type="com.meagle.action.SaveOrderAction" <br />    name="OrderForm" <br />    scope="request" <br />    validate="true" <br />    input="/NewOrder.jsp"&gt; <br />  &lt;display-name&gt;Save New Order&lt;/display-name&gt; <br />  &lt;exception key="error.order.save" <br />    path="/NewOrder.jsp" <br />    scope="request" <br />    type="com.meagle.exception.OrderException"/&gt; <br />  &lt;exception key="error.order.not.enough.money" <br />    path="/NewOrder.jsp" <br />    scope="request" <br />    type="com. <br />          meagle. <br />          exception. <br />          OrderMinimumAmountException"/&gt; <br />  &lt;forward name="success" path="/ViewOrder.jsp"/&gt; <br />  &lt;forward name="failure" path="/NewOrder.jsp"/&gt; <br />&lt;/action&gt;</td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />SaveNewOrder 这个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中一个很典型的Action; 注意观察这个Action中exception配置，这些Exceptions也在Spring 配置文件(applicationContext-hibernate.xml)中配置了（就在 business service object 的transactionAttributes属性里）。 当异常在业务层被被抛出时，我们可以控制他们，并适当的显示给UI层。 <br /><br />第一个异常，OrderException,在持久层保存order对象失败的时候被触发。这将导致事物回滚并且通过BO把异常回传到Struts这一层。 <br /><br />第二个异常，OrderMinimumAmountException也同第一个一样。 <br /><br /><br /><br /><br /><br />搭配整和的最后一步 通过是让你显示层和业务层相结合。这个已经被服务定位器（service locator）实现了（前面讨论过了）， 这里服务层作为一个接口提供给我们的业务逻辑和持久层。 <br /><br /><br /><br />SaveNewOrder Action 在Struts中用一个服务定位器（service locator）来调用执行业务方法的。 方法代码如下： <br /><br /><br /><br /></span>
										<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="genmed">
																				<b>代码:</b>
																		</span>
																</td>
														</tr>
														<tr>
																<td class="code">public ActionForward execute( <br /><br />  ActionMapping mapping, <br /><br />  ActionForm form, <br /><br />  javax.servlet.http.HttpServletRequest request, <br /><br />  javax.servlet.http.HttpServletResponse response) <br /><br />  throws java.lang.Exception { <br /><br />  <br /><br />  OrderForm oForm = (OrderForm) form; <br /><br />  <br /><br />  // Use the form to build an Order object that <br /><br />  // can be saved in the persistence layer. <br /><br />  // See the full source code in the sample app. <br /><br />  <br /><br />  // Obtain the wired business service object <br /><br />  // from the service locator configuration <br /><br />  // in BaseAction. <br /><br />  // Delegate the save to the service layer and <br /><br />  // further upstream to save the Order object. <br /><br />  getOrderService().saveNewOrder(order); <br /><br />  <br /><br />  oForm.setOrder(order); <br /><br />  <br /><br />  ActionMessages messages = new ActionMessages(); <br /><br />  messages.add( <br /><br />      ActionMessages.GLOBAL_MESSAGE, <br /><br />            new ActionMessage( <br /><br />      "message.order.saved.successfully")); <br /><br />  <br /><br />  saveMessages(request, messages); <br /><br />  <br /><br />  return mapping.findForward("success"); <br /><br />}</td>
														</tr>
												</tbody>
										</table>
										<span class="postbody">
												<br />
												<br />总结 <br /><br />这篇文章在技术和构架方面掩盖了很多低层的基础信息， 文章的主要的意图在于让你意识到如何给你应用程序分层。 分层可以“解耦”你的代码——允许新的组件被添加进来，而且让你的代码易于维护。 这里用到的技术只是专注于把“解偶”做好。 不管怎样，使用这样的构架可以让你用其他技术代替现在的层。 例如，你可能不使用Hibernate实现持久化。既然你在DAO中面向接口的编程的，所以你完全可以用iBATIS来代替。或者，你也可能想用Struts外的其他的技术或者框架替换现在的UI层（转换久层，实现层并不应该直接影响到你的业务逻辑和业务服务层）。 用适当的框架搭建你的Web应用，其实也不是一件烦琐的工作，更主要的是它“解耦”了你程序中的各个层。 <br /><br /><br /><br /><br /><br />后记： <br /><br />看完这篇文章后，只是觉得很喜欢，于是就翻译了，当然同时也准备着挨大家扔来的鸡蛋：）。 <br /><br />这篇文章里并没有太多的技术细节，和详细的步骤。如果你从未使用过这些框架而在运行实例程序遇上困难的话，可以到CSDN论坛Java Open Source版发贴，我一定会详细解答的（啊哦，这不算做广告吧？）， <br /><br />文章是从一个构架的角度讲述了如何搭配现有的开源框架进行分层， 有太多的术语我都不知道怎么表达，而且可能有很多语句存在错误。如果影响了你的阅读，请你直接点原文地址，我同时也象你说声抱歉。 <br /><br /><br /><br />作者简介：Mark Eagle 高级软件工程师，亚特兰大。 <br />翻 译：Totodo,软件工程师 <br /><br /><br /><br /><br /><br />参考： <br /><br />Struts：http://jakarta.apache.org/struts/index.html <br /><br />Spring: <a href="http://www.springframework.org/" target="_blank"><font color="#006699">http://www.springframework.org</font></a><br /><br />Hibernate: <a href="http://www.hibernate.org/" target="_blank"><font color="#006699">http://www.hibernate.org</font></a><br /><br /><a href="http://www.hibernate.org.cn/" target="_blank"><font color="#006699">http://www.hibernate.org.cn</font></a><br /><br />关于控制反转IOC和依赖注射：http://www.martinfowler.com/articles/injection.html <br /><br />原文: <br /><br /><a href="http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=1" target="_blank"><font color="#006699">http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=1</font></a><br /><a href="http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=2" target="_blank"><font color="#006699">http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=2</font></a><br /><a href="http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3" target="_blank"><font color="#006699">http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3</font></a><br /><a href="http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=4" target="_blank"><font color="#006699">http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=4</font></a></span>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/i369/aggbug/101116.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-02-28 12:53 <a href="http://www.blogjava.net/i369/articles/101116.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate实践 [个人认为写得很好]</title><link>http://www.blogjava.net/i369/articles/89524.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Fri, 22 Dec 2006 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/89524.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/89524.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/89524.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/89524.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/89524.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一.								             																				序												在实际项目中使用Hibernate有两年多了，在两年多的实践过程中既体验到了Hibernate带来的N多好处，同时也碰到不少的问题，特写此篇文章做个总结，记录自己在Hibernate实践中的一些经验，希望对于新使用Hibernate的朋友能有个帮助，避...&nbsp;&nbsp;<a href='http://www.blogjava.net/i369/articles/89524.html'>阅读全文</a><img src ="http://www.blogjava.net/i369/aggbug/89524.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2006-12-22 14:40 <a href="http://www.blogjava.net/i369/articles/89524.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>open session and Hibernate事务处理机制 </title><link>http://www.blogjava.net/i369/articles/86994.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 11 Dec 2006 11:32:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/86994.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/86994.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/86994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/86994.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/86994.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">
						<font color="#4b4b4b">
								<font face="宋体">在没有使用</font>
								<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">Spring</span>
						</font>
				</font>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">提供的</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">Open Session In View</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">情况下，因需要在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">service(or Dao)</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">层里把</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">session</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">关闭，所以</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">lazy loading </span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">为</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">true</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">的话，要在应用层内把关系集合都初始化，如</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana"> company.getEmployees()</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">，否则</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">Hibernate</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">抛</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">session already closed Exception;</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">    Open Session In View</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">提供了一种简便的方法，较好地解决了</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">lazy loading</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">问题</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">.</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">
				</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">
						<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">    </span>它有两种配置方式<font face="Verdana">OpenSessionInViewInterceptor</font></span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">和<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">OpenSessionInViewFilter(具体参看<a title="SpringSide" href="http://www.springside.org.cn/" target="_blank"><font color="#999999">SpringSide</font></a>)</span></span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">，功能相同，只是一个在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">web.xml</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">配置，另一个在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">application.xml</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">配置而已。</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">
				</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">
				</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">    Open Session In View</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">request</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">把</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">session</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">绑定到当前</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">thread</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">期间一直保持</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">hibernate session</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">open</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">状态，使</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">session</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">request</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">的整个期间都可以使用，如在</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">View</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">层里</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">PO</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">也可以</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">lazy loading</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">数据，如</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana"> ${ company.employees }</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">。当</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">View </span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">层逻辑完成后，才会通过</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">Filter</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">的</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">doFilter</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">方法或</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">Interceptor</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">的</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">postHandle</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">方法自动关闭</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">session</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: 宋体">。</span>
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">
				</span>
		</p>
		<p>
				<br />
				<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">
						<span style="FONT-SIZE: 10pt; COLOR: #4b4b4b; FONT-FAMILY: Verdana">
						</span>
				</span>
		</p>
		<div class="head">
				<pre class="java">
						<div class="head">OpenSessionInViewInterceptor配置</div>
						<ol>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">&lt;beans&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;bean name=<span class="st0"><font color="#0000ff">"openSessionInViewInterceptor"</font></span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">class</font>
																</strong>
														</span>=<span class="st0"><font color="#0000ff">"org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"</font></span>&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;property name=<span class="st0"><font color="#0000ff">"sessionFactory"</font></span>&gt;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      &lt;ref bean=<span class="st0"><font color="#0000ff">"sessionFactory"</font></span>/&gt;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;/property&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;/bean&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;bean id=<span class="st0"><font color="#0000ff">"urlMapping"</font></span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">class</font>
																</strong>
														</span>=<span class="st0"><font color="#0000ff">"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"</font></span>&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;property name=<span class="st0"><font color="#0000ff">"interceptors"</font></span>&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      &lt;list&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">        &lt;ref bean=<span class="st0"><font color="#0000ff">"openSessionInViewInterceptor"</font></span>/&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      &lt;/list&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;/property&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;property name=<span class="st0"><font color="#0000ff">"mappings"</font></span>&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    ... </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;/property&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;/bean&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">... </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">&lt;/beans&gt; </font>
										</div>
								</li>
						</ol>
				</pre>
		</div>
		<div class="head">
		</div>
		<div class="head">
				<pre class="java">
						<div class="head">OpenSessionInViewFilter配置</div>
						<ol>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">&lt;web-app&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">... </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;filter&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;filter-class&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      org.<span class="me1">springframework</span>.<span class="me1">orm</span>.<span class="me1">hibernate3</span>.<span class="me1">support</span>.<span class="me1">OpenSessionInViewFilter</span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;/filter-class&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;!-- singleSession默认为true,若设为false则等于没用<span class="me1">OpenSessionInView --&gt;</span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;init-param&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      &lt;param-name&gt;singleSession&lt;/param-name&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      &lt;param-value&gt;true&lt;/param-value&gt;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;/init-param&gt;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;/filter&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">... </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;filter-mapping&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;url-pattern&gt;*.<span class="me1">do</span>&lt;/url-pattern&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;/filter-mapping&gt; </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">... </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">&lt;/web-app&gt; </font>
										</div>
								</li>
						</ol>
				</pre>
		</div>
		<p class="head">很多人在使用OpenSessionInView过程中提及一个错误：</p>
		<div class="head">
				<pre class="java">
						<ol>
								<li class="li1">
										<div class="de1">org.<span class="me1">springframework</span>.<span class="me1">dao</span>.<span class="me1">InvalidDataAccessApiUsageException</span>: Write operations </div>
								</li>
								<li class="li1">
										<div class="de1">are not allowed in read-only mode <span class="br0"><font color="#663300">(</font></span>FlushMode.<span class="me1">NEVER</span><span class="br0"><font color="#663300">)</font></span> - turn your Session into </div>
								</li>
								<li class="li1">
										<div class="de1">FlushMode.<span class="me1">AUTO</span> or remove <span class="st0"><font color="#0000ff">'readOnly'</font></span> marker from transaction definition </div>
								</li>
						</ol>
				</pre>
		</div>
		<p class="head">看看OpenSessionInViewFilter里的几个方法</p>
		<div class="head">
				<pre class="java">
						<ol>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">protected</font>
																</strong>
														</span>
														<span class="kw4">void</span>
														<font color="#808080">doFilterInternal</font>
														<span class="br0">
																<font color="#663300">(</font>
														</span>HttpServletRequest request, <br />HttpServletResponse response,FilterChain filterChain<span class="br0"><font color="#663300">)</font></span><br /><span class="kw2"><strong><font color="#7f0055">throws</font></strong></span> ServletException, <span class="kw3">IOException</span></font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">{<br /></font>
														</span>　SessionFactory sessionFactory = lookupSessionFactory<font color="#663300"><span class="br0">(</span><span class="br0">)</span></font>;<br />　logger.<span class="me1">debug</span><span class="br0"><font color="#663300">(</font></span><span class="st0"><font color="#0000ff">"Opening Hibernate Session in OpenSessionInViewFilter"</font></span><span class="br0"><font color="#663300">)</font></span>;<br />　Session session = getSession<span class="br0"><font color="#663300">(</font></span>sessionFactory<span class="br0"><font color="#663300">)</font></span>;<br />　TransactionSynchronizationManager.<span class="me1">bindResource</span></font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">(<br /></font>
														</span>　　sessionFactory, <span class="kw2"><strong><font color="#7f0055">new</font></strong></span> SessionHolder<span class="br0"><font color="#663300">(</font></span>session<font color="#663300"><span class="br0">)</span><span class="br0">)</span></font>;<br />　<span class="kw2"><strong><font color="#7f0055">try</font></strong></span></font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">{<br /></font>
														</span>　　filterChain.<span class="me1">doFilter</span><span class="br0"><font color="#663300">(</font></span>request, response<span class="br0"><font color="#663300">)</font></span>;<br />　</font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">}<br /></font>
														</span>
														<span class="kw2">
																<strong>
																		<font color="#7f0055">　finally</font>
																</strong>
														</span>
												</font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">{<br /></font>
														</span>　TransactionSynchronizationManager.<span class="me1">unbindResource</span><span class="br0"><font color="#663300">(</font></span>sessionFactory<span class="br0"><font color="#663300">)</font></span>;<br />　logger.<span class="me1">debug</span><span class="br0"><font color="#663300">(</font></span><span class="st0"><font color="#0000ff">"Closing Hibernate Session in OpenSessionInViewFilter"</font></span><span class="br0"><font color="#663300">)</font></span>;<br />　closeSession<span class="br0"><font color="#663300">(</font></span>session, sessionFactory<span class="br0"><font color="#663300">)</font></span>;<br />　</font>
												<font color="#663300">
														<font style="BACKGROUND-COLOR: #c0c0c0">
																<span class="br0">}<br /></span>
																<span class="br0">}</span>
														</font>
												</font>
												<span class="br0">
														<br />
														<br />
														<br />
														<br />
														<br />
												</span>
												<font style="BACKGROUND-COLOR: #c0c0c0"> </font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">protected</font>
																</strong>
														</span> Session <font color="#808080">getSession</font><span class="br0"><font color="#663300">(</font></span>SessionFactory sessionFactory</font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">)<br /></font>
														</span>
														<span class="kw2">
																<strong>
																		<font color="#7f0055">throws</font>
																</strong>
														</span> DataAccessResourceFailureException </font>
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">{<br /></font>
														</span>　Session session = SessionFactoryUtils.<span class="me1">getSession</span><span class="br0"><font color="#663300">(</font></span>sessionFactory, <span class="kw2"><strong><font color="#7f0055">true</font></strong></span><span class="br0"><font color="#663300">)</font></span>;<br />　session.<span class="me1">setFlushMode</span><span class="br0"><font color="#663300">(</font></span><font color="#ff6600">FlushMode.<span class="me1">NEVER</span></font><span class="br0"><font color="#663300">)</font></span>;<br />　<span class="kw2"><strong><font color="#7f0055">return</font></strong></span> session;<br /><span class="br0"><font color="#663300">}</font></span></font>
										</div>
								</li>
								<li class="li1">
										<span class="kw2">
												<br />
												<strong>
														<font style="BACKGROUND-COLOR: #c0c0c0" color="#7f0055">protected</font>
												</strong>
										</span>
										<font style="BACKGROUND-COLOR: #c0c0c0">
												<span class="kw4">void</span>
												<font color="#808080">closeSession</font>
												<span class="br0">
														<font color="#663300">(</font>
												</span>Session session, SessionFactory sessionFactory</font>
										<font style="BACKGROUND-COLOR: #c0c0c0">
												<span class="br0">
														<font color="#663300">)<br /></font>
												</span>
												<span class="kw2">
														<strong>
																<font color="#7f0055">throws</font>
														</strong>
												</span> CleanupFailureDataAccessException </font>
										<font style="BACKGROUND-COLOR: #c0c0c0">
												<span class="br0">
														<font color="#663300">{<br /></font>
												</span>　SessionFactoryUtils.<span class="me1">closeSessionIfNecessary</span><span class="br0"><font color="#663300">(</font></span>session, sessionFactory<span class="br0"><font color="#663300">)</font></span>;<br /><span class="br0"><font color="#663300">}</font></span></font>
								</li>
						</ol>
				</pre>
		</div>
		<p class="head">          <font color="#3366ff"><font style="BACKGROUND-COLOR: #ffffff">关于绑定session的方式，通过看spring里TransactionSynchronizationManager的实现，发现：它维护一个java.lang.ThreadLocal类型的resources，resources负责持有线程局部变量，这里resources持有的是一个HashMap，通过TransactionSynchronizationManager.bindResource()方法在map里绑定和线程相关的所有变量到他们的标识上，包括如上所述的绑定在sessionFactory上的线程局部session。sessionHolder只不过是存放可以hold一个session并可以和transtaction同步的容器。</font></font>可以看到OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。然后把该sessionFactory绑定到TransactionSynchronizationManager，使request的整个过程都使用同一个session，在请求过后再接除该sessionFactory的绑定，最后<span class="me1">closeSessionIfNecessary</span>根据该session是否已和transaction绑定来决定是否关闭session。绑定以后，就可以防止每次不会新开一个Session呢？看看HibernateDaoSupport的情况：</p>
		<div class="code">
				<pre>
						<font style="BACKGROUND-COLOR: #c0c0c0">
								<span class="java-keyword">     1.  public</span>
								<span class="java-keyword">final</span> void setSessionFactory(SessionFactory sessionFactory) {    2.      <span class="java-keyword">this</span>.hibernateTemplate = <span class="java-keyword">new</span> HibernateTemplate(sessionFactory);    3.  }    4.  <span class="java-keyword">protected</span><span class="java-keyword">final</span> HibernateTemplate getHibernateTemplate() {    5.      <span class="java-keyword">return</span> hibernateTemplate;    6.  }</font>
				</pre>
		</div>
		<p class="paragraph">        我们的DAO将使用这个template进行操作.</p>
		<p class="paragraph">public abstract class BaseHibernateObjectDao extends HibernateDaoSupport<br />implements BaseObjectDao {<br />     protected BaseEntityObject getByClassId(final long id) {<br />                BaseEntityObject obj =(BaseEntityObject) getHibernateTemplate().execute(new HibernateCallback() {<br />                        public Object doInHibernate(Session session) throws HibernateException {<br />                                    return session.get(getPersistentClass(),new Long(id));<br />                        }<br />                });<br />                return obj;<br />      }<br />     public void save(BaseEntityObject entity) {<br />                  getHibernateTemplate().saveOrUpdate(entity);<br />     }</p>
		<p class="paragraph">    public void remove(BaseEntityObject entity) {<br />              try {<br />                     getHibernateTemplate().delete(entity);<br />              } catch (Exception e) {<br />                      throw new FlexEnterpriseDataAccessException(e);<br />             }<br />     }</p>
		<p class="paragraph">      public void refresh(final BaseEntityObject entity) {<br />               getHibernateTemplate().execute(new HibernateCallback() {<br />                          public Object doInHibernate(Session session) throws HibernateException {<br />                                      session.refresh(entity);<br />                                      return null;<br />                          }<br />               });<br />      }</p>
		<p class="paragraph">     public void replicate(final Object entity) {<br />                getHibernateTemplate().execute(new HibernateCallback() {<br />                          public Object doInHibernate(Session session)throws HibernateException {<br />                                      session.replicate(entity,ReplicationMode.OVERWRITE);<br />                                      return null;<br />               }<br />                });<br />      }<br />}</p>
		<p class="head">        而HibernateTemplate试图每次在execute之前去获得Session，执行完就力争关闭Session </p>
		<div class="code">
				<pre>
						<font style="BACKGROUND-COLOR: #c0c0c0">
								<span class="java-keyword">  1. public</span>
								<span class="java-object">Object</span> execute(HibernateCallback action) <span class="java-keyword">throws</span> DataAccessException {  2.    Session session = (!<span class="java-keyword">this</span>.allowCreate ?  3.          SessionFactoryUtils.getSession(getSessionFactory(),   4.                <span class="java-keyword">false</span>) :  5.          SessionFactoryUtils.getSession(getSessionFactory(),  6.                 getEntityInterceptor(),  7.                 getJdbcExceptionTranslator()));  8.     <span class="java-object">boolean</span> existingTransaction =    9.         TransactionSynchronizationManager.hasResource(getSessionFactory());  10.    <span class="java-keyword">if</span> (!existingTransaction &amp;&amp; getFlushMode() == FLUSH_NEVER) {  11.          session.setFlushMode(FlushMode.NEVER);  12.    }  13.    <span class="java-keyword">try</span> {  14.          <span class="java-object">Object</span> result = action.doInHibernate(session);  15.          flushIfNecessary(session, existingTransaction);  16.          <span class="java-keyword">return</span> result;  17.    }  18.    <span class="java-keyword">catch</span> (HibernateException ex) {  19.          <span class="java-keyword">throw</span> convertHibernateAccessException(ex);  20.    }  21.    <span class="java-keyword">finally</span> {  22.          SessionFactoryUtils.closeSessionIfNecessary(  23.                  session, getSessionFactory());  24.    }  25. }</font>
				</pre>
		</div>
		<p class="head">      而这个SessionFactoryUtils能否得到当前的session以及closeSessionIfNecessary是否真正关闭session，端取决于这个session是否用sessionHolder和这个sessionFactory在我们最开始提到的TransactionSynchronizationManager绑定。 </p>
		<p class="head">     <font style="BACKGROUND-COLOR: #c0c0c0"><span class="kw2"><strong><font color="#7f0055">public</font></strong></span><span class="kw2"><strong><font color="#7f0055">static</font></strong></span><span class="kw4">void</span><font color="#808080">closeSessionIfNecessary</font><span class="br0"><font color="#663300">(</font></span>Session session, SessionFactory sessionFactory<span class="br0"><font color="#663300">)</font></span></font></p>
		<div class="head">
				<pre class="java">
						<ol>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">throws</font>
																</strong>
														</span> CleanupFailureDataAccessException <span class="br0"><font color="#663300">{</font></span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw1">if</span>
														<span class="br0">
																<font color="#663300">(</font>
														</span>session == <span class="kw2"><strong><font color="#7f0055">null</font></strong></span> || <br />TransactionSynchronizationManager.<span class="me1">hasResource</span><span class="br0"><font color="#663300">(</font></span>sessionFactory<font color="#663300"><span class="br0">)</span><span class="br0">)</span></font><span class="br0"><font color="#663300">{</font></span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">return</font>
																</strong>
														</span>;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">}</font>
														</span>
												</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">    logger.<span class="me1">debug</span><span class="br0"><font color="#663300">(</font></span><span class="st0"><font color="#0000ff">"Closing Hibernate session"</font></span><span class="br0"><font color="#663300">)</font></span>;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">try</font>
																</strong>
														</span>
														<span class="br0">
																<font color="#663300">{</font>
														</span>
												</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">      session.<span class="me1">close</span><font color="#663300"><span class="br0">(</span><span class="br0">)</span></font>;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">}</font>
														</span>
												</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">catch</font>
																</strong>
														</span>
														<span class="br0">
																<font color="#663300">(</font>
														</span>JDBCException ex<span class="br0"><font color="#663300">)</font></span><span class="br0"><font color="#663300">{</font></span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="co1">
																<font color="#3f5fbf">// SQLException underneath</font>
														</span>
												</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">throw</font>
																</strong>
														</span>
														<span class="kw2">
																<strong>
																		<font color="#7f0055">new</font>
																</strong>
														</span> CleanupFailureDataAccessException<span class="br0"><font color="#663300">(</font></span><span class="st0"><font color="#0000ff">"Could not close Hibernate session"</font></span>, ex.<span class="me1">getSQLException</span><font color="#663300"><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></font>;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">}</font>
														</span>
												</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">catch</font>
																</strong>
														</span>
														<span class="br0">
																<font color="#663300">(</font>
														</span>HibernateException ex<span class="br0"><font color="#663300">)</font></span><span class="br0"><font color="#663300">{</font></span></font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="kw2">
																<strong>
																		<font color="#7f0055">throw</font>
																</strong>
														</span>
														<span class="kw2">
																<strong>
																		<font color="#7f0055">new</font>
																</strong>
														</span> CleanupFailureDataAccessException<span class="br0"><font color="#663300">(</font></span><span class="st0"><font color="#0000ff">"Could not close Hibernate session"</font></span>, ex<span class="br0"><font color="#663300">)</font></span>;</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">}</font>
														</span>
												</font>
										</div>
								</li>
								<li class="li1">
										<div class="de1">
												<font style="BACKGROUND-COLOR: #c0c0c0">
														<span class="br0">
																<font color="#663300">}</font>
														</span>
												</font>
										</div>
								</li>
						</ol>
				</pre>
		</div>
		<p class="head">    在这个过程中，若HibernateTemplate 发现自当前session有不是readOnly的transaction，就会获取到FlushMode.AUTO Session，使方法拥有写权限。也即是，如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限，如果没有transaction，并且没有另外人为地设flush model的话，则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限，没受保护的则没有。</p>
		<ol>
				<li class="head">可能的解決方式有：<br />1、将singleSession设为false，这样只要改web.xml，缺点是Hibernate Session的Instance可能会大增，使用的JDBC Connection量也会大增，如果Connection Pool的maxPoolSize设得太小，很容易就出问题。<br />2、在控制器中自行管理Session的FlushMode，麻烦的是每个有Modify的Method都要多几行程式。<br />      session.setFlushMode(FlushMode.AUTO); <br />      session.update(user); <br />      session.flush(); <br />3、Extend OpenSessionInViewFilter，Override protected Session getSession(SessionFactory sessionFactory)，将FlushMode直接改为Auto。<br />4、<font style="BACKGROUND-COLOR: #c0c0c0">让方法受Spring的事务控制</font>。这就是常使用的方法： </li>
		</ol>
		<p class="head">采用spring的事务声明,使方法受transaction控制</p>
		<pre class="xml">
				<ol>
						<li class="li1">
								<div class="de1">
										<span class="sc3">
												<span class="re1">
														<font style="BACKGROUND-COLOR: #c0c0c0">  &lt;bean id="baseTransaction" <br />class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" <br />          abstract="true"&gt; <br />        &lt;property name="transactionManager" ref="transactionManager"/&gt; <br />        &lt;property name="proxyTargetClass" value="true"/&gt; <br />        &lt;property name="transactionAttributes"&gt; <br />            &lt;props&gt; <br />                &lt;prop key="get*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />                &lt;prop key="find*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />                &lt;prop key="load*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />                &lt;prop key="save*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />                &lt;prop key="add*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />                &lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />                &lt;prop key="remove*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />            &lt;/props&gt; <br />        &lt;/property&gt; <br />    &lt;/bean&gt; </font>
												</span>
										</span>
										<span class="sc3">
												<span class="re1">
														<br />
												</span>
										</span>
								</div>
								<span class="sc3">
								</span>
						</li>
						<li class="li1">
								<font style="BACKGROUND-COLOR: #c0c0c0">    &lt;bean id="userService" parent="baseTransaction"&gt; <br />        &lt;property name="target"&gt; <br />            &lt;bean class="com.phopesoft.security.service.impl.UserServiceImpl"/&gt; <br />        &lt;/property&gt; <br />    &lt;/bean&gt;</font>
						</li>
				</ol>
		</pre>
		<ol>
		</ol>
		<p>对于上例，则以save,add,update,remove开头的方法拥有可写的事务，如果当前有某个方法，如命名为importExcel()，则因没有transaction而没有写权限，这时若方法内有insert,update,delete操作的话，则需要手动设置flush model为Flush.AUTO,如</p>
		<pre class="java">
				<ol>
						<li class="li1">
								<div class="de1">
										<font style="BACKGROUND-COLOR: #c0c0c0"> session.<span class="me1">setFlushMode</span><span class="br0"><font color="#663300">(</font></span>FlushMode.<span class="me1">AUTO</span><span class="br0"><font color="#663300">)</font></span>; </font>
								</div>
						</li>
						<li class="li1">
								<div class="de1">
										<font style="BACKGROUND-COLOR: #c0c0c0"> session.<span class="me1">save</span><span class="br0"><font color="#663300">(</font></span>user<span class="br0"><font color="#663300">)</font></span>; </font>
								</div>
						</li>
						<li class="li1">
								<div class="de1">
										<font style="BACKGROUND-COLOR: #c0c0c0"> session.<span class="me1">flush</span><font color="#663300"><span class="br0">(</span><span class="br0">)</span></font>;</font>
								</div>
						</li>
				</ol>
		</pre>
		<p>     尽管Open Session In View看起来还不错，其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代码，这个方法实际上是被父类的doFilter调用的，因此，我们可以大约了解的OpenSessionInViewFilter调用流程: request(请求)-&gt;open session并开始transaction-&gt;controller-&gt;View(Jsp)-&gt;结束transaction并close session.</p>
		<p>     一切看起来很正确，尤其是在本地开发测试的时候没出现问题，但试想下如果流程中的某一步被阻塞的话，那在这期间connection就一直被占用而不释放。最有可能被阻塞的就是在写Jsp这步，一方面可能是页面内容大，response.write的时间长，另一方面可能是网速慢，服务器与用户间传输时间久。当大量这样的情况出现时，就有连接池连接不足，造成页面假死现象。</p>
		<p>Open Session In View是个双刃剑，放在公网上内容多流量大的网站请慎用。</p>
		<p> </p>
		<p>
				<font style="BACKGROUND-COLOR: #c0c0c0">另外：</font>这样会产生一点危险性，毕竟把数据库访问的环境放到了表现层。（：用VO）</p>
		<p> </p>
		<hr />
		<p> </p>
		<p> </p>
		<hr />
		<p> </p>
		<p> </p>
		<p>        Hibernate是对JDBC的轻量级对象封装，Hibernate本身是不具备Transaction处理功能的，Hibernate的Transaction实际上是底层的JDBC Transaction的封装，或者是JTA Transaction的封装，下面我们详细的分析： <br /><br />　　Hibernate可以配置为JDBCTransaction或者是JTATransaction，这取决于你在hibernate.properties中的配置: <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">#hibernate.transaction.factory_class<br />net.sf.hibernate.transaction.JTATransactionFactory <br />#hibernate.transaction.factory_class<br />net.sf.hibernate.transaction.JDBCTransactionFactory</font><br />　　如果你什么都不配置，默认情况下使用JDBCTransaction，如果你配置为： <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">hibernate.transaction.factory_class<br />net.sf.hibernate.transaction.JTATransactionFactory</font><br />　　将使用JTATransaction，不管你准备让Hibernate使用JDBCTransaction，还是JTATransaction，我的忠告就是什么都不配，将让它保持默认状态，如下： <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">#hibernate.transaction.factory_class<br />net.sf.hibernate.transaction.JTATransactionFactory <br />#hibernate.transaction.factory_class<br />net.sf.hibernate.transaction.JDBCTransactionFactory</font><br />　　在下面的分析中我会给出原因。 <br /><br />　　<strong>一、JDBC Transaction <br /></strong><br />　　看看使用JDBC Transaction的时候我们的代码例子： <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">Session session = sf.openSession(); <br />Transaction tx = session.beginTransactioin(); <br />... <br />session.flush(); <br />tx.commit(); <br />session.close(); <br /></font>　　这是默认的情况，当你在代码中使用Hibernate的Transaction的时候实际上就是JDBCTransaction。那么JDBCTransaction究竟是什么东西呢？来看看源代码就清楚了： <br /><br />　　Hibernate2.0.3源代码中的类<br /><br />　　net.sf.hibernate.transaction.JDBCTransaction: <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">public void begin() throws HibernateException { <br />... <br />if (toggleAutoCommit) session.connection().setAutoCommit(false); <br />... <br />}<br /></font>　　这是启动Transaction的方法，看到 connection().setAutoCommit(false) 了吗？是不是很熟悉？ <br /><br />　　再来看 <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">public void commit() throws HibernateException { <br />... <br />try { <br />if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush(); <br />try { <br />session.connection().commit(); <br />committed = true; <br />} <br />... <br />toggleAutoCommit(); <br />}</font><br />　　这是提交方法，看到connection().commit() 了吗？下面就不用我多说了，这个类代码非常简单易懂，通过阅读使我们明白Hibernate的Transaction都在干了些什么？我现在把用Hibernate写的例子翻译成JDBC，大家就一目了然了： <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">Connection conn = ...;               &lt;--- session = sf.openSession(); <br />conn.setAutoCommit(false);   &lt;--- tx = session.beginTransactioin(); <br />... &lt;--- ... <br />conn.commit();                           &lt;--- tx.commit(); (对应左边的两句) <br />conn.setAutoCommit(true); <br />conn.close();                              &lt;--- session.close();</font><br />　　看明白了吧，Hibernate的JDBCTransaction根本就是conn.commit而已，根本毫无神秘可言，只不过在Hibernate中，Session打开的时候，就会自动conn.setAutoCommit(false)，不像一般的JDBC，默认都是true，所以你最后不写commit也没有关系，由于Hibernate已经把AutoCommit给关掉了，所以用Hibernate的时候，你在程序中不写Transaction的话，数据库根本就没有反应。 </p>
		<p>
				<strong> 二、JTATransaction</strong>
				<br />
				<br />如果你在EJB中使用Hibernate，或者准备用JTA来管理跨Session的长事务，那么就需要使用JTATransaction，先看一个例子： <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction"); <br /><br />Session s1 = sf.openSession(); <br />... <br />s1.flush(); <br />s1.close(); <br />... <br /><br />Session s2 = sf.openSession(); <br />... <br />s2.flush(); <br />s2.close(); <br /><br />tx.commit();</font><br /><br />这是标准的使用JTA的代码片断，Transaction是跨Session的，它的生命周期比Session要长。如果你在EJB中使用Hibernate，那么是最简单不过的了，你什么Transaction代码统统都不要写了，直接在EJB的部署描述符上配置某某方法是否使用事务就可以了。 <br /><br />现在我们来分析一下JTATransaction的源代码， net.sf.hibernate.transaction.JTATransaction: <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">public void begin(InitialContext context, ... <br />... <br />ut = (UserTransaction) context.lookup(utName); <br />...</font><br /><br />看清楚了吗？ 和我上面写的代码 tx = new Initial Context?().lookup("javax.transaction.UserTransaction"); 是不是完全一样？ <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">public void commit() ... <br />... <br />if (newTransaction) ut.commit(); <br />...</font><br /><br />JTATransaction的控制稍微复杂，不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的。 <br /><br />但是你现在是否看到了什么问题？ 仔细想一下，Hibernate Transaction是从Session中获得的，tx = session.beginTransaction()，最后要先提交tx，然后再session.close，这完全符合JDBC的Transaction的操作顺序，但是这个顺序是和JTA的Transactioin操作顺序彻底矛盾的！！！ JTA是先启动Transaction，然后启动Session，关闭Session，最后提交Transaction，因此当你使用JTA的Transaction的时候，那么就千万不要使用Hibernate的Transaction，而是应该像我上面的JTA的代码片断那样使用才行。 <br /><br /><font style="BACKGROUND-COLOR: #c0c0c0">总结：</font><br />1、在JDBC上使用Hibernate <br /><br />必须写上Hibernate Transaction代码，否则数据库没有反应。此时Hibernate的Transaction就是Connection.commit而已 <br /><br />2、在JTA上使用Hibernate <br /><br />写JTA的Transaction代码，不要写Hibernate的Transaction代码，否则程序会报错 <br /><br />3、在EJB上使用Hibernate <br /><br />什么Transactioin代码都不要写，在EJB的部署描述符里面配置 <br /><br />|---CMT(Container Managed Transaction) <br />| <br />|---BMT(Bean Managed Transaction) <br />| <br />|----JDBC Transaction <br />| <br />|----JTA Transaction </p>
		<p> </p>
		<hr />
		<p> </p>
		<p> </p>
		<hr />
		<p> </p>
		<p>关于session：</p>
		<p>1.  servlet的session机制基于cookies,关闭浏览器的cookies则session失效即不能用网站的登录功能。</p>
		<p>2.  Hibernate Session.</p>
		<p>      1&gt;. session 清理缓存时，按照以下顺序执行SQL语句：</p>
		<p>            session.save()的<font style="BACKGROUND-COLOR: #c0c0c0">实体insert</font><font style="BACKGROUND-COLOR: #ffffff">                                                                                                                 </font><font style="BACKGROUND-COLOR: #ffffff">                       </font><font style="BACKGROUND-COLOR: #c0c0c0">  </font></p>
		<p>
				<font style="BACKGROUND-COLOR: #ffffff">            </font>
				<font style="BACKGROUND-COLOR: #c0c0c0">实体的update</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #ffffff">            对</font>
				<font style="BACKGROUND-COLOR: #c0c0c0">集合的delete</font>
		</p>
		<p>            <font style="BACKGROUND-COLOR: #c0c0c0">集合元素的delete，update，insert</font></p>
		<p>            <font style="BACKGROUND-COLOR: #c0c0c0">集合的insert</font></p>
		<p>            session.delete()的先后，执行<font style="BACKGROUND-COLOR: #c0c0c0">实体的delete</font></p>
		<p>       2&gt;. 默认时，session在以下时间点清理缓存：</p>
		<p>              net.sf.hibernate.Transaction.commit():先清理缓存，再向数据库提交事务                                                          </p>
		<p>              Session.find()或iterate()时，若缓存中持久化对象的属性发生了变化，就会先清缓存，以保证查询结果正确</p>
		<p> </p>
		<p>       3&gt;.  Session的commit()和flush()的区别：flush()只执行SQL语句，不提交事务；commit()先调用flush()，再提交事务</p>
		<p>       4&gt;.  Session.setFlushMode()用于设定清理缓存的时间点。</p>
		<p>
		</p>
		<table style="WIDTH: 468px; HEIGHT: 83px" cellspacing="1" cellpadding="1" width="468" summary="" border="1">
				<tbody>
						<tr>
								<td>清理缓存的模式</td>
								<td>Session的查询方法</td>
								<td>Session.commit()</td>
								<td>Session.flush() </td>
						</tr>
						<tr>
								<td>FlushMode.AUTO</td>
								<td>清理</td>
								<td>清理</td>
								<td>清理</td>
						</tr>
						<tr>
								<td>FlushMode.COMMIT</td>
								<td>
										<font color="#ff0000">不清理</font>
								</td>
								<td>清理</td>
								<td>清理</td>
						</tr>
						<tr>
								<td>FlushMode.NEVER</td>
								<td>
										<font color="#ff0000">不清理</font>
								</td>
								<td>
										<font color="#ff0000">不清理</font>
								</td>
								<td>清理</td>
						</tr>
				</tbody>
		</table>
		<p>            </p>
		<br />
		<br />
		<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=797399</p>
<img src ="http://www.blogjava.net/i369/aggbug/86994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2006-12-11 19:32 <a href="http://www.blogjava.net/i369/articles/86994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的问题</title><link>http://www.blogjava.net/i369/articles/86993.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 11 Dec 2006 11:30:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/86993.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/86993.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/86993.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/86993.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/86993.html</trackback:ping><description><![CDATA[
		<p>0.注意<font style="BACKGROUND-COLOR: #cc99ff">unsaved-value</font>是个很重要的属性。Hibernate通过这个属性来判断一个对象应该save还是update，如果这个对象的id是unsaved-value的话，那说明这个对象不是 persistence object要save（insert)；如果id是非unsaved-value的话，那说明这个对象是persistence object（数据库中已存在），只要update就行了。</p>
		<p>1、<br />org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.xindeco.myregister.pojo.MyRegisterInfo column: password (should be mapped with insert="false" update="false")</p>
		<p>出错原因：1、数据库的字段值和javaBean中的属性类型不统一。对于基本类型，要用wrapper类型而不是primitive类型。2、hibernate的配置文件xxx.hbm.xml中的属性配置不为空，而数据库中的字段却为空。3.两个字段对应同一列，如：password 和repassword同时对应数据库表中的password一列，同时update和insert都设为true。<br />xml文件如下：<br />    &lt;property name="password"<br />                          type="java.lang.String"<br />                          update="true"<br />                          insert="true"<br />                          access="property"<br />                          column="password"<br />                          length = "32"<br />                          /&gt;</p>
		<p>                         &lt;property name="repassword"<br />                          type="java.lang.String"<br />                          update="false"<br />                          insert="false"<br />                          access="property"<br />                          column="password"<br />                          length = "32"<br />                          /&gt;<br />解决的方法：<br />将repassword的insert和update设为false。<br />2.<br />org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition<br /><br />错误原因：<br />在application.xml文件中deleteRegister方法以delete开头，并没有被设定为可更改的，应如下设置：<br /> &lt;!--为事物创建代理类，并指定方法的事物类型--&gt;<br />  &lt;bean id="baseTxProxy" lazy-init="true" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br />    &lt;property name="transactionManager"&gt;<br />      &lt;ref bean="transactionManager"/&gt;<br />    &lt;/property&gt;<br />    &lt;property name="transactionAttributes"&gt;<br />      &lt;props&gt;<br />        &lt;prop key="add*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />        &lt;prop key="cancel*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />           &lt;/props&gt;<br />    &lt;/property&gt;<br />  &lt;/bean&gt;<br />加上一行<br />  &lt;prop key="delete*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />3.session---connection</p>
		<p>
				<font style="BACKGROUND-COLOR: #cc99ff">4.one-to-one小结：</font>
		</p>
		<p>
				<strong>one-to-one</strong>在hibernate中可以用来作为两张表之间的主键关联，这也是hibernate中主键关联的一种用法，这样在一张表中的ID，在生成另外一张表的同时回自动插入到相应的ID字段中去，相应的XML文件设置比较简单，举例如下：<br /><br />    &lt;!-- 建立一对一的到Address的映射，这个是写在User的XML配置文件中的 --&gt;<br />    &lt;!-- 相应的User bean（PO）中也要添加属性 <strong>com.xx.Address </strong> <strong>address</strong>--&gt;<br />    <strong><font color="#008000">&lt;one-to-one name="address" cascade="all" class="com.xx.Address"/&gt;<br /></font></strong>   <br />   &lt;!-- cascade的属性设置不再重复了，可以查看hibernate文档 --&gt;<br /><br />    &lt;!-- 建立一对一的到User的映射，这个是写在Address的XML配置文件中的 --&gt;<br />    &lt;!-- 相应的Address bean（PO）中也要添加属性 <strong>com.xx.</strong>User user--&gt; --&gt;<br />    <strong><font color="#008000">&lt;one-to-one name="user" class="com.xx.User" constrained="true"/&gt;<br /></font></strong><br />      为了在Address中使用User中的主键ID值，我们需要设置Address中的主键生成规则，如下所示，采用foreign关键字<br /><br />   <strong><font color="#008000">&lt;id column="ID" name="id" type="long" unsaved-value="0"&gt; <br />      &lt;generator class="foreign"&gt;<br />        &lt;param name="property"&gt;user&lt;/param&gt;  <br />      &lt;/generator&gt;<br />   &lt;/id&gt;<br /></font></strong><br /><br />      <font color="#000000">这里需要注意的是property的属性值必须与上面到User的映射所填写的name属性值一致</font>，这样就完成了one-to-one的映射关系。<br /><br />上面的过程都很简单，下面我来说说这里需要注意的地方：<br /><br />  1.   在设置属性ID的时候必须注意字段的长度，如笔者这样使用oracle的sequence来生成ID，其长度有14位之长，则应选择hibernate类型long，对应的实体中应选择Long，这样不会出现溢出的情况。<br /><br /><br />  2.   在测试的时候必须要注意这两张表之间因为已经存在了一对一的关系，所以我们不能只写<br />         <font color="#008000">user.setAddress(address);<br /></font>         而忽略了<br />         <font color="#008000">address.setUser(user);<br /></font>         这样在做插入的时候会报出attempted to assign id from null one-to-one property: address的错误，这一点初学者会经常犯，笔者也是其中之一。<br /><br /><br /> 3.   如果不写cascade="all"或者写成cascade="none"的话，即使你写了<br />         <font color="#008000">user.setAddress(address);<br />         address.setUser(user);<br /></font>       也不会发生任何事情，只有user会被存储。</p>
		<p>4. <font style="BACKGROUND-COLOR: #cc99ff">one-to-one的效率问题</font>-------one-to-one在查询时，总是查出和主表关联的表，而且one-to-one的lazy属性只有false proxy no-proxy三种，没有true。outer-join="false"也只是徒增查询语句条数，把本来的一条sql语句变成多条。所以在one-to-one这种一对一的关系不是很强的情况下（one-to-one关系强即总是查出这所有的几个关联表），或者是在一张表中存在多个one-to-one的情况下，使用最好one-to-many来代替one-to-one。</p>
		<p> </p>
		<hr />
		<p> </p>
		<p>
				<font style="BACKGROUND-COLOR: #cc99ff">
						<strong>关于父子关系（</strong>all-delete-orphan<strong>）</strong></font>
		</p>
		<p>当关联双方存在父子关系，就可以在 set 处设定 cascade 为 all-delete-orphan<br />所谓父子关系，即指由父方控制子方的持久化圣明周期，子方对象必须和一个父方对象关联。如果删除父方对象，应该级联删除所有关联的子方对象；如果一个子方对象不再和一个父方对象关联，应该把这个子方对象删除。<br />all-deleteorphan 的能力：<br />1. 当保存或更新父方对象时，级联保存或更新所有关联的子方对象，相当于 cascade 为 save-update<br />2. 当删除父方对象时，级联删除所有关联的子方对象，相当于 cascade 为 delete<br />3. 删除不再和父方对象关联的所有子方对象<br />解除父子关系的 java 语句例如：<br /><font style="BACKGROUND-COLOR: #c0c0c0">customer.getOrders().remove(order);<br />order.setCustomer(null);<br />tx.commit();</font><br />如果 cascade 属性取默认值 null，当解除父子关系时，会执行如下 sql：<br /><font style="BACKGROUND-COLOR: #c0c0c0">update ORDER set CUSTOMER_ID=null where ID=2</font><br />如果要把它也删掉，则设置：</p>
		<p>
				<font style="BACKGROUND-COLOR: #c0c0c0">&lt;set   name="orders"  cascade="all-delete-orphan"  inverse="true"&gt;<br />&lt;key  column="CUSTOMER_ID"  /&gt;<br />&lt;one-to-many  class="mypack.Order" /&gt;</font>
		</p>
		<p>再运行时就会执行：<font style="BACKGROUND-COLOR: #c0c0c0">delete from ORDERS where CUSTOMER_ID=2  and ID=2;</font></p>
		<p>
				<font style="BACKGROUND-COLOR: #cc99ff">cascade几种取值：<br />save-update:   级联保存(load以后如果子对象发生了更新,也会级联更新). 但它不会级联删除<br />delete:              级联删除, 但不具备级联保存和更新<br />all-delete-orphan: 在解除父子关系时,自动删除不属于父对象的子对象, 也支持级联删除和级联保存更新.<br />all:                     级联删除, 级联更新,但解除父子关系时不会自动删除子对象. <br />delete-orphan:删除所有和当前对象解除关联关系的对象<br />none:...<br />级联保存和级联更新总是集合在一起的, 所以没单独的save 或 updata</font>
				<br />
		</p>
<img src ="http://www.blogjava.net/i369/aggbug/86993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2006-12-11 19:30 <a href="http://www.blogjava.net/i369/articles/86993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate中Hql语句中两个字段的计算问题</title><link>http://www.blogjava.net/i369/articles/86983.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Mon, 11 Dec 2006 10:54:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/86983.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/86983.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/86983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/86983.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/86983.html</trackback:ping><description><![CDATA[select (aa.initAmount + aa.initMoney)as MM from SaleFinaDayAccountTemp as aa<br /><br /><br /><br />上面语句错误应该为:<br /><br />select (aa.initAmount  || aa.initMoney)as MM from SaleFinaDayAccountTemp as aa<br /><br /><br /><br />其他的"-","*","/" 均可以直接写,"+"号则应换成"||".<img src ="http://www.blogjava.net/i369/aggbug/86983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2006-12-11 18:54 <a href="http://www.blogjava.net/i369/articles/86983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>