﻿<?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-Eric Kong-随笔分类-Hibernate</title><link>http://www.blogjava.net/jjshcc/category/44963.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 03 Sep 2012 20:40:33 GMT</lastBuildDate><pubDate>Mon, 03 Sep 2012 20:40:33 GMT</pubDate><ttl>60</ttl><item><title>hibernate中set的排序</title><link>http://www.blogjava.net/jjshcc/archive/2012/09/03/386839.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 03 Sep 2012 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2012/09/03/386839.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/386839.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2012/09/03/386839.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/386839.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/386839.html</trackback:ping><description><![CDATA[<object id="reader" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" height="500" width="450" align="center" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">
<param value="window" name="wmode"  /><param value="true" name="allowfullscreen"  /><param name="allowscriptaccess" value="always"  /><param value="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&amp;docid=cd885f6a1eb91a37f1115cd5&amp;title=hibernate%E4%B8%ADset%E7%9A%84%E6%8E%92%E5%BA%8F&amp;doctype=doc&amp;fpn=5&amp;npn=5&amp;readertype=external&catal=0&amp;cdnurl=http://txt.wenku.baidu.com/play" name="movie"  /><embed width="450" align="center" height="500" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" name="reader" src="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&amp;docid=cd885f6a1eb91a37f1115cd5&amp;title=hibernate%E4%B8%ADset%E7%9A%84%E6%8E%92%E5%BA%8F&amp;doctype=doc&amp;fpn=5&amp;npn=5&amp;readertype=external&catal=0&amp;cdnurl=http://txt.wenku.baidu.com/play" wmode="window" allowscriptaccess="always" bgcolor="#FFFFFF" ver="9.0.0" allowfullscreen="true"></embed></object><img src ="http://www.blogjava.net/jjshcc/aggbug/386839.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2012-09-03 10:03 <a href="http://www.blogjava.net/jjshcc/archive/2012/09/03/386839.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate主键生成策略 </title><link>http://www.blogjava.net/jjshcc/archive/2012/08/31/386683.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Fri, 31 Aug 2012 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2012/08/31/386683.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/386683.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2012/08/31/386683.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/386683.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/386683.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body">
<p>&nbsp;</p>
<p>1、自动增长identity</p>
<p>适用于MySQL、DB2、MS SQL Server，采用数据库生成的主键，用于为long、short、int类型生成唯一标识<br />使用SQL Server 和 MySQL 的自增字段，这个方法不能放到 Oracle 中，Oracle 不支持自增字段，要设定sequence（MySQL 和 SQL Server 中很常用）<br />数据库中的语法如下：<br />MySQL：create table t_user(id int auto_increment primary key, name varchar(20));<br />SQL Server：create table t_user(id int identity(1,1) primary key, name varchar(20));</p>
<p>&nbsp;</p>
<p>&lt;id name="id" column="id" type="long"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="identity" /&gt;<br />&lt;/id&gt;<br />&nbsp;<br />2、sequence</p>
<p>DB2、Oracle均支持的序列，用于为long、short或int生成唯一标识<br />数据库中的语法如下：<br />Oracle：create sequence seq_name increment by 1 start with 1;<br />需要主键值时可以调用seq_name.nextval或者seq_name.curval得到，数据库会帮助我们维护这个sequence序列，保证每次取到的值唯一，如：<br />insert into tbl_name(id, name) values(seq_name.nextval, &#8216;Jimliu&#8217;);</p>
<p>&nbsp;</p>
<p>&lt;id name="id" column="id" type="long"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="sequence"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="sequence"&gt;seq_name&lt;/param&gt;<br />&nbsp;&nbsp; &lt;/generator&gt;<br />&lt;/id&gt;<br />&nbsp;<br />如果我们没有指定sequence参数，则Hibernate会访问一个默认的sequence，是hibernate_sequence，我们也需要在数据库中建立这个sequence<br />此外，sequence还可以有另外一个参数是paramters，可以查看Hibernate的API了解它的用法，见org.hibernate.id.SequenceGenerator<br />调用数据库的sequence来生成主键，要设定序列名，不然hibernate无法找到：<br />&lt;param name="sequence"&gt;NAME_SEQ&lt;/param&gt;（Oracle中很常用）</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>3、hilo</p>
<p>使用一个高/低位算法生成的long、short或int类型的标识符，给定一个表和字段作为高位值的来源，默认的表是hibernate_unique_key，默认的字段是next_hi。它将id的产生源分成两部分，DB+内存，然后按照算法结合在一起产生id值，可以在很少的连接次数内产生多条记录，提高效率</p>
<p>MySQL：create table hi_value(next_hi integer not null);</p>
<p>&nbsp;</p>
<p>insert into hi_value(next_hi) values(1);</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&lt;id name="id" column="id"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="hilo"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="table"&gt;hi_value&lt;/param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="column"&gt;next_hi&lt;/param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="max_lo"&gt;100&lt;/param&gt;<br />&nbsp;&nbsp; &lt;/generator&gt;<br />&lt;/id&gt;<br />&nbsp;<br />在hibernate持久化的时候，由hibernate负责生成低位值。hilo标识符生成器在生成标识符时需要从hi_value表中取出next_hi的当前值，然后修改该值，这个操作是在单独的事务中完成的。最大的低值在属性max_lo中配置，但在Hibernate内存中生成的低位值超过此值时，就有需要到数据库的hi_value表中再次读取高位值了<br />使用hilo生成策略，要在数据库中建立一张额外的表，默认表名为hibernate_unique_key,默认字段为integer类型，名称是next_hi（比较少用）<br />我们也可以自己设置自定义的表名和字段名<br />&lt;id name="id" type="integer"&gt;<br />&nbsp;&nbsp; &lt;column name="id"/&gt;<br />&nbsp;&nbsp; &lt;generator class="hilo"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="my_unique_key"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param column="next_hi"/&gt;<br />&nbsp;&nbsp; &lt;/generator&gt;<br />&lt;/id&gt;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />4、native</p>
<p>&nbsp;</p>
<p>会根据底层数据库的能力，从identity、sequence、hilo中选择一个，灵活性更强，但此时，如果选择sequence或者hilo，则所有的表的主键都会从Hibernate默认的sequence或者hilo表中取。并且，有的数据库对于默认情况主键生成测试的支持，效率并不是很高<br />&nbsp;&nbsp;&nbsp;&nbsp; 对于 oracle 采用 Sequence 方式，对于MySQL 和 SQL Server 采用identity（自增主键生成机制），native就是将主键的生成工作交由数据库完成，hibernate不管（很常用）</p>
<p>&nbsp;</p>
<p>&lt;id name="id" column="id"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="native" /&gt;<br />&lt;/id&gt;<br />&nbsp;<br />5、seqhilo</p>
<p>sequence和hilo的结合，hilo的高位由sequence产生，所以也需要底层数据库的支持<br />通过hilo算法实现，但是主键历史保存在Sequence中，适用于支持 Sequence 的数据库，如 Oracle（比较少用）</p>
<p>&nbsp;</p>
<p>&lt;id name="id" column="id"&gt;<br />&nbsp;&nbsp; &lt;generator class="seqhilo"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="sequence"&gt;seq_name&lt;/param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="max_lo"&gt;100&lt;/param&gt;<br />&nbsp;&nbsp; &lt;/generator&gt;<br />&lt;/id&gt;<br />&nbsp;<br />6、increment</p>
<p>这个是由Hibernate在内存中生成主键，每次增量为1，不依赖于底层的数据库，因此所有的数据库都可以使用，但问题也随之而来，由于是Hibernate生成的，所以只</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>能有一个Hibernate应用进程访问数据库，否则就会产生主键冲突，不能在集群情况下使用<br />插入数据的时候hibernate会给主键添加一个自增的主键，但是一个hibernate实例就维护一个计数器，所以在多个实例运行的时候不能使用这个方法<br />&lt;id name="id" column="id"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="increment" /&gt;<br />&lt;/id&gt;<br />&nbsp;<br />7、</p>
<p>uuid.hex</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>使用一个128-bit的UUID算法生成字符串类型的标识符，UUID被编码成一个32位16进制数字的字符串。UUID包含：IP地址、JVM启动时间、系统时间（精确到1/4秒）和一个计数器值（JVM中唯一）<br />hibernate会算出一个128位的唯一值插入</p>
<p>&lt;id name="id" column="id"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="uuid.hex" /&gt;<br />&lt;/id&gt;</p>
<p>&nbsp;</p>
<p><br />uuid.string<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hibernate会算出一个16位的值插入</p>
<p>&nbsp;</p>
<p><br />8、assigned</p>
<p>由应用程序负责生成主键标识符，往往使用在数据库中没有代理主键，使用的主键与业务相关的情况，如：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&lt;id name="id" column="id" type="string"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;generator class="assigned" /&gt;<br />&lt;/id&gt;<br />&nbsp;<br />这种主键的生成方式不建议使用，在数据库表设计时就应该使用代理主键（surrogate key），不应使用自然主键（natural key具有业务含义），在没有指定&lt;generator&gt;标签时，默认就是assigned主键的生成方式<br />在插入数据的时候主键由用户自己添加，hibernate也不管</p>
<p>&nbsp;</p>
<p><br />9、foreign<br />使用外部表的字段作为主键</p>
<p>&nbsp;</p>
<p>10、select<br />使用触发器生成主键（主要用于早期的数据库主键生成机制，少用）</p>
<p>ps:</p>
<p><span style="color: #ff0000">代理主键是指与业务无关且能唯一标识数据库中记录,一般是数据库自动生成的,比如mysql可以使用auto_increment,Sql2000可以使用identity生成方式,oracle可以使用sequence生成方式自然主键指业务相关,由用户指定,且能唯一标识数据库中的任意一条记录</span></p>
<p><span style="color: #ff0000"><br /></span></p>
<p><span style="color: #ff0000"><span style="color: #000000">简介版：</span><br /></span></p>
<p>increment：代理主键，适合于所有数据库，由hibernate维护主键自增，和底层数据库无关，但是不适合于2个或以上hibernate进程。</p>
<p><span style="color: #ff0000">identity：代理主键，适合于Mysql或ms sql server等支持自增的dbms，主键值不由hibernate维护。</span></p>
<p><span style="color: #ff0000">sequence：代理主键，适合于oracle等支持序列的dbms，主键值不由hibernate维护，由序列产生。</span></p>
<p>native：代理主键，根据底层数据库的具体特性选择适合的主键生成策略，如果是mysql或sqlserver，选择identity，如果是oracle，选择sequence。</p>
<p>hilo：代理主键，hibernate把特定表的字段作为hign值，生成主键值</p>
<p>uuid.hex：代理主键，hibernate采用uuid 128位算法生成基于字符串的主键值</p>
<p>assign：适合于应用程序维护的自然主键。</p></div><img src ="http://www.blogjava.net/jjshcc/aggbug/386683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2012-08-31 13:29 <a href="http://www.blogjava.net/jjshcc/archive/2012/08/31/386683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Equals and HashCode</title><link>http://www.blogjava.net/jjshcc/archive/2011/07/02/353549.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Sat, 02 Jul 2011 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2011/07/02/353549.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/353549.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2011/07/02/353549.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/353549.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/353549.html</trackback:ping><description><![CDATA[<p>Java's Collections and Relational database (and thus Hibernate) relies heavily on being able to distinguish objects in a unified way. In Relational database's this is done with primary keys, in Java we have equals() and hashCode() methods on the objects. This page tries to discuss the best strategies for implementation of equals() and hashcode() in your persistent classes.</p>
<p>&nbsp;<br />Why are equals() and hashcode() important<br />Normally, most Java objects provide a built-in equals() and hashCode() based on the object's identity; so each new() object will be different from all others.</p>
<p>This is generally what you want in ordinary Java programming. And if all your objects are in memory, this is a fine model. Hibernate's whole job, of course, is to move your objects out of memory. But Hibernate works hard to prevent you from having to worry about this.</p>
<p>Hibernate uses the Hibernate session to manage this uniqueness. When you create an object with new(), and then save it into a session, Hibernate now knows that whenever you query for an object and find that particular object, Hibernate should return you that instance of the object.&nbsp; And Hibernate will do just that.</p>
<p>However, once you close the Hibernate session, all bets are off. If you keep holding onto an object that you either created or loaded in a Hibernate session that you have now closed, Hibernate has no way to know about those objects. So if you open another session and query for "the same" object, Hibernate will return you a new instance. Hence, if you keep collections of objects around between sessions, you will start to experience odd behavior (duplicate objects in collections, mainly).</p>
<p>The general contract is: if you want to store an object in a List, Map or a Set then it is an requirement that equals and hashCode are implemented so they obey the standard contract as specified in the&nbsp; documentation.</p>
<p>&nbsp;<br />What is the problem after all?<br />So let's say you do want to keep objects around from session to session, e.g. in a Set related to a particular application user or some other scope that spans several Hibernate sessions.</p>
<p>The most natural idea that comes to mind is implementing equals() and hashCode() by comparing the property you mapped as a database identifier (ie. the primary key attribute). This will cause problems, however, for newly created objects, because Hibernate sets the identifier value for you after storing new objects. Each new instance therefore has the same identifier, null (or &lt;literal&gt;0&lt;/literal&gt;). For example, if you add some new objects to a Set:</p>
<p>// Suppose UserManager and User are Beans mapped with Hibernate<br />&nbsp;<br />UserManager u = session.load(UserManager.class, id);<br />&nbsp;<br />u.getUserSet().add(new User("newUsername1")); // adds a new Entity with id = null or id = 0<br />u.getUserSet().add(new User("newUsername2")); // has id=null, too so overwrites last added object.<br />&nbsp;<br />// u.getUserSet() now contains only the second User<br />As you can see relying on database identifier comparison for persistent classes can get you into trouble if you use Hibernate generated ids, because the identifier value won't be set before the object has been saved. The identifier value will be set when session.save() is called on your transient object, making it persistent.</p>
<p>If you use manually assigned ids (e.g. the "assigned" generator), you are not in trouble at all, you just have to make sure to set the identifier value before adding the object to the Set. This is, on the other hand, quite difficult to guarantee in most applications.</p>
<p>&nbsp;<br />Separating object id and business key<br />To avoid this problem we recommend using the "semi"-unique attributes of your persistent class to implement equals() (and hashCode()). Basically you should think of your database identifier as not having business meaning at all (remember, surrogate identifier attributes and automatically generated vales are recommended anyway). The database identifier property should only be an object identifier, and basically should be used by Hibernate only. Of course, you may also use the database identifier as a convenient read-only handle, e.g. to build links in web applications.</p>
<p>&nbsp;<br />Instead of using the database identifier for the equality comparison, you should use a set of properties for equals() that identify your individual objects. For example, if you have an "Item" class and it has a "name" String and "created" Date, I can use both to implement a good equals() method. No need to use the persistent identifier, the so called "business key" is much better. It's a natural key, but this time there is nothing wrong in using it!</p>
<p>&nbsp;<br />The combination of both fields is stable enough for the life duration of the Set containing your Items. It is not as good as a primary key, but it's certainly a candidate key. You can think of this as defining a "relational identity" for your object -- the key fields that would likely be your UNIQUE fields in your relational model, or at least immutable properties of your persistent class (the "created" Date never changes).</p>
<p>In the example above, you could probably use the "username" property.</p>
<p>&nbsp;<br />Note that this is all that you have to know about equals()/hashCode() in most cases. If you read on, you might find solutions that don't work perfectly or suggestions that don't help you much. Use any of the following at your own risk.</p>
<p>&nbsp;<br />Workaround by forcing a save/flush<br />If you really can't get around using the persistent id for equals() / hashCode(), and if you really have to keep objects around from session to session (and hence can't just use the default equals() / hashCode()), you can work around by forcing a save() / flush() after object creation and before insertion into the set:</p>
<p>// Suppose UserManager and User are Beans mapped with Hibernate<br />&nbsp;<br />UserManager u = session.load(UserManager.class, id);<br />&nbsp;<br />User newUser = new User("newUsername1");<br />// u.getUserSet().add(newUser); // DO NOT ADD TO SET YET!<br />session.save(newUser);<br />session.flush();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // The id is now assigned to the new User object<br />u.getUserSet().add(newUser); // Now OK to add to set.<br />newUser = new User("newUsername2");<br />session.save(newUser);<br />session.flush();<br />u.getUserSet().add(newUser); // Now userSet contains both users.<br />&nbsp;<br />Note that it's highly inefficient and thus not recommended. Also note that it is fragile when using disconnected object graphs on a thin client:</p>
<p>// on client, let's assume the UserManager is empty:<br />UserManager u = userManagerSessionBean.load(UserManager.class, id);<br />User newUser = new User("newUsername1");<br />u.getUserSet().add(newUser); // have to add it to set now since client cannot save it<br />userManagerSessionBean.updateUserManager(u);<br />&nbsp;<br />// on server:<br />UserManagerSessionBean updateUserManager (UserManager u) {<br />&nbsp; // get the first user (this example assumes there's only one)<br />&nbsp; User newUser = (User)u.getUserSet().iterator().next();<br />&nbsp; session.saveOrUpdate(u);<br />&nbsp; if (!u.getUserSet().contains(newUser)) System.err.println("User set corrupted.");<br />}<br />&nbsp;<br />This will actually print "User set corrupted." since newUser's hashcode will change due to the saveOrUpdate call.</p>
<p>This is all frustrating because Java's object identity seems to map directly to Hibernate-assigned database identity, but in reality the two are different -- and the latter doesn't even exist until an object is saved. The object's identity shouldn't depend on whether it's been saved yet or not, but if your equals() and hashCode() methods use the Hibernate identity, then the object id does change when you save.</p>
<p>&nbsp;<br />It's bothersome to write these methods, can't Hibernate help?<br />Well, the only "helping" hand Hibernate can provide is hbm2java.</p>
<p>hbm2java does not (anymore) generate equals/hashcode based on id's because of the described issues in this page.</p>
<p>You can though mark certain properties with &lt;meta attribute="use-in-equals"&gt;true&lt;/meta&gt; to tell hbm2java to generate a proper equals/hashcode.</p>
<p>&nbsp;<br />Summary<br />To sum all this stuff up, here is a listing of what will work or won't work with the different ways to handle equals/hashCode:</p>
<p>&nbsp;<br />&nbsp;no eq/hC at all eq/hC with the id property eq/hC with buisness key <br />use in a composite-id No Yes Yes <br />multiple new instances in set Yes No Yes <br />equal to same object from other session No Yes Yes <br />collections intact after saving Yes No Yes <br />&nbsp;<br />Where the various problems are as follows:</p>
<p>&nbsp;<br />use in a composite-id:</p>
<p>To use an object as a composite-id, it has to implement equals/hashCode in some way, == identity will not be enough in this case.</p>
<p>&nbsp;<br />multiple new instances in set:</p>
<p>Will the following work or not:</p>
<p>HashSet someSet = new HashSet();<br />someSet.add(new PersistentClass());<br />someSet.add(new PersistentClass());<br />assert(someSet.size() == 2);<br />&nbsp;<br />equal to same object from another session:</p>
<p>Will the following work or not:</p>
<p>PersistentClass p1 = sessionOne.load(PersistentClass.class, new Integer(1));<br />PersistentClass p2 = sessionTwo.load(PersistentClass.class, new Integer(1));<br />assert(p1.equals(p2));<br />&nbsp;<br />collections intact after saving:</p>
<p>Will the following work or not:</p>
<p>HashSet set = new HashSet();<br />User u = new User();<br />set.add(u);<br />session.save(u);<br />assert(set.contains(u));<br />&nbsp;<br />Any best practicies for equals and hashcode<br />Read the links in 'Background material' and the API docs - they provide the gory details.</p>
<p>Furthermore I encourage anyone with information and tips about equals and hashcode implementations to come forward and show their "patterns" - I might even try to incorporate them inside hbm2java to make it even more helpful ;)</p>
<p>&nbsp;<br />Background material:<br />Effective Java Programming Language Guide, sample chapter about equals() and hashCode()</p>
<p>Java theory and practice: Hashing it out, Article from IBM</p>
<p>Sam Pullara (BEA) comments on object identity: Blog comment</p>
<p>Article about how to implement equals and hashCode correctly by Manish Hatwalne: Equals and HashCode</p>
<p>Forum thread discussing implementation possibilities without defining a business identity: Equals and hashCode: Is there *any* non-broken approach?</p>
<p>According to The java.lang.Object documentation it should be perfectly ok to always return 0 for the hashCode(). The positive effect of implementing hashCode() to return unique numbers for unique objects, is that it might increase performance. The downside is that the behavior of hashCode() must be consistent with equals(). For object a and b, if a.equals(b) is true, than a.hashCode() == b.hashCode() must be true. But if a.equals(b) returns false, a.hashCode() == b.hashCode() may still be true. Implementing hashCode() as 'return 0' meets these criteria, but it will be extremely inefficient in Hash based collection such as a HashSet or HashMap.<br /></p><img src ="http://www.blogjava.net/jjshcc/aggbug/353549.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2011-07-02 14:06 <a href="http://www.blogjava.net/jjshcc/archive/2011/07/02/353549.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate 中 Criteria 的使用介绍</title><link>http://www.blogjava.net/jjshcc/archive/2010/08/16/329046.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 16 Aug 2010 14:43:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/08/16/329046.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/329046.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/08/16/329046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/329046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/329046.html</trackback:ping><description><![CDATA[要对资料库管理系统进行操作，最基本的就是使用SQL（Standard Query Language）语句，大部份的资料库都支援标准的SQL语句，然而也有一些特定于资料库的SQL语句，应用程式配合SQL语句进行资料库查询时，若使用到特定于资料库的SQL语句，程式本身会有相依于特定资料库的问题。<br />
<br />
使用Hibernate时，即使您不了解SQL的使用与撰写，也可以使用它所提供的API来进行SQL语句查询，org.hibernate.Criteria对SQL进行封装，您可以从Java物件的观点来组合各种查询条件，由Hibernate自动为您产生SQL语句，而不用特别管理SQL与资料库相依的问题。<br />
<br />
以最基本的查询来说，如果您想要查询某个物件所对应的资料表中所有的内容，您可以如下进行查询：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
List users = criteria.list();<br />
<br />
for(Iterator it = users.iterator(); it.hasNext(); ) {<br />
User user = (User) it.next();<br />
System.out.println(user.getId() +<br />
" "t " + user.getName() +<br />
"/" + user.getAge());<br />
}<br />
<br />
<br />
Criteria建立后，若不给予任何的条件，预设是查询物件所对应表格之所有资料，如果您执行以上的程式片段，并于设定档中设定了了Hibernate的&#8221;show_sql&#8221;属性，则可以在主控下看到以下的SQL语句之产生：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_<br />
<br />
Criteria基本查询条件设定<br />
<br />
org.hibernate.Criteria实际上是个条件附加的容器，如果想要设定查询条件，则要使用org.hibernate.criterion.Restrictions的各种静态方法传回org.hibernate.criterion.Criteria实例，传回的每个org.hibernate.criterion.Criteria实例代表着一个条件，您要使用org.hibernate.Criteria的add()方法加入这些条件实例，例如查询&#8221;age&#8221;大于20且小于40的资料：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.add(Restrictions.gt("age", new Integer(20)));<br />
criteria.add(Restrictions.lt("age", new Integer(40)));<br />
List users = criteria.list();<br />
<br />
for(Iterator it = users.iterator(); it.hasNext(); ) {<br />
User user = (User) it.next();<br />
System.out.println(user.getId() +<br />
" "t " + user.getName() +<br />
"/" + user.getAge());<br />
}<br />
<br />
Restrictions的gt()方法表示大于（great than）的条件，而lt表示小于（less than）的条件，执行以上程式片段，观察所产生的SQL语句，将使用where与and子句产来完成SQL的条件查询：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age&gt;? and this_.age<br />
<br />
使用add()方法加入条件时，预设是使用and来组合条件，如果要用or的方式来组合条件，则可以使用Restrictions.or()方法，例如结合age等于（eq）20或（or）age为空（isNull）的条件：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.add(Restrictions.or(<br />
Restrictions.eq("age", new Integer(20)),<br />
Restrictions.isNull("age")<br />
));<br />
List users = criteria.list();<br />
<br />
观察所产生的SQL语句，将使用where与or子句完成SQL的条件查询：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=? or this_.age is null)<br />
<br />
您也可以使用Restrictions.like()方法来进行SQL中like子句的功能，例如查询&#8221;name&#8221;中名称为&#8221;just&#8221;开头的资料：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.add(Restrictions.like("name", "just%"));<br />
List users = criteria.list();<br />
<br />
观察所产生的SQL语句如下：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name like ?<br />
<br />
Restrictions的几个常用限定查询方法如下表所示：<br />
<br />
方法 说明<br />
Restrictions.eq 等于<br />
Restrictions.allEq 使用Map，使用key/value进行多个等于的比对<br />
Restrictions.gt 大于 &gt;<br />
Restrictions.ge 大于等于 &gt;=<br />
Restrictions.lt 小于 &lt;<br />
Restrictions.le 小于等于 &lt;=<br />
Restrictions.between 对应SQL的BETWEEN子句<br />
Restrictions.like 对应SQL的LIKE子句<br />
Restrictions.in 对应SQL的in子句<br />
Restrictions.and and关係<br />
Restrictions.or or关係<br />
<br />
Criteria进阶查询条件设定<br />
<br />
使用Criteria进行查询时，不仅仅能组合出SQL中where子句的功能，还可以组合出如排序、统计、分组等的查询功能。<br />
<br />
排序<br />
<br />
您可以使用Criteria进行查询，并使用org.hibernate.criterion.Order对结果进行排序，例如使用Oder.asc()，指定根据&#8221;age&#8221;由小到大排序（反之则使用desc()）：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.addOrder(Order.asc("age"));<br />
List users = criteria.list();<br />
<br />
注意在加入Order条件时，使用的是addOrder()方法，而不是add()方法，在产生SQL语句时，会使用order by与asc（desc）来进行排序指定：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ order by this_.age asc<br />
<br />
限定查询笔数<br />
<br />
Criteria的setMaxResults()方法可以限定查询回来的笔数，如果配合setFirstResult()设定传回查询结果第一笔资料的位置，就可以实现简单的分页，例如传回第51笔之后的50笔资料（如果有的话）：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.setFirstResult(51);<br />
criteria.setMaxResults(50);<br />
List users = criteria.list();<br />
<br />
根据您所指定得资料库，Hibernate将自动产生与资料库相依的限定笔数查询子句，例如在MySQL中，将使用limit产生以下的SQL语句：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ limit ?, ?<br />
<br />
统计动作<br />
<br />
您可以对查询结果进行统计动作，使用org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min()、 countDistinct()等方法，再搭配Criteria的setProjection()方法加入条件设定，例如对查询结果的"age"作平均：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.setProjection(Projections.avg("age"));<br />
List users = criteria.list();<br />
<br />
上面的程式将由Hibernate自动产生SQL的avg函数进行平均计算：<br />
<br />
Hibernate: select avg(this_.age) as y0_ from T_USER this_<br />
<br />
分组<br />
<br />
还可以配合Projections的groupProperty()来对结果进行分组，例如以"age"进行分组，也就是如果资料中"age"如果有 20、20、25、30，则以下会显示20、25、30：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.setProjection(Projections.groupProperty("age"));<br />
List users = criteria.list();<br />
<br />
上面的程式将由Hibernate自动产生SQL的group by子句进行分组计算：<br />
<br />
Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age<br />
<br />
如果想同时结合统计与分组功能，则可以使用org.hibernate.criterion.ProjectionList，例如下面的程式会计算每个年龄各有多少个人：<br />
<br />
ProjectionList projectionList = Projections.projectionList();<br />
projectionList.add(Projections.groupProperty("age"));<br />
projectionList.add(Projections.rowCount());<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.setProjection(projectionList);<br />
List users = criteria.list();<br />
<br />
观察所产生的SQL语句，将使用group by先进行分组，再针对每个分组进行count函数的计数<br />
<br />
Hibernate: select this_.age as y0_, count(*) as y1_ from T_USER this_ group by this_.age<br />
<br />
根据已知物件进行查询<br />
<br />
设定查询条件并非一定要使用Restrictions，如果属性条件很多，使用Restrictions也不方便，如果有一个已知的物件，则可以根据这个物件作为查询的依据，看看是否有属性与之类似的物件，例如：<br />
<br />
User user = new User();<br />
user.setAge(new Integer(30));<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.add(Example.create(user));<br />
<br />
List users = criteria.list();<br />
<br />
您可以透过org.hibernate.criterion.Example的create()方法来建立Example实例，Example实作了Criteria介面，因此可以使用add()方法加入至Criteria条件设定之中，Hibernate将自动过滤掉空属性，根据已知物件上已设定的属性，判定是否产生于where子句之中：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=?)<br />
<br />
设定SQL范本<br />
<br />
如果您了解如何撰写SQL语句，想要设定一些Hibernate产生SQL时的范本，您也可以使用Restrictions的sqlRestriction()方法，提供SQL语法范本作限定查询，例如查询name以cater开头的资料：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));<br />
List users = criteria.list();<br />
<br />
其中alias将被替换为与User类别相关的名称，而?将被替换为cater%，也就是第二个参数所提供的值，sqlRestriction() 方法第一个参数所设定的是where子句的部份，所以在SQL撰写时，不必再写where，观察所产生的SQL语句，将使用您所设定的SQL范本作为基础，来完成SQL的条件查询：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name LIKE (?)<br />
<br />
如果有多个查询条件，例如between子句的查询，则可以如下：<br />
<br />
Criteria criteria = session.createCriteria(User.class);<br />
Integer[] ages = {new Integer(20), new Integer(40)};<br />
Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};<br />
criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));<br />
List users = criteria.list();<br />
<br />
观察所产生的SQL语句如下：<br />
<br />
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age BETWEEN (?) AND (?)<br />
<br />
使用DetchedCriteria<br />
<br />
Criteria与Session绑定，其生命週期跟随着Session结束而结束，使用Criteria时进行查询时，每次都要于执行时期动态建立物件，并加入各种查询条件，随着Session的回收，Criteria也跟着回收。<br />
<br />
为了能够重複使用Criteria物件，在Hibernate 3中新增了org.hibernate.criterion.DetchedCriteria，您可以先建立DetchedCriteria实例，并加入各种查询条件，并于需要查询时再与Session绑定，获得一个绑定Session的Criteria物件，例如：<br />
<br />
// 先建立DetchedCriteria物件<br />
DetachedCriteria detchedCriteria = DetachedCriteria.forClass(User.class);<br />
// 加入查询条件<br />
detchedCriteria.add(Restrictions.ge("age",new Integer(25)));<br />
<br />
Session session = sessionFactory.openSession();<br />
// 绑定Session并返回一个Criteria实例<br />
Criteria criteria = detchedCriteria.getExecutableCriteria(session);<br />
<br />
List users = criteria.list();<br />
<br />
结论<br />
<br />
Hibernate的Criteria API可以让您使用物件的方式，组合出查询资料库系统的条件，Hibernate会自动依您所使用的资料库，动态产生SQL语句，让您的应用程式在存取资料库时，不致于因撰写了特定的SQL而相依于特定的资料库，如果您的开发人员不熟悉SQL语句的撰写，也可以试着使用Criteria来解决查询资料库的需求。
<img src ="http://www.blogjava.net/jjshcc/aggbug/329046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-08-16 22:43 <a href="http://www.blogjava.net/jjshcc/archive/2010/08/16/329046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate 3.0 多条件查询方法 </title><link>http://www.blogjava.net/jjshcc/archive/2010/08/12/328714.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 12 Aug 2010 13:02:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/08/12/328714.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/328714.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/08/12/328714.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/328714.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/328714.html</trackback:ping><description><![CDATA[<p>此方法可多条件查询且可以根据关联的表条件进行查询<br />
如查询某个商品：<br />
表结构如下：<br />
goods(商品表)<br />
goodsid(商品id) goodsname(名称) typeid(分类-外键)&nbsp; supplierid(供应商-外键)</p>
<p>type(分类表)<br />
typeid(id主键)&nbsp;&nbsp; typename(分类名称)</p>
<p>supplier(供应商表)<br />
supplierid(ID主键)&nbsp;&nbsp; suppliername( 供应商名称)</p>
<p>你可建一个查询条件的类，里面包括你要查询的所有字段<br />
如: public class Query{<br />
&nbsp;&nbsp;&nbsp; private String suppliername;<br />
&nbsp;&nbsp;&nbsp; private String goodsname;<br />
&nbsp;&nbsp;&nbsp; private String typename;<br />
..................<br />
get/set方法................<br />
}</p>
<p>得到查询条件后，可以把此类的一个对象传入自己做的方法，此方法可以根据条件的个数及是否输入条件进行查询：<br />
public static List query_goods(Query query){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Session session = SessionFactory.getSession();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Criteria criteria = session.createCriteria(Goods.class);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Criteria type = criteria.createCriteria("type");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Criteria&nbsp; supplier= criteria.createCriteria("supplier");<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(null!=query.getGoodsname() &amp;&amp; !"".equels(query.getGoodsname() ))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; criteria.add(Restrictions.like("goodsname","%"+query.getGoodsname()+"%"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(null!=query.getSuppliername() &amp;&amp; !"".equels(query.getSuppliername() ))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; supplier.add(Restrictions.like("suppliername","%"+query.getSuppliername()+"%"));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(null!=query.getTypename() &amp;&amp; !"".equels(query.getTypename() ))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type.add(Restrictions.like("typename","%"+query.getTypename+"%"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List list = criteria.list();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return list;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>以上方面还可多层的嵌套，如type里还有外键，可以按照以上方法进行嵌套。注意，查询时所有涉及到的数据都将一次性写入类的属性中，包括有关联的，即此时goods的关联延迟加载无效，我觉得这一点非常的好。呵呵，有什么好处，可以自己好好的想想。<br />
有许多人曾经提到过用Example，就不用自己判断了，如果没有关联条件查询的话，确实是好，可它的缺点就是不能查询关联中的条件。 </p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/328714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-08-12 21:02 <a href="http://www.blogjava.net/jjshcc/archive/2010/08/12/328714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate中Criteria的完整用法 </title><link>http://www.blogjava.net/jjshcc/archive/2010/08/12/328712.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 12 Aug 2010 12:51:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/08/12/328712.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/328712.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/08/12/328712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/328712.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/328712.html</trackback:ping><description><![CDATA[<p>近在项目中使用 Spring 和 Hibernate 进行开发，有感于 Criteria 比较好用，在查询方法</p>
<p>设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装。现在对 Hibernate的Criteria 的用法进行总结：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口，下面提供了 Criteria和DetachedCriteria 。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Criteria 和 DetachedCriteria 的主要区别在于创建的形式不一样， Criteria 是在线的，所以它是由 Hibernate Session 进行创建的；而 DetachedCriteria 是离线的，创建时无需 Session，DetachedCriteria 提供了 2 个静态方法 forClass(Class) 或 forEntityName(Name) 进行DetachedCriteria 实例的创建。 Spring 的框架提供了getHibernateTemplate().findByCriteria(detachedCriteria) 方法可以很方便地根据DetachedCriteria 来返回查询结<br />
果。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 设置查询条件。可以设置 FetchMode( 联合查询抓取的模式 ) ，设置排序方式。对于 Criteria 还可以设置 FlushModel （冲刷 Session 的方式）和 LockMode （数据库锁模式）。 <br />
下面对 Criterion 和 Projection 进行详细说明。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Criterion 是 Criteria 的查询条件。Criteria 提供了 add(Criterion criterion) 方法来添加查询条件。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Criterion 接口的主要实现包括： Example 、 Junction 和 SimpleExpression 。而 Junction 的实际使用是它的两个子类 conjunction 和 disjunction ，分别是使用 AND 和 OR 操作符进行来联结查询条件集合。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Criterion 的实例可以通过 Restrictions 工具类来创建，Restrictions 提供了大量的静态方法，如 eq （等于）、 ge （大于等于）、 between 等来方法的创建 Criterion 查询条件 （SimpleExpression 实例）。除此之外， Restrictions 还提供了方法来创建 conjunction 和 disjunction 实例，通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;至于 Example 的创建有所不同， Example 本身提供了一个静态方法 create(Object entity) ，即根据一个对象（实际使用中一般是映射到数据库的对象）来创建。然后可以设置一些过滤条件： <br />
Example exampleUser =Example.create(u) <br />
.ignoreCase() // 忽略大小写 <br />
.enableLike(MatchMode.ANYWHERE); <br />
/ / 对 String 类型的属性，无论在那里值在那里都匹配。相当于 %value% <br />
Project 主要是让 Criteria 能够进行报表查询，并可以实现分组。 Project 主要有 SimpleProjection 、 ProjectionList 和 Property 三个实现。其中 SimpleProjection 和 <br />
ProjectionList 的实例化是由内建的 Projections 来完成，如提供的 avg 、 count 、 max 、 min 、 sum 可以让开发者很容易对某个字段进行统计查询。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Property 是对某个字段进行查询条件的设置，如通过Porperty.forName(&#8220;color&#8221;).in (new String[]{&#8220;black&#8221;,&#8221;red&#8221;,&#8221;write&#8221;}); 则可以创建一个 Project 实例。通过 <br />
criteria 的 add(Project) 方法加入到查询条件中去。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用 Criteria 进行查询，主要要清晰的是 Hibernate 提供了那些类和方法来满足开发中查询条件的创建和组装，下面介绍几种用法：<br />
1. 创建一个Criteria 实例<br />
org.hibernate.Criteria接口表示特定持久类的一个查询。Session是 Criteria实例的工厂。<br />
Criteria crit = sess.createCriteria(Cat.class);<br />
crit.setMaxResults(50);<br />
List cats = crit.list();</p>
<p>2. 限制结果集内容<br />
一个单独的查询条件是org.hibernate.criterion.Criterion 接口的一个实例。</p>
<p>org.hibernate.criterion.Restrictions类 定义了获得某些内置Criterion类型的工厂方法。<br />
List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.like("name", "Fritz%") )<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.between("weight", minWeight, maxWeight) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>约束可以按逻辑分组。 </p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.like("name", "Fritz%") )<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.or(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Restrictions.eq( "age", new Integer(0) ),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Restrictions.isNull("age")<br />
&nbsp;&nbsp;&nbsp; ) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.disjunction()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Restrictions.isNull("age") )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Restrictions.eq("age", new Integer(0) ) )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Restrictions.eq("age", new Integer(1) ) )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Restrictions.eq("age", new Integer(2) ) )<br />
&nbsp;&nbsp;&nbsp; ) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>Hibernate提供了相当多的内置criterion类型(Restrictions 子类), 但是尤其有用的是可以允许</p>
<p>你直接使用SQL。</p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", </p>
<p>Hibernate.STRING) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>{alias}占位符应当被替换为被查询实体的列别名。 <br />
Property实例是获得一个条件的另外一种途径。你可以通过调用Property.forName() 创建一个</p>
<p>Property。 </p>
<p>Property age = Property.forName("age");<br />
List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.disjunction()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( age.isNull() )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( age.eq( new Integer(0) ) )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( age.eq( new Integer(1) ) )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( age.eq( new Integer(2) ) )<br />
&nbsp;&nbsp;&nbsp; ) )<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>3. 结果集排序<br />
你可以使用org.hibernate.criterion.Order来为查询结果排序。 </p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.like("name", "F%")<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.asc("name") )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.desc("age") )<br />
&nbsp;&nbsp;&nbsp; .setMaxResults(50)<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("name").like("F%") )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Property.forName("name").asc() )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Property.forName("age").desc() )<br />
&nbsp;&nbsp;&nbsp; .setMaxResults(50)<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>4. 关联<br />
你可以使用createCriteria()非常容易的在互相关联的实体间建立 约束。</p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.like("name", "F%")<br />
&nbsp;&nbsp;&nbsp; .createCriteria("kittens")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Restrictions.like("name", "F%")<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
注意第二个 createCriteria()返回一个新的 Criteria实例，该实例引用kittens 集合中的元素。 <br />
接下来，替换形态在某些情况下也是很有用的。</p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .createAlias("kittens", "kt")<br />
&nbsp;&nbsp;&nbsp; .createAlias("mate", "mt")<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.eqProperty("kt.name", "mt.name") )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
(createAlias()并不创建一个新的 Criteria实例。) <br />
Cat实例所保存的之前两次查询所返回的kittens集合是 没有被条件预过滤的。如果你希望只获得</p>
<p>符合条件的kittens， 你必须使用returnMaps()。 </p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .createCriteria("kittens", "kt")<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.eq("name", "F%") )<br />
&nbsp;&nbsp;&nbsp; .returnMaps()<br />
&nbsp;&nbsp;&nbsp; .list();<br />
Iterator iter = cats.iterator();<br />
while ( iter.hasNext() ) {<br />
&nbsp;&nbsp;&nbsp; Map map = (Map) iter.next();<br />
&nbsp;&nbsp;&nbsp; Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);<br />
&nbsp;&nbsp;&nbsp; Cat kitten = (Cat) map.get("kt");<br />
}</p>
<p>5. 动态关联抓取<br />
你可以使用setFetchMode()在运行时定义动态关联抓取的语义。 </p>
<p>List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.like("name", "Fritz%") )<br />
&nbsp;&nbsp;&nbsp; .setFetchMode("mate", FetchMode.EAGER)<br />
&nbsp;&nbsp;&nbsp; .setFetchMode("kittens", FetchMode.EAGER)<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>这个查询可以通过外连接抓取mate和kittens。</p>
<p>6. 查询示例<br />
org.hibernate.criterion.Example类允许你通过一个给定实例 构建一个条件查询。</p>
<p>Cat cat = new Cat();<br />
cat.setSex('F');<br />
cat.setColor(Color.BLACK);<br />
List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Example.create(cat) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
版本属性、标识符和关联被忽略。默认情况下值为null的属性将被排除。 <br />
可以自行调整Example使之更实用。 </p>
<p>Example example = Example.create(cat)<br />
&nbsp;&nbsp;&nbsp; .excludeZeroes()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //exclude zero valued properties<br />
&nbsp;&nbsp;&nbsp; .excludeProperty("color") //exclude the property named "color"<br />
&nbsp;&nbsp;&nbsp; .ignoreCase()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //perform case insensitive string comparisons<br />
&nbsp;&nbsp;&nbsp; .enableLike();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //use like for string comparisons<br />
List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add(example)<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
甚至可以使用examples在关联对象上放置条件。</p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Example.create(cat) )<br />
&nbsp;&nbsp;&nbsp; .createCriteria("mate")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Example.create( cat.getMate() ) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
7. 投影(Projections)、聚合（aggregation）和分组（grouping）<br />
org.hibernate.criterion.Projections是 Projection 的实例工厂。我们通过调用 </p>
<p>setProjection()应用投影到一个查询。 </p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.rowCount() )<br />
&nbsp;&nbsp;&nbsp; .add( Restrictions.eq("color", Color.BLACK) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.projectionList()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.rowCount() )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.avg("weight") )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.max("weight") )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.groupProperty("color") )<br />
&nbsp;&nbsp;&nbsp; )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
在一个条件查询中没有必要显式的使用 "group by" 。某些投影类型就是被定义为 分组投影，他</p>
<p>们也出现在SQL的group by子句中。 </p>
<p>可以选择把一个别名指派给一个投影，这样可以使投影值被约束或排序所引用。下面是两种不同的</p>
<p>实现方式：</p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.asc("colr") )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>&nbsp;</p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.groupProperty("color").as("colr") )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.asc("colr") )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>alias()和as()方法简便的将一个投影实例包装到另外一个 别名的Projection实例中。简而言之，</p>
<p>当你添加一个投影到一个投影列表中时 你可以为它指定一个别名： </p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.projectionList()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.rowCount(), "catCountByColor" )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.avg("weight"), "avgWeight" )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.max("weight"), "maxWeight" )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.groupProperty("color"), "color" )<br />
&nbsp;&nbsp;&nbsp; )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.desc("catCountByColor") )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.desc("avgWeight") )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
List results = session.createCriteria(Domestic.class, "cat")<br />
&nbsp;&nbsp;&nbsp; .createAlias("kittens", "kit")<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.projectionList()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.property("cat.name"), "catName" )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.property("kit.name"), "kitName" )<br />
&nbsp;&nbsp;&nbsp; )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.asc("catName") )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.asc("kitName") )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
也可以使用Property.forName()来表示投影：</p>
<p>List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Property.forName("name") )<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("color").eq(Color.BLACK) )<br />
&nbsp;&nbsp;&nbsp; .list();<br />
List results = session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Projections.projectionList()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Projections.rowCount().as("catCountByColor") )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Property.forName("weight").avg().as("avgWeight") )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Property.forName("weight").max().as("maxWeight") )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add( Property.forName("color").group().as("color" )<br />
&nbsp;&nbsp;&nbsp; )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.desc("catCountByColor") )<br />
&nbsp;&nbsp;&nbsp; .addOrder( Order.desc("avgWeight") )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p><br />
8. 离线(detached)查询和子查询<br />
DetachedCriteria类使你在一个session范围之外创建一个查询，并且可以使用任意的 Session来</p>
<p>执行它。</p>
<p>DetachedCriteria query = DetachedCriteria.forClass(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("sex").eq('F') );<br />
//创建一个Session<br />
Session session = .;<br />
Transaction txn = session.beginTransaction();<br />
List results = query.getExecutableCriteria(session).setMaxResults(100).list();<br />
txn.commit();<br />
session.close();</p>
<p><br />
DetachedCriteria也可以用以表示子查询。条件实例包含子查询可以通过 Subqueries或者<br />
Property获得。</p>
<p>DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Property.forName("weight").avg() );<br />
session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("weight).gt(avgWeight) )<br />
&nbsp;&nbsp;&nbsp; .list();<br />
DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .setProjection( Property.forName("weight") );<br />
session.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add( Subqueries.geAll("weight", weights) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>相互关联的子查询也是有可能的：</p>
<p>DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")<br />
&nbsp;&nbsp;&nbsp; .setProjection( Property.forName("weight").avg() )<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("cat2.sex").eqProperty("cat.sex") );<br />
session.createCriteria(Cat.class, "cat")<br />
&nbsp;&nbsp;&nbsp; .add( Property.forName("weight).gt(avgWeightForSex) )<br />
&nbsp;&nbsp;&nbsp; .list();</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/328712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-08-12 20:51 <a href="http://www.blogjava.net/jjshcc/archive/2010/08/12/328712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate 对象 三种状态 瞬时态,持久态,脱管态 以及 save update saveOrUpdate merge等的使用</title><link>http://www.blogjava.net/jjshcc/archive/2010/08/10/328454.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Tue, 10 Aug 2010 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/08/10/328454.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/328454.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/08/10/328454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/328454.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/328454.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hibernate的对象有3种状态，分别为：瞬时态(Transient)、 持久态(Persistent)、脱管态(Detached)。处于持久态的对象也称为PO(Persistence Object)，瞬时对象和脱管对象也称为VO（Value Object）。<br />
<br />
&nbsp;&nbsp; &nbsp;*&nbsp; 瞬时态<br />
<br />
&nbsp;&nbsp; &nbsp;由new命令开辟内存空间的java对象，<br />
<br />
&nbsp;&nbsp; &nbsp;eg. Person person = new Person("amigo", "女");<br />
<br />
&nbsp;&nbsp; &nbsp;如果没有变量对该对象进行引用，它将被java虚拟机回收。<br />
<br />
&nbsp;&nbsp; &nbsp; 瞬时对象在内存孤立存在，它是携带信息的载体，不和数据库的数据有任何关联关系，在Hibernate中，可通过session的save()或 saveOrUpdate()方法将瞬时对象与数据库相关联，并将数据对应的插入数据库中，此时该瞬时对象转变成<span style="color: red;">持久化对象</span>。<br />
<br />
&nbsp;&nbsp; &nbsp;* 持久态<br />
<br />
&nbsp;&nbsp; &nbsp;处于该状态的对象在数据库中具有对应的记录，并拥有一个持久化标识。如果是用hibernate的delete()方法，对应的持久对象就变成<span style="color: red;">瞬时对象</span>，因数据库中的对应数据已被删除，该对象不再与数据库的记录关联。<br />
&nbsp;&nbsp; &nbsp;当一个session执行close()或clear()、evict()之后，持久对象变成<span style="color: red;">脱管对象</span>，此时持久对象会变成脱管对象，此时该对象虽然具有数据库识别值，但它已不在HIbernate持久层的管理之下。<br />
<br />
&nbsp;&nbsp; &nbsp;<span style="color: red;">持久对象具有如下特点</span>：<br />
<br />
&nbsp;&nbsp; &nbsp;1. <span style="color: red;">和session实例关联</span>；<br />
&nbsp;&nbsp; &nbsp;2. <span style="color: red;">在数据库中有与之关联的记录</span>。<br />
<br />
&nbsp;&nbsp; &nbsp;* 脱管态<br />
<br />
&nbsp;&nbsp; &nbsp;当与某持久对象关联的session被关闭后，该持久对象转变为脱管对象。当脱管对象被重新关联到session上时，并再次转变成持久对象。<br />
&nbsp;&nbsp; &nbsp;脱管对象拥有数据库的识别值，可通过update()、saveOrUpdate()等方法，转变成<span style="color: red;">持久对象</span>。<br />
<br />
&nbsp;&nbsp; &nbsp;脱管对象具有如下特点：<br />
<br />
&nbsp;&nbsp; &nbsp;1. <span style="color: red;">本质上与瞬时对象相同，在没有任何变量引用它时，JVM会在适当的时候将它回收</span>；<br />
&nbsp;&nbsp; &nbsp;2. <span style="color: red;">比瞬时对象多了一个数据库记录标识值</span>。<br />
<br />
&nbsp;<br />
<br />
&nbsp;&nbsp; &nbsp;瞬态(Transient)，也叫临时态。处于这种状态的对象具备的特征如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;不在Session的缓存中，不与任何的Session实例相关联。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;在数据库中没有与之相对应的记录。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;持久态(Persistent)，处于这种状态的对象具备的特征如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;在Session的缓存中，与Session实例相关联。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;在数据库中存在与之相对应的记录。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;脱管态(Detached)，也叫游离态。处于这种状态的对象具备的特征如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;不在Session的缓存中，不与任何的Session实例相关联。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;在数据库中存在与之相对应的记录。(前提条件是没有其他Session实例删除该条记录)。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <br />
一、预备知识<br />
对于hibernate，它的对象有三种状态，transient、persistent、detached<br />
下边是常见的翻译办法：<br />
transient：瞬态或者自由态<br />
&nbsp;&nbsp; &nbsp;(new DeptPo(1,&#8221;行政部&#8221;,20,&#8221;行政相关&#8221;)，该po的实例和session没有关联，该po的实例处于transient)<br />
persistent：持久化状态<br />
&nbsp;&nbsp; &nbsp;(和数据库中记录想影射的Po实例，它的状态是persistent, 通过get和load等得到的对象都是persistent)<br />
detached：脱管状态或者游离态<br />
&nbsp;&nbsp; &nbsp;(1)当通过get或load方法得到的po对象它们都处于persistent,但如果执行delete(po)时(但不能执行事务),该po状态就处于detached, (表示和session脱离关联),因delete而变成游离态可以通过save或saveOrUpdate()变成持久态<br />
&nbsp;&nbsp; &nbsp;(2)当把session关闭时，session缓存中的persistent的po对象也变成detached<br />
<br />
因关闭session而变成游离态的可以通过lock、save、update变成持久态<br />
持久态实例可以通过调用 delete()变成脱管状态。<br />
通过get()或load()方法得到的实例都是持久化状态的。<br />
脱管状态的实例可以通过调用lock()或者replicate()进行持久化。<br />
save()和persist()将会引发SQL的INSERT，delete()会引发SQLDELETE，<br />
而update()或merge()会引发SQL UPDATE。对持久化（persistent）实例的修改在刷新提交的时候会被检测到，它也会引起SQL UPDATE。<br />
saveOrUpdate()或者replicate()会引发SQL INSERT或者UPDATE<br />
<br />
二、save 和update区别<br />
&nbsp;&nbsp; &nbsp;把这一对放在第一位的原因是因为这一对是最常用的。<br />
&nbsp;&nbsp; &nbsp;save的作用是把一个新的对象保存<br />
&nbsp;&nbsp; &nbsp;update是把一个脱管状态的对象或自由态对象（一定要和一个记录对应）更新到数据库<br />
三、update 和saveOrUpdate区别<br />
&nbsp;&nbsp; &nbsp;这个是比较好理解的，顾名思义，saveOrUpdate基本上就是合成了save和update,而update只是update;引用hibernate reference中的一段话来解释他们的使用场合和区别<br />
&nbsp;&nbsp; &nbsp;通常下面的场景会使用update()或saveOrUpdate()：<br />
&nbsp;&nbsp; &nbsp;程序在第一个session中加载对象,接着把session关闭<br />
&nbsp;&nbsp; &nbsp;该对象被传递到表现层<br />
&nbsp;&nbsp; &nbsp;对象发生了一些改动<br />
&nbsp;&nbsp; &nbsp;该对象被返回到业务逻辑层最终到持久层<br />
&nbsp;&nbsp; &nbsp;程序创建第二session调用第二个session的update()方法持久这些改动<br />
&nbsp;&nbsp; &nbsp;saveOrUpdate(po)做下面的事:<br />
&nbsp;&nbsp; &nbsp;如果该po对象已经在本session中持久化了，在本session中执行saveOrUpdate不做任何事<br />
&nbsp;&nbsp; &nbsp;如果savaOrUpdate(新po)与另一个与本session关联的po对象拥有相同的持久化标识(identifier)，抛出一个异常<br />
&nbsp;&nbsp; &nbsp;org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.itfuture.www.po.Xtyhb#5]<br />
&nbsp;&nbsp; &nbsp;saveOrUpdate如果对象没有持久化标识(identifier)属性，对其调用save() ，否则update() 这个对象<br />
四、persist和save区别<br />
&nbsp;&nbsp; &nbsp;这个是最迷离的一对，表面上看起来使用哪个都行，在hibernate reference文档中也没有明确的区分他们.<br />
&nbsp;&nbsp; &nbsp;这里给出一个明确的区分。（可以跟进src看一下，虽然实现步骤类似，但是还是有细微的差别）<br />
&nbsp;&nbsp; &nbsp;主要内容区别：<br />
&nbsp;&nbsp; &nbsp;1，persist把一个瞬态的实例持久化，但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中，标识符的填入可能被推迟到flush的时候。<br />
&nbsp;&nbsp; &nbsp;2，save, 把一个瞬态的实例持久化标识符，及时的产生,它要返回标识符，所以它会立即执行Sql insert<br />
五、saveOrUpdate,merge和update区别<br />
&nbsp;&nbsp; &nbsp;比较update和merge<br />
&nbsp;&nbsp; &nbsp;update的作用上边说了，这里说一下merge的<br />
&nbsp;&nbsp; &nbsp;如果session中存在相同持久化标识(identifier)的实例，用用户给出的对象覆盖session已有的持久实例<br />
&nbsp;&nbsp; &nbsp;(1)当我们使用update的时候，执行完成后，会抛出异常<br />
&nbsp;&nbsp; &nbsp;(2)但当我们使用merge的时候，把处理自由态的po对象A的属性copy到session当中处于持久态的po的属性中，执行完成后原来是持久状态还是持久态，而我们提供的A还是自由态<br />
六、flush和update区别<br />
&nbsp;&nbsp; &nbsp;这两个的区别好理解<br />
&nbsp;&nbsp; &nbsp;update操作的是在自由态或脱管状态(因session的关闭而处于脱管状态)的对象//updateSQL<br />
&nbsp;&nbsp; &nbsp;而flush是操作的在持久状态的对象。<br />
&nbsp;&nbsp; &nbsp;默认情况下，一个持久状态的对象的改动（包含set容器）是不需要update的，只要你更改了对象的值，等待hibernate flush就自动更新或保存到数据库了。hibernate flush发生在以下几种情况中：<br />
&nbsp;&nbsp; &nbsp;1， 调用某些查询的和手动flush(),session的关闭、SessionFactory关闭结合<br />
&nbsp;&nbsp; &nbsp;get()一个对象，把对象的属性进行改变,把资源关闭。<br />
&nbsp;&nbsp; &nbsp;2，transaction commit的时候（包含了flush）<br />
七、lock和update区别<br />
&nbsp;&nbsp; &nbsp;update是把一个已经更改过的脱管状态的对象变成持久状态<br />
&nbsp;&nbsp; &nbsp;lock是把一个没有更改过的脱管状态的对象变成持久状态(针对的是因Session的关闭而处于脱管状态的po对象(2)，不能针对因delete而处于脱管状态的po对象)<br />
&nbsp;&nbsp; &nbsp;对应更改一个记录的内容，两个的操作不同：<br />
&nbsp;&nbsp; &nbsp;update的操作步骤是：<br />
&nbsp;&nbsp; &nbsp;(1)属性改动后的脱管的对象的修改-&gt;调用update<br />
&nbsp;&nbsp; &nbsp;lock的操作步骤是：<br />
&nbsp;&nbsp; &nbsp;(2)调用lock把未修改的对象从脱管状态变成持久状态--&gt;更改持久状态的对象的内容--&gt;等待flush或者手动flush<br />
八、clear和evcit的区别<br />
&nbsp;&nbsp; &nbsp;clear完整的清除session缓存<br />
&nbsp;&nbsp; &nbsp;evcit(obj)把某个持久化对象从session的缓存中清空。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
<img src ="http://www.blogjava.net/jjshcc/aggbug/328454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-08-10 23:39 <a href="http://www.blogjava.net/jjshcc/archive/2010/08/10/328454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决hibernate 删除异常：deleted object would be re-saved by cascade (remove deleted object from</title><link>http://www.blogjava.net/jjshcc/archive/2010/07/31/327664.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Sat, 31 Jul 2010 12:58:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/07/31/327664.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/327664.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/07/31/327664.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/327664.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/327664.html</trackback:ping><description><![CDATA[<div>
<p><font size="3">我遇到到是第三种</font></p>
<p><font size="3">解决hibernate 删除异常： deleted object would be re-saved by cascade (remove deleted object from associations) 收藏 <br />
在hibernate 删除关联时会出现eleted object would be re-saved by
cascade (remove deleted object from
associations)的异常，结合别人的和自己的经验通常有三种解决的方案：</font></p>
<p><font size="3">方法1 删除Set方的cascade：<br />
方法2 解决关联关系后，再删除</font></p>
<p><font size="3">&nbsp;&nbsp;&nbsp;  onside.getManys().remove(thisMany);&nbsp;&nbsp;  //在所关联的一方的set中移走当前要删除的对象<br />
&nbsp;&nbsp;&nbsp;  thisMany.setOne(null);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  //设置所对应的一方为空，解除它们之间的关系<br />
&nbsp;&nbsp;&nbsp;  manyDao.delete(thisMany);<br />
方法3 在many-to-one方增加cascade 但值不能是none</font></p>
</div>
<img src ="http://www.blogjava.net/jjshcc/aggbug/327664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-07-31 20:58 <a href="http://www.blogjava.net/jjshcc/archive/2010/07/31/327664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决could not initialize proxy - the owning Session was closed的方法</title><link>http://www.blogjava.net/jjshcc/archive/2010/06/23/324285.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Wed, 23 Jun 2010 15:23:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/06/23/324285.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/324285.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/06/23/324285.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/324285.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/324285.html</trackback:ping><description><![CDATA[<p><font>其实这个异常写的非常之清楚，就是会话关闭，无法对Hibernate实体进行操作。造成这样的情况有很多，什么书写错误啊，逻辑错误
啊,等等.不过,偶是因为LAZY.</font></p>
<p><font style="background-color: #ffffff;" color="#339966">关
于lazy机制：</font></p>
<p><font color="#0000ff">延迟初始化错误是运用Hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检
索策略，那么必须当代理类实例或代理集合处于持久化状态（即处于Session范围内）时，才能初始化它。如果在游离状态时才初始化它，就会产生延迟初始
化错误。</font></p>
<p><font>下面把Customer.hbm.xml文件的&lt;class&gt;元素的lazy属性设为true，表示使用延迟检索策略：</font></p>
<p><font>&lt;class name="mypack.Customer" table="CUSTOMERS"
lazy="true"&gt;</font></p>
<p><font>当执行Session的load()方法时，Hibernate不会立即执行查询CUSTOMERS表的select语句，仅仅返回
Customer类的代理类的实例，这个代理类具由以下特征：</font></p>
<p><font>（1）
由Hibernate在运行时动态生成，它扩展了Customer类，因此它继承了Customer类的所有属性和方法，但它的实现对于应用程序是透明
的。<br />
（2）
当Hibernate创建Customer代理类实例时，仅仅初始化了它的OID属性，其他属性都为null，因此这个代理类实例占用的内存很少。<br />
（3）当应用程序第一次访问Customer代理类实例时（例如调用customer.getXXX()或customer.setXXX()方法），
Hibernate会初始化代理类实例，在初始化过程中执行select语句，真正从数据库中加载Customer对象的所有数据。但有个例外，那就是当
应用程序访问Customer代理类实例的getId()方法时，Hibernate不会初始化代理类实例，因为在创建代理类实例时OID就存在了，不必
到数据库中去查询。</font></p>
<p><font>提示：Hibernate采用CGLIB工具来生成持久化类的代理类。CGLIB是一个功能强大的Java字节码生成工具，它能够在程
序运行时动态生成扩展
Java类或者实现Java接口的代理类。关于CGLIB的更多知识，请参考：</font></p>
<p><font>http://cglib.sourceforge.net/。</font></p>
<p><font>以下代码先通过Session的load()方法加载Customer对象，然后访问它的name属性： </font></p>
<p><font>tx = session.beginTransaction();<br />
Customer customer=(Customer)session.load(Customer.class,new Long(1));<br />
customer.getName();<br />
tx.commit();</font></p>
<p><font>在运行session.load()方法时Hibernate不执行任何select语句，仅仅返回Customer类的代理类的实
例，它的OID为1，这是由load()方法的第二个参数指定的。当应用程序调用customer.getName()方法时，Hibernate会初始
化Customer代理类实例，从数据库中加载Customer对象的数据，执行以下select语句：</font></p>
<p><font>select * from CUSTOMERS where ID=1;<br />
select * from ORDERS where CUSTOMER_ID=1;</font></p>
<p><font>当&lt;class&gt;元素的lazy属性为true，会影响Session的load()方法的各种运行时行为，下面举例说
明。</font></p>
<p><font>1．如果加载的Customer对象在数据库中不存在，Session的load()方法不会抛出异常，只有当运行
customer.getName()方法时才会抛出以下异常：</font></p>
<p><font>ERROR LazyInitializer:63 - Exception initializing proxy<br />
net.sf.hibernate.ObjectNotFoundException: No row with the given
identifier exists: 1, of class: <br />
mypack.Customer</font></p>
<p><font>2．如果在整个Session范围内，应用程序没有访问过Customer对象，那么Customer代理类的实例一直不会被初始
化，Hibernate不会执行任何select语句。以下代码试图在关闭Session后访问Customer游离对象：</font></p>
<p><font>tx = session.beginTransaction();<br />
Customer customer=(Customer)session.load(Customer.class,new Long(1));<br />
tx.commit();<br />
session.close();<br />
customer.getName();</font></p>
<p><font>由于引用变量customer引用的Customer代理类的实例在Session范围内始终没有被初始化，因此在执行
customer.getName()方法时，Hibernate会抛出以下异常：</font></p>
<p><font>ERROR LazyInitializer:63 - Exception initializing proxy<br />
net.sf.hibernate.HibernateException: Could not initialize proxy - the
owning Session was closed</font></p>
<p><font>由此可见，Customer代理类的实例只有在当前Session范围内才能被初始化。</font></p>
<p><font>3．net.sf.hibernate.Hibernate类的initialize()静态方法用于在Session范围内显式初始
化代理类实例，isInitialized()方法用于判断代理类实例是否已经被初始化。例如：</font></p>
<p><font>tx = session.beginTransaction();<br />
Customer customer=(Customer)session.load(Customer.class,new Long(1));<br />
if(!Hibernate.isInitialized(customer)) <br />
Hibernate.initialize(customer);<br />
tx.commit();<br />
session.close();<br />
customer.getName();</font></p>
<p><font>以上代码在Session范围内通过Hibernate类的initialize()方法显式初始化了Customer代理类实例，因
此当Session关闭后，可以正常访问Customer游离对象。</font></p>
<p><font>4．当应用程序访问代理类实例的getId()方法时，不会触发Hibernate初始化代理类实例的行为，例如：</font></p>
<p><font>tx = session.beginTransaction();<br />
Customer customer=(Customer)session.load(Customer.class,new Long(1));<br />
customer.getId();<br />
tx.commit();<br />
session.close();<br />
customer.getName();</font></p>
<p><font>当应用程序访问customer.getId()方法时，该方法直接返回Customer代理类实例的OID值，无需查询数据库。由于
引用变量
customer始终引用的是没有被初始化的Customer代理类实例，因此当Session关闭后再执行customer.getName()方法，
Hibernate会抛出以下异常：</font></p>
<p><font>ERROR LazyInitializer:63 - Exception initializing proxy<br />
net.sf.hibernate.HibernateException: Could not initialize proxy - the
owning Session was closed</font></p>
<font>
<p><br />
解决方法：</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异常》</p>
<p>?<br />
解决方法:在web.xml中加入<br />
&lt;filter&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.orm.hibernate3.support.OpenSessionInViewFilter<br />
&nbsp;&nbsp;&nbsp; &lt;/filter-class&gt;<br />
&lt;/filter<br />
&lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&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>Interceptor的配置:</p>
<p><br />
&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; </p>
<p>&lt;/bean&gt; </p>
<p>&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><br />
&lt;web-app&gt; </p>
<p>&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; </p>
<p>&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; </p>
<p>&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><br />
在业务逻辑层中使用延迟加载</p>
<p>即使在视图外面，Spring框架也通过使用AOP 拦截器
HibernateInterceptor来使得延迟加载变得很容易实现。这个Hibernate
拦截器透明地将调用配置在Spring应用程序上下文中的业务对象中方法的请求拦截下来，在调用方法之前打开一个Hibernate会话，然后在方法执行
完之后将会话关闭。让我们来看一个简单的例子，假设我们有一个接口BussinessObject：</p>
<p><br />
public&nbsp;&nbsp;&nbsp;&nbsp; interface&nbsp;&nbsp;&nbsp; BusinessObject&nbsp;&nbsp;&nbsp;&nbsp; { <br />
public&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp; doSomethingThatInvolvesDaos(); <br />
} <br />
类BusinessObjectImpl实现了BusinessObject接口:</p>
<p>public&nbsp;&nbsp;&nbsp;&nbsp; class&nbsp;&nbsp;&nbsp; BusinessObjectImpl&nbsp;&nbsp;&nbsp; implements&nbsp;&nbsp;&nbsp;
BusinessObject&nbsp;&nbsp;&nbsp;&nbsp; { <br />
public&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp; doSomethingThatInvolvesDaos()&nbsp;&nbsp;&nbsp;&nbsp; { <br />
//&nbsp;&nbsp;&nbsp; lots of logic that calls <br />
//&nbsp;&nbsp;&nbsp; DAO classes Which access <br />
//&nbsp;&nbsp;&nbsp; data objects lazily&nbsp; <br />
}&nbsp; <br />
}&nbsp; </p>
<p>&nbsp;</p>
<p>通过在Spring应用程序上下文中的一些配置，我们可以让将调用BusinessObject的方法拦截下来，再令它的方法支持延迟加载。看看下
面的一个程序片段：</p>
<p>&nbsp;</p>
<p>&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 />
} </p>
</font>
<img src ="http://www.blogjava.net/jjshcc/aggbug/324285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-06-23 23:23 <a href="http://www.blogjava.net/jjshcc/archive/2010/06/23/324285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于An association from the table refers to an unmapped class</title><link>http://www.blogjava.net/jjshcc/archive/2010/05/12/320705.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Wed, 12 May 2010 07:24:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/05/12/320705.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/320705.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/05/12/320705.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/320705.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/320705.html</trackback:ping><description><![CDATA[&nbsp;1,检查你的hibernate.cfg.xml文件中是否添加了&nbsp;&nbsp;&lt;mapping resource="xxxx.hbm.xml"/&gt; <br />
2,检查你的hibernate.cfg.xml文件中的相关联的两个&lt;mapping resource=""/&gt;的顺序，可能有其中一个需要引用另一个，但是另一个却还没有编译，就是说被用作外键的表要放在前面<br />
3,检查你的*.hbm.xml文件名是否正确<br />
4,&nbsp;检查你的*.hbm.xml里面类全名
<img src ="http://www.blogjava.net/jjshcc/aggbug/320705.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-05-12 15:24 <a href="http://www.blogjava.net/jjshcc/archive/2010/05/12/320705.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的基本映射数据类型</title><link>http://www.blogjava.net/jjshcc/archive/2010/05/11/320601.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Tue, 11 May 2010 09:15:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/05/11/320601.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/320601.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/05/11/320601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/320601.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/320601.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 表4-4&nbsp; 3种数据类型之间的对应关系                                    Hibernate映射类型                                    Java类型                                    标准SQL类型              ...&nbsp;&nbsp;<a href='http://www.blogjava.net/jjshcc/archive/2010/05/11/320601.html'>阅读全文</a><img src ="http://www.blogjava.net/jjshcc/aggbug/320601.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-05-11 17:15 <a href="http://www.blogjava.net/jjshcc/archive/2010/05/11/320601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java数据类型，Hibernate数据类型，标准sql数据类型之间的对应表 </title><link>http://www.blogjava.net/jjshcc/archive/2010/05/11/320599.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Tue, 11 May 2010 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/05/11/320599.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/320599.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/05/11/320599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/320599.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/320599.html</trackback:ping><description><![CDATA[<div class="postTitle"><a id="viewpost1_TitleUrl" class="postTitle2" href="http://www.blogjava.net/haoqingshi/articles/10912.html">Java数据类型，Hibernate数据类型，标准sql数据类型之间的对应表</a> </div>
<table style="text-align: left; width: 100%" border="1" cellspacing="2" cellpadding="2">
    <tbody>
        <tr>
            <td style="background-color: rgb(204,204,204)"><small>Java数据类型</small></td>
            <td style="background-color: rgb(204,204,204)"><small>Hibernate数据类型</small></td>
            <td style="background-color: rgb(204,204,204)"><small>标准SQL数据类型<br />
            (PS:对于不同的DB可能有所差异)</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>
 <img src ="http://www.blogjava.net/jjshcc/aggbug/320599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-05-11 16:49 <a href="http://www.blogjava.net/jjshcc/archive/2010/05/11/320599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate的表结构以及表之间的关系的　*.hbm.xml</title><link>http://www.blogjava.net/jjshcc/archive/2010/05/11/320584.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Tue, 11 May 2010 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/05/11/320584.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/320584.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/05/11/320584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/320584.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/320584.html</trackback:ping><description><![CDATA[<div>假设有一个实体类，用于存放用户信息，其定义如下：</div>
<div>
<hr id="null" />
</div>
<div>package events;</div>
<div>import java.util.*;</div>
<div>public class Person {</div>
<div>&nbsp;&nbsp;&nbsp; private Long id;<br />
&nbsp;&nbsp;&nbsp; private int age;<br />
&nbsp;&nbsp;&nbsp; private String firstname;<br />
&nbsp;&nbsp;&nbsp; private String lastname;</div>
<div>&nbsp;&nbsp;&nbsp; public Person() {}</div>
<div><br />
&nbsp;&nbsp;&nbsp; public Long getId() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return id;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void setId(Long id) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.id = id;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public int getAge() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return age;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void setAge(int age) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.age = age;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public String getFirstname() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return firstname;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void setFirstname(String firstname) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.firstname = firstname;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public String getLastname() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return lastname;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void setLastname(String lastname) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.lastname = lastname;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div><br />
&nbsp;&nbsp;&nbsp; private Set emailAddresses = new HashSet();</div>
<div>&nbsp;&nbsp;&nbsp; public Set getEmailAddresses() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return emailAddresses;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void setEmailAddresses(Set emailAddresses) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.emailAddresses = emailAddresses;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div><br />
&nbsp;&nbsp;&nbsp; private Set events = new HashSet();</div>
<div>&nbsp;&nbsp;&nbsp; // Defensive, convenience methods<br />
&nbsp;&nbsp;&nbsp; protected Set getEvents() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return events;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; protected void setEvents(Set events) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.events = events;<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void addToEvent(Event event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.getEvents().add(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event.getParticipants().add(this);<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; public void removeFromEvent(Event event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.getEvents().remove(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event.getParticipants().remove(this);<br />
&nbsp;&nbsp;&nbsp; }</div>
<div>}</div>
<div>
<hr id="null" />
</div>
<div>&nbsp;</div>
<div>则相应的描述POJO---&gt;Person.hbm.xml中的配置信息如下：<br />
<hr id="null" />
&lt;?xml version="1.0"?&gt;<br />
&lt;!DOCTYPE hibernate-mapping PUBLIC<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>"&gt;<br />
&lt;hibernate-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;class name="events.Person" table="PERSON"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;id name="id" column="PERSON_ID"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="identity" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/id&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="age" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="firstname" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="lastname" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="events" table="PERSON_EVENT"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="PERSON_ID" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-many column="EVENT_ID" class="events.Event" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="emailAddresses" table="PERSON_EMAIL_ADDR"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="PERSON_ID" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;element type="string" column="EMAIL_ADDR" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/class&gt;<br />
&lt;/hibernate-mapping&gt;<br />
<hr id="null" />
<br />
说明：</div>
<div>１．class 节点</div>
<div>
<table border="1" cellspacing="1" cellpadding="1" width="85%">
    <tbody>
        <tr>
            <td>
            <p><strong>name</strong>: 类名<br />
            <br />
            <strong>table</strong>: 类对应表名，默认为类名称<br />
            <br />
            <strong>dynamic-update</strong>: 生成更新字段时，只包含发生变动的字段，默认为false。<br />
            <br />
            <strong>dynamic-insert</strong>:　生成insert语句时仅包含非null字段<br />
            <br />
            <strong>Proxy</strong>: 代理类，默认为空<br />
            <br />
            <strong>discriminator-value</strong>: 子类辨别标识用于多态支持<br />
            <br />
            <strong>where</strong>:　通过限定条件查询结果集。如：查询有籍在校学生的信息可以使用"where studentstatus='0'"</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>2.id节点<br />
<table border="1" cellspacing="1" cellpadding="1" width="85%">
    <tbody>
        <tr>
            <td>
            <p>1.column&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字段名称<br />
            2.type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字段类型<br />
            3.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字段长度<br />
            4.unsaved-value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用于判断对象值是否已经保存<br />
            5.generator-class&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主键产生方式<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assigned<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hilo<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seqhilo<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; increment<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; identity<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sequence<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; native<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid.hex<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid.string<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreign</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<br />
3.property 节点<br />
<table border="1" cellspacing="1" cellpadding="1" width="85%">
    <tbody>
        <tr>
            <td>
            <p>1.column&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库表字段名称<br />
            2.type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型<br />
            3.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 长度<br />
            4.not-null&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字段是否允许为空<br />
            5.unique&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;字段是否允许唯一（是否允许重复值）<br />
            6.insert&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insert操作时，是否允许包含本字段数值<br />
            7.update&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update操作时，是否包含本字段数据</p>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<br />
<br />
</p>
<div>Event.hbm.xml</div>
<div>
<hr id="null" />
&lt;?xml version="1.0"?&gt;<br />
&lt;!DOCTYPE hibernate-mapping PUBLIC<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>"&gt;<br />
&lt;hibernate-mapping&gt;<br />
&nbsp;&lt;class name="events.Event" table="EVENTS"&gt;<br />
&nbsp;&nbsp;&lt;id name="id" column="EVENT_ID"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;generator class="native" /&gt;<br />
&nbsp;&nbsp;&lt;/id&gt;<br />
&nbsp;&nbsp;&lt;property name="date" type="timestamp" column="EVENT_DATE" /&gt;<br />
&nbsp;&nbsp;&lt;property name="title" /&gt;<br />
&nbsp;&nbsp;&lt;set name="participants" table="PERSON_EVENT" inverse="true"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;key column="EVENT_ID" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;many-to-many column="PERSON_ID" class="events.Person" /&gt;<br />
&nbsp;&nbsp;&lt;/set&gt;<br />
&nbsp;&lt;/class&gt;<br />
&lt;/hibernate-mapping&gt;<br />
</div>
<img src ="http://www.blogjava.net/jjshcc/aggbug/320584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-05-11 14:06 <a href="http://www.blogjava.net/jjshcc/archive/2010/05/11/320584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Hibernate的客户化映射类型 </title><link>http://www.blogjava.net/jjshcc/archive/2010/05/11/320575.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Tue, 11 May 2010 03:40:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/05/11/320575.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/320575.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/05/11/320575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/320575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/320575.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;Hibernate提供客户化映射类型接口，使用户能以编程方式创建自定义的映射类型来将持久化类任意类型的属性映射到数据库中。使用客户化映射类型，需要实现org.hibernate.usertype.UserType接口。这是个强大的功能，也是Hibernate的最佳实践之一。我们经常提到ORM中很困难的一点便是O的属性和R的属性不能一一映射，而Hibernate提供的UserType无疑给出了一个很好的解决方案。本文给出使用客户化映射类型的两个例子，算是对Hibernate初学者的抛砖。<br />
&nbsp;&nbsp; &nbsp;第一个例子是使用UserType映射枚举类型。假设Account表中含有一sex列，类型为tinyint（当前其0代表男，1代表女，将来可能出现2等代表其他性别类型）；我们当然可以在对应的Account类中添加int类型的sex属性，但这种数字化无显示意义且类型不安全的枚举不是很好的解决方式，这里就采用了java5的enum来作为Account类的性别属性（如果不熟悉java5的enum，也可采用《effective java》中提到的经典的类型安全的枚举方案）。在Account添加enum Gender：<br />
<br />
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;Account&nbsp;</span><span style="color: rgb(0,0,255)">extends</span><span style="color: rgb(0,0,0)">&nbsp;AbstractDomain</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">Long</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">enum</span><span style="color: rgb(0,0,0)">&nbsp;Gender{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Male(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">male</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">,</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Female(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">female</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">,</span><span style="color: rgb(0,0,0)">1</span><span style="color: rgb(0,0,0)">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;getName()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;getValue()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;Gender(String&nbsp;name,</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;value){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.name&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.value&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;Gender&nbsp;getGender(</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;value){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;value)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;Male;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(</span><span style="color: rgb(0,0,0)">1</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;value)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;Female;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">throw</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;RuntimeException();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;Gender&nbsp;gender;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Gender&nbsp;getGender()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;gender;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;setGender(Gender&nbsp;gender)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.gender&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;gender;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">省略其他&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,0,0)">}</span></div>
<br />
&nbsp;&nbsp; &nbsp;接下来定义实现UserType接口的GenderUserType：<br />
<br />
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;GenderUserType&nbsp;</span><span style="color: rgb(0,0,255)">implements</span><span style="color: rgb(0,0,0)">&nbsp;UserType{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;assemble(Serializable&nbsp;arg0,&nbsp;Object&nbsp;arg1)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;这是用于Hibernate缓存生成的快照，由于Gender是不可变的，直接返回就好了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;deepCopy(Object&nbsp;arg0)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;arg0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Serializable&nbsp;disassemble(Object&nbsp;arg0)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;由于Gender是不可变的，因此直接==了，这个方法将在insert、update时用到。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;equals(Object&nbsp;x,&nbsp;Object&nbsp;y)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;x&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;y;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;hashCode(Object&nbsp;o)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;o.hashCode();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;表明Gender是不是可变类（很重要的概念哦），这里的Gender由于是枚举所以是不可变的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;isMutable()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;从ResultSet读取sex并返回Gender实例，这个方法是在从数据库查询数据时用到。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;nullSafeGet(ResultSet&nbsp;rs,&nbsp;String[]&nbsp;names,&nbsp;Object&nbsp;owner)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException,&nbsp;SQLException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;value&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;rs.getInt(names[</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;Account.Gender.getGender(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;将Gender的value设置到PreparedStatement。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;nullSafeSet(PreparedStatement&nbsp;ps,&nbsp;Object&nbsp;value,&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;index)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException,&nbsp;SQLException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(value == null){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ps.setInt(index,Account.Gender.Male.getValue());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }else{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ps.setInt(index,((Account.Gender)value).getValue());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;replace(Object&nbsp;arg0,&nbsp;Object&nbsp;arg1,&nbsp;Object&nbsp;arg2)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;设置映射的Gender类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Class&nbsp;returnedClass()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;Account.Gender.</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;设置Gender枚举中的value属性对应的Account表中的sex列的SQL类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">[]&nbsp;sqlTypes()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">[]&nbsp;typeList&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;{Types.TINYINT};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;typeList;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
&nbsp;&nbsp; &nbsp;最后在Account的配置文件中配置gender属性就好了：<br />
&lt;property name="gender" type="org.prague.domain.util.GenderUserType" column="sex"&gt;&lt;/property&gt;<br />
&nbsp;&nbsp; &nbsp;除了可以使用 UserType映射枚举类型，也可以使用Hibernate的PersistentEnum来实现同样的功能，感兴趣的朋友可以参考文章http://www.hibernate.org/203.html。<br />
<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;第二个例子是关于email的。假设Account表中email是一个varchar型的字段，而Account中的Email是如下的类：<br />
<br />
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;Email&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;username;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;domain;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Email()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Email(String&nbsp;username,&nbsp;String&nbsp;domain)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.username&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;username;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.domain&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;domain;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;getUsername()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;username;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;getDomain()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;domain;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;setDomain(String&nbsp;domain)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.domain&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;domain;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;setUsername(String&nbsp;username)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.username&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;username;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;toString()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;username&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">'</span><span style="color: rgb(0,0,0)">@</span><span style="color: rgb(0,0,0)">'</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;domain;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;Email&nbsp;parse(String&nbsp;email)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email&nbsp;e&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Email();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;at&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;email.indexOf(</span><span style="color: rgb(0,0,0)">'</span><span style="color: rgb(0,0,0)">@</span><span style="color: rgb(0,0,0)">'</span><span style="color: rgb(0,0,0)">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(at&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">-</span><span style="color: rgb(0,0,0)">1</span><span style="color: rgb(0,0,0)">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">throw</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;IllegalArgumentException(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">Invalid&nbsp;email&nbsp;address</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.username&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;email.substring(</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">,&nbsp;at);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.domain&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;email.substring(at&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">1</span><span style="color: rgb(0,0,0)">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;e;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;hashCode()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;PRIME&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">31</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;result&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">1</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;PRIME&nbsp;</span><span style="color: rgb(0,0,0)">*</span><span style="color: rgb(0,0,0)">&nbsp;result&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;((domain&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)&nbsp;</span><span style="color: rgb(0,0,0)">?</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">&nbsp;:&nbsp;domain.hashCode());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;PRIME&nbsp;</span><span style="color: rgb(0,0,0)">*</span><span style="color: rgb(0,0,0)">&nbsp;result&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;((username&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)&nbsp;</span><span style="color: rgb(0,0,0)">?</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">&nbsp;:&nbsp;username.hashCode());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;equals(Object&nbsp;obj)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;obj)&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">true</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;obj)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(getClass()&nbsp;</span><span style="color: rgb(0,0,0)">!=</span><span style="color: rgb(0,0,0)">&nbsp;obj.getClass())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;Email&nbsp;other&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(Email)&nbsp;obj;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(domain&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(other.domain&nbsp;</span><span style="color: rgb(0,0,0)">!=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">!</span><span style="color: rgb(0,0,0)">domain.equals(other.domain))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(username&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(other.username&nbsp;</span><span style="color: rgb(0,0,0)">!=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">!</span><span style="color: rgb(0,0,0)">username.equals(other.username))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">true</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
&nbsp;&nbsp;&nbsp;&nbsp;email是Account类的一个属性：<br />
</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;Account&nbsp;</span><span style="color: rgb(0,0,255)">extends</span><span style="color: rgb(0,0,0)">&nbsp;AbstractDomain</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">Long</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;Email&nbsp;email;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Email&nbsp;getEmail()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;email;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;setEmail(Email&nbsp;email)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.email&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;email;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">省略其他&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,0,0)">}</span></div>
<br />
&nbsp;&nbsp; &nbsp;这样的情况下，需要将email的username + '@' + domain映射到Account表的email列，定义一个EmailUserType如下：<br />
&nbsp;
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;EmailUserType&nbsp;</span><span style="color: rgb(0,0,255)">implements</span><span style="color: rgb(0,0,0)">&nbsp;UserType{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;assemble(Serializable&nbsp;arg0,&nbsp;Object&nbsp;arg1)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;deepCopy(Object&nbsp;o)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;o)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email&nbsp;e&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(Email)o;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Email(e.getUsername(),e.getDomain());<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Serializable&nbsp;disassemble(Object&nbsp;arg0)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;equals(Object&nbsp;x,&nbsp;Object&nbsp;y)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(x&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;y)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">true</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(x&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">||</span><span style="color: rgb(0,0,0)">&nbsp;y&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;f&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;x.equals(y);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;hashCode(Object&nbsp;o)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;o.hashCode();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;isMutable()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">true</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;nullSafeGet(ResultSet&nbsp;rs,&nbsp;String[]&nbsp;names,&nbsp;Object&nbsp;o)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException,&nbsp;SQLException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;email&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;rs.getString(names[</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(email&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;index&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;email.indexOf(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">@</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(index&nbsp;</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">)</span><span style="color: rgb(0,0,255)">throw</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;RuntimeException();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Email(email.substring(</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,0)">,index),email.substring(index</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">1</span><span style="color: rgb(0,0,0)">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;nullSafeSet(PreparedStatement&nbsp;ps,&nbsp;Object&nbsp;o,&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;index)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException,&nbsp;SQLException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(o&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;)ps.setNull(index,&nbsp;Types.VARCHAR);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email&nbsp;e&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(Email)o;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">(e.getDomain()&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">||</span><span style="color: rgb(0,0,0)">&nbsp;e.getUsername()&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)ps.setNull(index,&nbsp;Types.VARCHAR);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;email&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;e.getUsername()&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">@</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;e.getDomain();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setString(index,&nbsp;email);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;replace(Object&nbsp;arg0,&nbsp;Object&nbsp;arg1,&nbsp;Object&nbsp;arg2)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;HibernateException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Class&nbsp;returnedClass()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;Email.</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">[]&nbsp;sqlTypes()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">[]&nbsp;typeList&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;{Types.VARCHAR};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;typeList;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
&nbsp;&nbsp; &nbsp;最后配置下 email 属性：<br />
&lt;property name="email" type="org.prague.domain.util.EmailUserType" column="email"&gt;&lt;/property&gt;<br />
&nbsp;&nbsp; &nbsp;相比于Gedner，Email是一个可变类（如果想将其变为不可变类，只需要去掉属性的set方法），因此EmailUserType中的equals要用到Email的equals（hashCode()）方法，而deepCopy(Object o) 要做到是深拷贝，否则即便Email属性内容改变，由于Hibernate缓存中的快照指向的对象不变，在update时可能不起作用（在指定了dynamic-update属性的清况下）。<br />
 <img src ="http://www.blogjava.net/jjshcc/aggbug/320575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-05-11 11:40 <a href="http://www.blogjava.net/jjshcc/archive/2010/05/11/320575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>