<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>涂0实验室 &#187; hibernate</title>
	<atom:link href="http://www.sulong.info/archives/tag/hibernate/feed" rel="self" type="application/rss+xml" />
	<link>http://www.sulong.info</link>
	<description>一个程序员的成长之路</description>
	<lastBuildDate>Fri, 27 Aug 2010 01:54:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>用hibernate映射时遇到的问题</title>
		<link>http://www.sulong.info/archives/335</link>
		<comments>http://www.sulong.info/archives/335#comments</comments>
		<pubDate>Thu, 21 Jan 2010 09:35:37 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[hibernate]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=335</guid>
		<description><![CDATA[对象和关系型数据库之间存在着根本不同, ORM（对象/关系映射）试图把对象映射到关系型数据库的表结构上，从而简化存储对象到数据库及从数据库中恢复对象的复杂性，让操作数据库就像操作对象一样简单。Hibernate估计是众多ORM框架中最成熟的了，但是在处理类的继承关系时还是会有一些问题。 延迟加载与继承 先看如下的代码, 演示这一映射关系： @Entity @Table&#40;name = &#34;a&#34;&#41; @Inheritance&#40;strategy = InheritanceType.SINGLE_TABLE&#41; @DiscriminatorColumn&#40; &#160; &#160; &#160; &#160; name = &#34;disc&#34;, &#160; &#160; &#160; &#160; columnDefinition = &#34;varchar(4)&#34;, &#160; &#160; &#160; &#160; discriminatorType = DiscriminatorType.STRING&#41; public abstract class A &#123; &#160;@Id &#160;private int oid; &#160;private String name; &#125; @Entity @DiscriminatorValue&#40;&#34;b&#34;&#41; public class B extends A &#123; [...]]]></description>
			<content:encoded><![CDATA[<p>对象和关系型数据库之间存在着根本不同, ORM（对象/关系映射）试图把对象映射到关系型数据库的表结构上，从而简化存储对象到数据库及从数据库中恢复对象的复杂性，让操作数据库就像操作对象一样简单。Hibernate估计是众多ORM框架中最成熟的了，但是在处理类的继承关系时还是会有一些问题。</p>
<p>延迟加载与继承<br />
先看如下的代码, 演示这一映射关系：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><br />
@Inheritance<span style="color: #009900;">&#40;</span>strategy <span style="color: #339933;">=</span> InheritanceType.<span style="color: #006633;">SINGLE_TABLE</span><span style="color: #009900;">&#41;</span><br />
@DiscriminatorColumn<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;disc&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; columnDefinition <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;varchar(4)&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; discriminatorType <span style="color: #339933;">=</span> DiscriminatorType.<span style="color: #006633;">STRING</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp;@Id<br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@DiscriminatorValue<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;b&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> B <span style="color: #000000; font-weight: bold;">extends</span> A <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> age<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@DiscriminatorValue<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;c&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> C <span style="color: #000000; font-weight: bold;">extends</span> B <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> sex<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;d&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #009900;">&#123;</span><br />
&nbsp; @Id<br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
&nbsp; @ManyToOne<span style="color: #009900;">&#40;</span>fetch <span style="color: #339933;">=</span> FetchType.<span style="color: #006633;">LAZY</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> A a<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> A getA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #000000; font-weight: bold;">return</span> a<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>当查询 D类时，应为 D.a 是延迟加载的，所以没有查询过 a表，自然就不知道该记录对应的disc为什么值，也不知道A具体是哪种子类类型。但是查询出的d对象，如果 d.a != null d.a必须有值。Hibernate会生成一个A的子类，并用它的实例作为 d.a 当你真的要访问 d.a 的方法或域时，hibernate才会真正的去查询 a 表。 这其实就是hibernate实现延迟加载的原理。但在本例中，如果你执行如下代码就会遇到 ClassCastException，</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">D d <span style="color: #339933;">=</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>D.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
C c <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>C<span style="color: #009900;">&#41;</span> d.<span style="color: #006633;">getA</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//即使d.getA()确实是C类型，也会ClassCastException</span></div></div>
</pre>
<p>hibernate生成的是A的子类，而不是B或C的子类，所以在类型转换的时候出错了。要解决这一问题，要么不要用延迟加载, 但是性能上面很可能出问题；要么不要用继承，向下面这样：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp;@Id<br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> age<span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> sex<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;d&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #009900;">&#123;</span><br />
&nbsp; @Id<br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
&nbsp; @ManyToOne<span style="color: #009900;">&#40;</span>fetch <span style="color: #339933;">=</span> FetchType.<span style="color: #006633;">LAZY</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> A a<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> A getA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #000000; font-weight: bold;">return</span> a<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>这样实际上是限制OO的能力；要么每次都显示的重新查询改对象，向这样：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">D d <span style="color: #339933;">=</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>D.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
C c <span style="color: #339933;">=</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>C.<span style="color: #000000; font-weight: bold;">class</span>, d.<span style="color: #006633;">getA</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getOid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//重新查，指明类型</span></div></div>
</pre>
<p>这样做既不方便，又不OO。</p>
<p>看来要想让hibernate的映射类保持对象的特性，还是有些困难的。很多时候，这些映射类最终就变成了只负责映射功能的数据库表对象了</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/335/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>DBCP和hibernate有兼容性问题</title>
		<link>http://www.sulong.info/archives/67</link>
		<comments>http://www.sulong.info/archives/67#comments</comments>
		<pubDate>Wed, 30 Jan 2008 05:24:53 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[DB]]></category>
		<category><![CDATA[hibernate]]></category>

		<guid isPermaLink="false">http://www.sulong.info/archives/67</guid>
		<description><![CDATA[从spring 2.5的文档里直接抄下的来配置文件，来配置数据库连接池和hibernate，结果发现运行一段时间后程序就会在查询数据库的地方卡死，而且日志里并没有打印现hibenrate的sql，问题到底发生在什么地方呢？我打开jconsole，连接到程序上一看，发现好多线程被阻塞了，而且都阻塞于pool.getConnection()，看来是DBCP出了问题。后来在网上查了一会，找到hibernate邮件列表上的一段讨论，原来hibernate开发人员认为DBCP设计得不好，BUG多，文档少，所以就不再提供对DBCP的支持了，要用数据库连接池就得用c3p0。看来hibernate每次用完连接都不还给连接池的。我也不想去找如何配置C3P0了，反正生产环境用的肯定是jboss的通过JNDI取到的数据源。干脆让tomcat来管理数据库连接池吧，让spring通过jndi来找到它。在tomcat里配置数据源很简单，官方网站上有详细说明。简单说把下面这段xml复制到tomcat安装目录下的conf/context.xml里就可以了： &#60;Resource name=&#34;myDataSourceName&#34; &#160; &#160; auth=&#34;Container&#34; &#160; &#160; type=&#34;javax.sql.DataSource&#34; &#160; &#160; maxActive=&#34;100&#34; &#160; &#160; maxIdle=&#34;30&#34; &#160; &#160; maxWait=&#34;10000&#34; &#160; &#160; username=&#34;root&#34; &#160; &#160; password=&#34;&#34; &#160; &#160; driverClassName=&#34;com.mysql.jdbc.Driver&#34; &#160; &#160; url=&#34;jdbc:mysql://localhost:3309/mydatabase&#34; &#160; &#160; removeAbandoned=&#34;true&#34; &#160; &#160; removeAbandonedTimeout=&#34;10&#34; &#160; &#160; logAbandoned=&#34;false&#34; /&#62; 上面这段Resource元素很容易理解，关键就是removeAbandoned和removeAbandonedTimeout这两个属性，它们是告诉DBCP把被遗弃的连接删掉，以及被遗弃多久才删除。hibernate就是那个常常遗弃连接的家伙。]]></description>
			<content:encoded><![CDATA[<p>从spring 2.5的文档里直接抄下的来配置文件，来配置数据库连接池和hibernate，结果发现运行一段时间后程序就会在查询数据库的地方卡死，而且日志里并没有打印现hibenrate的sql，问题到底发生在什么地方呢？我打开jconsole，连接到程序上一看，发现好多线程被阻塞了，而且都阻塞于pool.getConnection()，看来是DBCP出了问题。后来在网上查了一会，找到hibernate邮件列表上的一段讨论，原来hibernate开发人员认为DBCP设计得不好，BUG多，文档少，所以就不再提供对DBCP的支持了，要用数据库连接池就得用c3p0。看来hibernate每次用完连接都不还给连接池的。我也不想去找如何配置C3P0了，反正生产环境用的肯定是jboss的通过JNDI取到的数据源。干脆让tomcat来管理数据库连接池吧，让spring通过jndi来找到它。在tomcat里配置数据源很简单，<a href="http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html" title="tomcat6下配置数据源说明">官方网站</a>上有详细说明。简单说把下面这段xml复制到tomcat安装目录下的conf/context.xml里就可以了：</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Resource</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;myDataSourceName&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">auth</span>=<span style="color: #ff0000;">&quot;Container&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;javax.sql.DataSource&quot;</span></span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">maxActive</span>=<span style="color: #ff0000;">&quot;100&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">maxIdle</span>=<span style="color: #ff0000;">&quot;30&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">maxWait</span>=<span style="color: #ff0000;">&quot;10000&quot;</span></span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">username</span>=<span style="color: #ff0000;">&quot;root&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">password</span>=<span style="color: #ff0000;">&quot;&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">driverClassName</span>=<span style="color: #ff0000;">&quot;com.mysql.jdbc.Driver&quot;</span></span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">url</span>=<span style="color: #ff0000;">&quot;jdbc:mysql://localhost:3309/mydatabase&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">removeAbandoned</span>=<span style="color: #ff0000;">&quot;true&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">removeAbandonedTimeout</span>=<span style="color: #ff0000;">&quot;10&quot;</span> </span><br />
<span style="color: #009900;">&nbsp; &nbsp; <span style="color: #000066;">logAbandoned</span>=<span style="color: #ff0000;">&quot;false&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>上面这段Resource元素很容易理解，关键就是removeAbandoned和removeAbandonedTimeout这两个属性，它们是告诉DBCP把被遗弃的连接删掉，以及被遗弃多久才删除。hibernate就是那个常常遗弃连接的家伙。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/67/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>hibernate在什么时候才会去检测持久化对象的version?</title>
		<link>http://www.sulong.info/archives/64</link>
		<comments>http://www.sulong.info/archives/64#comments</comments>
		<pubDate>Wed, 09 Jan 2008 05:43:51 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[hibernate]]></category>

		<guid isPermaLink="false">http://www.sulong.info/archives/64</guid>
		<description><![CDATA[如果在映射时，定义了 optimistic-lock=&#8221;version&#8221;，同时映射了  &#60;version name=&#8221;version&#8221; type=&#8221;integer&#8221; unsaved-value=&#8221;negative&#8221;/&#62;，那么就会起用hibernate的乐观锁机制。hibernate会在执行update merge等更新操作时对比数据库里的该行的version和当前对象的version是否一样，如果一样则更新，不一样则出异常。但并hibernate并不会在所有的更新操作时都做去对比这个version。 乐观锁是用来处理并发事务的。如果有多个事物同时对一行数据进行更新，那么才会检测这个version；反之，如果在一个事务内部，无论对version做怎么样的更改，都不会检测。那么hibernate是如何做到这一步的呢？在每个事务提交的时候，hibernate会判断当前事务里有哪些对象被更新到数据库里，如果这个对象处理持久化状态，则不检查它的version，如果处于游离态，则要在更新前检查version。 换句话说， 如果对象是在当前的事物里通过load方法，get方法，或者通过query等查询出来的，那么这个对象在当前事物里处于持久化状态，hibernate就不会检测version。如果对象不是在当前事务中被从数据库中读出来的，而是程序新建，或者是前一个事务或前一个session里取出来的，那么在当前事务里它就处于游离态，hibernate就会检version。 例如，有一个类Person，需要更新属性name。于你查出这个对象把这个对象在页面显示，并且让用户在页面上更改完成并提交时，form里包含那个对象的id，要更新的字段name和version。这样当用户提交后，在后台，如果你是这样做的： //...... Transaction transaction = session.beginTransaction&#40;&#41;; &#60;font color=&#34;#ff0000&#34;&#62;Person person = &#40;Person&#41; session.load&#40; Person.class, id&#41;;&#60;/font&#62; person.setName&#40;name&#41;; person.setVersion&#40;version&#41;; session.update&#40;person&#41;; transaction.commit&#40;&#41;; //...... 上面那种情况，因为被update的person是从当前事务中查询出来的，正处于持久化状态，所以在更新时，就算页面传来的version值比前数据库里的version值小，hibernate也不会报错，因为它根本就不会检测。如果想让hibernate检测，你可以这样做： //...... Transaction transaction = session.beginTransaction&#40;&#41;; &#60;font color=&#34;#ff0000&#34;&#62;Person person = new Person&#40;&#41;;&#60;/font&#62; &#60;font color=&#34;#ff0000&#34;&#62;person.setId&#40;id&#41;; &#60;/font&#62; person.setName&#40;name&#41;; person.setVersion&#40;version&#41;; session.update&#40;person&#41;; transaction.commit&#40;&#41;; //...... 由于是新建出来的person，这时的person处于游离态，所以在后面的更新时，hibernate就会按照你的意愿去检测version 了。 但是上面的方法还是有问题，就是如果那个Person里有很多个属性，而你只要改其中一部分，如果你不把所有的属性都扔到页面上，再在回来时写入新建的person里，那么在更新时，很可能会就会把一些你不想被更新字段给覆盖掉。而且，如果person和其它对象有外键关联，就更麻烦了。在这样的情况下，还是从数据库里取出当前对象，并更新它的那几个字段来得方便，不过这个时候如果你真的需要检测version，估计只好手动判断version 的值是否正确了。]]></description>
			<content:encoded><![CDATA[<p>如果在映射时，定义了 optimistic-lock=&#8221;version&#8221;，同时映射了  &lt;version name=&#8221;version&#8221; type=&#8221;integer&#8221; unsaved-value=&#8221;negative&#8221;/&gt;，那么就会起用hibernate的乐观锁机制。hibernate会在执行update merge等更新操作时对比数据库里的该行的version和当前对象的version是否一样，如果一样则更新，不一样则出异常。但并hibernate并不会在所有的更新操作时都做去对比这个version。</p>
<p>乐观锁是用来处理并发事务的。如果有多个事物同时对一行数据进行更新，那么才会检测这个version；反之，如果在一个事务内部，无论对version做怎么样的更改，都不会检测。那么hibernate是如何做到这一步的呢？在每个事务提交的时候，hibernate会判断当前事务里有哪些对象被更新到数据库里，如果这个对象处理持久化状态，则不检查它的version，如果处于游离态，则要在更新前检查version。</p>
<p>换句话说， 如果对象是在当前的事物里通过load方法，get方法，或者通过query等查询出来的，那么这个对象在当前事物里处于持久化状态，hibernate就不会检测version。如果对象不是在当前事务中被从数据库中读出来的，而是程序新建，或者是前一个事务或前一个session里取出来的，那么在当前事务里它就处于游离态，hibernate就会检version。</p>
<p>例如，有一个类Person，需要更新属性name。于你查出这个对象把这个对象在页面显示，并且让用户在页面上更改完成并提交时，form里包含那个对象的id，要更新的字段name和version。这样当用户提交后，在后台，如果你是这样做的：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">//......</span><br />
<br />
Transaction transaction <span style="color: #339933;">=</span> session.<span style="color: #006633;">beginTransaction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #339933;">&lt;</span>font color<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;#ff0000&quot;</span><span style="color: #339933;">&gt;</span>Person person <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Person<span style="color: #009900;">&#41;</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span> Person.<span style="color: #000000; font-weight: bold;">class</span>, id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;&lt;/</span>font<span style="color: #339933;">&gt;</span><br />
<br />
person.<span style="color: #006633;">setName</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
person.<span style="color: #006633;">setVersion</span><span style="color: #009900;">&#40;</span>version<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
session.<span style="color: #006633;">update</span><span style="color: #009900;">&#40;</span>person<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
transaction.<span style="color: #006633;">commit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//......</span></div></div>
<p>上面那种情况，因为被update的person是从当前事务中查询出来的，正处于持久化状态，所以在更新时，就算页面传来的version值比前数据库里的version值小，hibernate也不会报错，因为它根本就不会检测。如果想让hibernate检测，你可以这样做：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">//......</span><br />
<br />
Transaction transaction <span style="color: #339933;">=</span> session.<span style="color: #006633;">beginTransaction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #339933;">&lt;</span>font color<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;#ff0000&quot;</span><span style="color: #339933;">&gt;</span>Person person <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Person<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;&lt;/</span>font<span style="color: #339933;">&gt;</span><br />
<br />
<span style="color: #339933;">&lt;</span>font color<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;#ff0000&quot;</span><span style="color: #339933;">&gt;</span>person.<span style="color: #006633;">setId</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">&lt;/</span>font<span style="color: #339933;">&gt;</span><br />
<br />
person.<span style="color: #006633;">setName</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
person.<span style="color: #006633;">setVersion</span><span style="color: #009900;">&#40;</span>version<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
session.<span style="color: #006633;">update</span><span style="color: #009900;">&#40;</span>person<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
transaction.<span style="color: #006633;">commit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//......</span></div></div>
<p>由于是新建出来的person，这时的person处于游离态，所以在后面的更新时，hibernate就会按照你的意愿去检测version 了。</p>
<p>但是上面的方法还是有问题，就是如果那个Person里有很多个属性，而你只要改其中一部分，如果你不把所有的属性都扔到页面上，再在回来时写入新建的person里，那么在更新时，很可能会就会把一些你不想被更新字段给覆盖掉。而且，如果person和其它对象有外键关联，就更麻烦了。在这样的情况下，还是从数据库里取出当前对象，并更新它的那几个字段来得方便，不过这个时候如果你真的需要检测version，估计只好手动判断version 的值是否正确了。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/64/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>hibernate中的inverse和cascade的区别</title>
		<link>http://www.sulong.info/archives/48</link>
		<comments>http://www.sulong.info/archives/48#comments</comments>
		<pubDate>Wed, 05 Dec 2007 14:06:32 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[cascade]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[inverse]]></category>

		<guid isPermaLink="false">http://www.sulong.info/archives/48</guid>
		<description><![CDATA[１、到底在哪用cascade=&#8221;&#8230;&#8221;？ cascade属性并不是多对多关系一定要用的，有了它只是让我们在插入或删除对像时更方便一些，只要在cascade的源头上插入或是删除，所有cascade的关系就会被自己动的插入或是删除。便是为了能正确的 cascade，unsaved-value是个很重要的属性。Hibernate通过这个属性来判断一个对象应该save还是update，如果这个对象的id是unsaved-value的话，那说明这个对象不是persistence object要save（insert)；如果id是非unsaved-value的话，那说明这个对象是persistence object（数据库中已存在），只要update就行了。saveOrUpdate方法用的也是这个机制。 ２、到底在哪用inverse=&#8221;ture&#8221;? inverse属性默认是false的，就是说关系的两端都来维护关系。这个意思就是说，如有一个Student, Teacher和TeacherStudent表，Student和Teacher是多对多对多关系，这个关系由TeacherStudent这个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来维护关系呢？在用hibernate时，我们不会显示的对 TeacherStudent表做操作。对TeacherStudent的操作是hibernate帮我们做的。hibernate就是看hbm文件中指定的是&#8221;谁&#8221;维护关系，那个在插入或删除&#8221;谁&#8221;时，就会处发对关系表的操作。前提是&#8221;谁&#8221;这个对象已经知道这个关系了，就是说关系另一头的对象已经set 或是add到&#8221;谁&#8221;这个对象里来了。前面说过inverse默认是false，就是关系的两端都维护关系，对其中任一个操作都会处发对表系表的操作。当在关系的一头，如Student中的bag或set中用了inverse＝&#8221;true&#8221;时，那就代表关系是由另一关维护的（Teacher）。就是说当这插入Student时，不会操作TeacherStudent表，即使Student已经知道了关系。只有当Teacher插入或删除时才会处发对关系表的操作。所以，当关系的两头都用inverse=&#8221;true&#8221;是不对的，就会导致任何操作都不处发对关系表的操作。当两端都是 inverse=&#8221;false&#8221;或是default值是，在代码对关系显示的维护也是不对的，会导致在关系表中插入两次关系。 在一对多关系中inverse就更有意义了。在多对多中，在哪端inverse=&#8221;true&#8221;效果差不多（在效率上）。但是在一对多中，如果要一方维护关系，就会使在插入或是删除&#8221;一&#8221;方时去update&#8221;多&#8221;方的每一个与这个&#8221;一&#8221;的对象有关系的对象。而如果让&#8221;多&#8221;方面维护关系时就不会有update 操作，因为关系就是在多方的对象中的，直指插入或是删除多方对象就行了。当然这时也要遍历&#8221;多&#8221;方的每一个对象显示的操作修关系的变化体现到DB中。不管怎样说，还是让&#8221;多&#8221;方维护关系更直观一些。]]></description>
			<content:encoded><![CDATA[<p><strong>１、到底在哪用cascade=&#8221;&#8230;&#8221;？</strong><br />
cascade属性并不是多对多关系一定要用的，有了它只是让我们在插入或删除对像时更方便一些，只要在cascade的源头上插入或是删除，所有cascade的关系就会被自己动的插入或是删除。便是为了能正确的 cascade，unsaved-value是个很重要的属性。Hibernate通过这个属性来判断一个对象应该save还是update，如果这个对象的id是unsaved-value的话，那说明这个对象不是persistence object要save（insert)；如果id是非unsaved-value的话，那说明这个对象是persistence object（数据库中已存在），只要update就行了。saveOrUpdate方法用的也是这个机制。<br />
<strong>２、到底在哪用inverse=&#8221;ture&#8221;?</strong><br />
inverse属性默认是false的，就是说关系的两端都来维护关系。这个意思就是说，如有一个Student, Teacher和TeacherStudent表，Student和Teacher是多对多对多关系，这个关系由TeacherStudent这个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来维护关系呢？在用hibernate时，我们不会显示的对 TeacherStudent表做操作。对TeacherStudent的操作是hibernate帮我们做的。hibernate就是看hbm文件中指定的是&#8221;谁&#8221;维护关系，那个在插入或删除&#8221;谁&#8221;时，就会处发对关系表的操作。前提是&#8221;谁&#8221;这个对象已经知道这个关系了，就是说关系另一头的对象已经set 或是add到&#8221;谁&#8221;这个对象里来了。前面说过inverse默认是false，就是关系的两端都维护关系，对其中任一个操作都会处发对表系表的操作。当在关系的一头，如Student中的bag或set中用了inverse＝&#8221;true&#8221;时，那就代表关系是由另一关维护的（Teacher）。就是说当这插入Student时，不会操作TeacherStudent表，即使Student已经知道了关系。只有当Teacher插入或删除时才会处发对关系表的操作。所以，当关系的两头都用inverse=&#8221;true&#8221;是不对的，就会导致任何操作都不处发对关系表的操作。当两端都是 inverse=&#8221;false&#8221;或是default值是，在代码对关系显示的维护也是不对的，会导致在关系表中插入两次关系。<br />
在一对多关系中inverse就更有意义了。在多对多中，在哪端inverse=&#8221;true&#8221;效果差不多（在效率上）。但是在一对多中，如果要一方维护关系，就会使在插入或是删除&#8221;一&#8221;方时去update&#8221;多&#8221;方的每一个与这个&#8221;一&#8221;的对象有关系的对象。而如果让&#8221;多&#8221;方面维护关系时就不会有update 操作，因为关系就是在多方的对象中的，直指插入或是删除多方对象就行了。当然这时也要遍历&#8221;多&#8221;方的每一个对象显示的操作修关系的变化体现到DB中。不管怎样说，还是让&#8221;多&#8221;方维护关系更直观一些。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/48/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
