﻿<?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-Sealyu-随笔分类-Hibernate</title><link>http://www.blogjava.net/sealyu/category/30668.html</link><description>--- The devil's in the Details</description><language>zh-cn</language><lastBuildDate>Mon, 26 Apr 2010 05:47:09 GMT</lastBuildDate><pubDate>Mon, 26 Apr 2010 05:47:09 GMT</pubDate><ttl>60</ttl><item><title>Hibernate中Criteria的完整用法(转)</title><link>http://www.blogjava.net/sealyu/archive/2010/04/24/319238.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Fri, 23 Apr 2010 21:55:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/04/24/319238.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/319238.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/04/24/319238.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/319238.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/319238.html</trackback:ping><description><![CDATA[最近在项目中使用 Spring 和 Hibernate 进行开发，有感于 Criteria 比较好用，在查询方法<br />
<br />
<font face="Times New Roman" size="4">设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装。现在对
Hibernate的Criteria 的用法进行总结：</font><br />
<font face="Times New Roman" size="4">&nbsp;&nbsp; Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口，下面提供了
Criteria和DetachedCriteria </font>。 <br />
&nbsp;&nbsp; Criteria 和 DetachedCriteria
的主要区别在于创建的形式不一样， Criteria 是在线的，所<br />
<font face="Times New Roman" size="4">以它是由 Hibernate Session 进行创建的；而 DetachedCriteria 是离线的，创建时无需 </font><br />
<font face="Times New Roman" size="4">Session，DetachedCriteria 提供了 2 个静态方法
forClass(Class) 或 forEntityName(Name) </font><br />
<font face="Times New
Roman" size="4">进行DetachedCriteria 实例的创建。 Spring
的框架提供了getHibernateTemplate</font><br />
<font face="Times New Roman" size="4">().findByCriteria(detachedCriteria) 方法可以很方便地根据DetachedCriteria
来返回查询结</font><br />
<font face="Times New Roman" size="4">果。 <br />
&nbsp;&nbsp;
Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 设置查询条件。可以设</font><br />
<font face="Times New Roman" size="4">置 FetchMode( 联合查询抓取的模式 ) ，设置排序方式。对于
Criteria 还可以设置 FlushModel </font><br />
<font face="Times New Roman" size="4">（冲刷 Session 的方式）和 LockMode （数据库锁模式）。 </font><br />
<font face="Times New Roman" size="4">下面对 Criterion 和 Projection 进行详细说明。</font><br />
<font face="Times New Roman" size="4">&nbsp;&nbsp;&nbsp;&nbsp; Criterion 是 Criteria
的查询条件。Criteria 提供了 add(Criterion criterion) 方法来</font><br />
<font face="Times New Roman" size="4">添加查询条件。<br />
&nbsp;&nbsp;&nbsp;&nbsp; Criterion 接口的主要实现包括：
Example 、 Junction 和 SimpleExpression 。而 </font><br />
<font face="Times
New Roman" size="4">Junction 的实际使用是它的两个子类 conjunction 和 disjunction
，分别是使用 AND 和 OR 操</font><br />
<font face="Times New Roman" size="4">作符进行来联
结查询条件集合。<br />
&nbsp;&nbsp;&nbsp;&nbsp; Criterion 的实例可以通过 Restrictions 工具类来创建，Restrictions
提供了大量的静态</font><br />
<font face="Times New Roman" size="4">方法，如 eq （等于）、
ge （大于等于）、 between 等来方法的创建 Criterion 查询条件 </font><br />
<font face="Times
New Roman" size="4">（SimpleExpression 实例）。除此之外， Restrictions 还提供了方法来创建
conjunction 和 </font><br />
<font face="Times New Roman" size="4">disjunction
实例，通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合</font><br />
<font face="Times New Roman" size="4">。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 至于 Example 的创建有所不同， Example
本身提供了一个静态方法 create(Object </font><br />
<font face="Times New Roman" size="4">entity) ，即根据一个对象（实际使用中一般是映射到数据库的对象）来创建。然后可以设置一些</font><br />
<font face="Times New Roman" size="4">过滤条件： <br />
Example exampleUser
=Example.create(u) <br />
.ignoreCase() // 忽略大小写 <br />
.enableLike(MatchMode.ANYWHERE);
<br />
// 对 String 类型的属性，无论在那里值在那里都匹配。相当于 %value% </font><br />
<font face="Times New Roman" size="4">&nbsp; Project 主要是让 Criteria
能够进行报表查询，并可以实现分组。 Project 主要有 </font><br />
<font face="Times New Roman" size="4">SimpleProjection 、 ProjectionList 和 Property 三个实现。其中
SimpleProjection 和 </font><br />
<font face="Times New Roman" size="4">ProjectionList
的实例化是由内建的 Projections 来完成，如提供的 avg 、 count 、 max 、 </font><br />
<font face="Times New Roman" size="4">min 、 sum 可以让开发者很容易对某个字段进行统计查询。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Property 是对某个字段进行查询条件的设置，如通过Porperty.forName(&#8220;color&#8221;).in</font><br />
<font face="Times New Roman" size="4">(new String[]{&#8220;black&#8221;,&#8221;red&#8221;,&#8221;write&#8221;});
则可以创建一个 Project 实例。通过 </font><br />
<font face="Times New Roman" size="4">criteria
的 add(Project) 方法加入到查询条件中去。 </font><br />
<font face="Times New Roman" size="4">&nbsp;&nbsp;&nbsp; 使用 Criteria 进行查询，主要要清晰的是 Hibernate 提供了那些类和方法来满足开发中查</font><br />
<font face="Times New Roman" size="4">询条件的创建和组装，下面介绍几种用法：</font><br />
<font face="Times New Roman" size="4">1. 创建一个Criteria 实例<br />
org.hibernate.Criteria
接口表示特定持久类的一个查询。Session是 Criteria实例的工厂。<br />
Criteria crit =
sess.createCriteria(Cat.class);<br />
crit.setMaxResults(50);<br />
List cats =
crit.list();<br />
&nbsp;<br />
2. 限制结果集内容<br />
一个单独的查询条件是
org.hibernate.criterion.Criterion 接口的一个实例。</font><br />
<br />
<font face="Times New Roman" size="4">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();</font><br />
<br />
<font face="Times New Roman" size="4">约束可以按逻辑分组。 <br />
&nbsp;<br />
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();<br />
&nbsp;<br />
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();<br />
&nbsp;<br />
Hibernate提供了相当多的内置criterion类型(Restrictions 子类),
但是尤其有用的是可以允许</font><br />
<br />
<font face="Times New Roman" size="4">你直接使用
SQL。<br />
&nbsp;<br />
List cats = sess.createCriteria(Cat.class)<br />
&nbsp;&nbsp;&nbsp; .add(
Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", </font><br />
<br />
<font face="Times New Roman" size="4">Hibernate.STRING) )<br />
&nbsp;&nbsp;&nbsp; .list();<br />
&nbsp;<br />
{alias}
占位符应当被替换为被查询实体的列别名。 <br />
Property实例是获得一个条件的另外一种途径。你可以通过调用
Property.forName() 创建一个</font><br />
<br />
<font face="Times New Roman" size="4">Property。 <br />
&nbsp;<br />
&nbsp; 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();<br />
&nbsp;<br />
3. 结果集排序<br />
你可以使用org.hibernate.criterion.Order来为查询结果排
序。 <br />
&nbsp;<br />
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();<br />
&nbsp;<br />
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();<br />
&nbsp;<br />
4. 关联<br />
你可以使用createCriteria()非常容易的在互相关联的实体间建立 约束。<br />
&nbsp;<br />
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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
注意第二个 createCriteria()返回一个新的
Criteria实例，该实例引用kittens 集合中的元素。 <br />
接下来，替换形态在某些情况下也是很有用的。<br />
&nbsp;<br />
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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
(createAlias()并不创建一个新的 Criteria实例。)
<br />
Cat实例所保存的之前两次查询所返回的kittens集合是 没有被条件预过滤的。如果你希望只获得</font><br />
<br />
<font face="Times New Roman" size="4">符合条件的kittens， 你必须使用returnMaps()。 <br />
&nbsp;<br />
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 />
}</font><br />
<br />
<font face="Times New Roman" size="4">5. 动态关联抓取<br />
你可以使用setFetchMode()在运行时定义动
态关联抓取的语义。 <br />
&nbsp;<br />
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();<br />
&nbsp;<br />
这个查询可以通过外连接抓取mate和kittens。<br />
&nbsp;<br />
6. 查询示例<br />
org.hibernate.criterion.Example
类允许你通过一个给定实例 构建一个条件查询。<br />
&nbsp;<br />
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();</font><br />
<br />
<font face="Times
New Roman" size="4"><br />
版本属性、标识符和关联被忽略。默认情况下值为null的属性将被排除。 <br />
可以自行调整
Example使之更实用。 <br />
&nbsp;<br />
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")&nbsp; //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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
甚至可以使用
examples在关联对象上放置条件。<br />
&nbsp;<br />
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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
7.
投影(Projections)、聚合（aggregation）和分组（grouping）<br />
org.hibernate.criterion.Projections
是 Projection 的实例工厂。我们通过调用 </font><br />
<br />
<font face="Times New Roman" size="4">setProjection()应用投影到一个查询。 <br />
&nbsp;<br />
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();<br />
&nbsp;<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() )<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();</font><br />

<p><font face="Times New Roman" size="4"><br />
在一个条件查询中没有必要显式的使用 "group
by" 。某些投影类型就是被定义为 分组投影，他</font><br />
<br />
<font face="Times New Roman" size="4">们也出现在SQL的group by子句中。 </font><br />
<br />
<font face="Times New
Roman" size="4">可以选择把一个别名指派给一个投影，这样可以使投影值被约束或排序所引用。下面是两种不同的</font><br />
<br />
<font face="Times New Roman" size="4">实现方式：<br />
&nbsp;<br />
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();</font></p>
<br />

<font face="Times New Roman" size="4">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();<br />
&nbsp;<br />
alias()和as()方法简便的将一个投影实例包装到另
外一个 别名的Projection实例中。简而言之，</font><br />
<br />
<font face="Times New Roman" size="4">当你添加一个投影到一个投影列表中时 你可以为它指定一个别名： <br />
&nbsp;<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(),
"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();</font><br />
<br />
<font face="Times New Roman" size="4"><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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
也可以使用
Property.forName()来表示投影：<br />
&nbsp;<br />
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();</font><br />
<font face="Times New Roman" size="4">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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
8. 离线(detached)查询和子查询<br />
DetachedCriteria
类使你在一个session范围之外创建一个查询，并且可以使用任意的 Session来</font><br />
<br />
<font face="Times New Roman" size="4">执行它。<br />
&nbsp;<br />
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();</font><br />
<br />
<font face="Times New Roman" size="4"><br />
DetachedCriteria也可以用以表示子查询。条件实例包含子查
询可以通过 Subqueries或者</font><br />
<font face="Times New Roman" size="4">Property
获得。<br />
&nbsp;<br />
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();</font><br />
<font face="Times New Roman" size="4">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();</font><br />
<font face="Times New Roman" size="4"><br />
相互关联的子查询也是有可能的：<br />
&nbsp;<br />
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();</font>
<img src ="http://www.blogjava.net/sealyu/aggbug/319238.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-04-24 05:55 <a href="http://www.blogjava.net/sealyu/archive/2010/04/24/319238.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>illegal attempt to dereference collection(转)</title><link>http://www.blogjava.net/sealyu/archive/2010/04/23/319225.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Fri, 23 Apr 2010 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/04/23/319225.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/319225.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/04/23/319225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/319225.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/319225.html</trackback:ping><description><![CDATA[<p>首先说一句：是版本的问题!</p>
<p>我写的hql为：</p>
<p>from Department as d where
d.employees.name='Tom';</p>
<p>运行时出现异常：org.hibernate.QueryException:
illegal attempt to dereference collection </p>
<p>是因为：在上面的HQL语句
中，Department的关联实体employees是一个集合，而不直接是一个Employee实体。</p>
<p>在
Hibernate3.2.2以前的版本，Hibernate会对关联实体自动使用隐式的inner join，</p>
<p>也就是说如下SQL语句
不会有任何问题&nbsp;:from Department as d where d.employees.name='Tom';</p>
<p>从
Hibernate3.2.3以后，Hibernate改变了这种隐式的inner join的策略 </p>
<p>对于如下这条语句：</p>
<p>from
Department as d where d.employees.name='Tom';</p>
<p>如果employees是普通组件属
性，或单个的关联实体，则Hibernate会自动生成隐式的inner join </p>
<p>如果myEvents是也一个集合，那么对不起！系
统将会出现 org.hibernate.QueryException: illegal attempt to dereference
collection异常。<br />
据Hibernate官方说法: <br />
这样可以让这使得隐含关联更具确定性（原文：This makes
implicit joins more deterministic ）。</p>
<p>推荐这样写：</p>
from Department as d inner join fetch
d.employees e where e.name='Tom';
<img src ="http://www.blogjava.net/sealyu/aggbug/319225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-04-23 22:44 <a href="http://www.blogjava.net/sealyu/archive/2010/04/23/319225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>getHibernateTemplate()和getSession()的区别（转）</title><link>http://www.blogjava.net/sealyu/archive/2010/02/22/313642.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 22 Feb 2010 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/02/22/313642.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/313642.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/02/22/313642.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/313642.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/313642.html</trackback:ping><description><![CDATA[<div>
<p>在前一篇日志中自动生成hibernate配置文件的时候，会在dao层用到getSession()方法来操作数据库记录，但是他还有个方法getHibernateTemplate()，这两个方法究竟有什么区别呢？</p>
<p>1.使用getSession()方法你只要继承sessionFactory，而使用getHibernateTemplate()方法必须继承
HibernateDaoSupport当然包括sessionFactory，这点区别都不是特别重要的，下面这些区别就很重要了</p>
<p>2.getSession()方法是没有经过spring包装的，spring会把最原始的session给你，在使用完之后必须自己调用相应的
close方法，而且也不会对声明式事务进行相应的管理，一旦没有及时关闭连接，就会导致数据库连接池的连接数溢
出，getHibernateTemplate()方法是经过spring封装的，例如添加相应的声明式事务管理，由spring管理相应的连接。</p>
<p>在实际的使用过程中发现的确getHibernateTemplate()比getSession()方法要好很多，但是有些方法在getHibernateTemplate()并没有提供，这时我们用HibernateCallback 回调的方法管理数据库.</p>
<p>例如如下代码：</p>
<p>/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 使用 hql 语句进行操作<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param hql HSQL 查询语句（使用回调函数访问外部变量，必须是final的）<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param offset 开始取数据的下标<br />
&nbsp;&nbsp;&nbsp; * @param length 读取数据记录数<br />
&nbsp;&nbsp;&nbsp; * @return List 结果集<br />
*/<br />
public List getListForPage ( final String hql , final int offset , final int length ) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List list = getHibernateTemplate().executeFind ( new HibernateCallback ( ) {<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; public Object doInHibernate ( Session session ) throws HibernateException, SQLException {<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; Query query = session.createQuery ( hql ) ;<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; query.setFirstResult ( offset ) ;<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;query.setMaxResults ( length ) ;<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; List list = query.list ( ) ;<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;return list ;<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; }<br />
&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; return list ;<br />
}</p>
</div>
<img src ="http://www.blogjava.net/sealyu/aggbug/313642.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-02-22 16:43 <a href="http://www.blogjava.net/sealyu/archive/2010/02/22/313642.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 的 HibernateDaoSupport 类的 getSession() 导致的连接泄露问题（转）</title><link>http://www.blogjava.net/sealyu/archive/2010/02/22/313643.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 22 Feb 2010 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/02/22/313643.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/313643.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/02/22/313643.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/313643.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/313643.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Spring+Hibernate做项目, 发现有member在不加事务的情况下就去调用 getSession() 方法,结果导致数据库连接不能释放, 也无法正常的提交事务(只能做查询, 不能做save(), update()). 如果配合连接池使用的话,不出几分钟就会导致连接池无法拿到新连接的情况.不过, 只要给DAO或者Service加入了事务, 就不会出现连接泄漏的问题.谈谈解...&nbsp;&nbsp;<a href='http://www.blogjava.net/sealyu/archive/2010/02/22/313643.html'>阅读全文</a><img src ="http://www.blogjava.net/sealyu/aggbug/313643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-02-22 16:43 <a href="http://www.blogjava.net/sealyu/archive/2010/02/22/313643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate 的配置文件模板</title><link>http://www.blogjava.net/sealyu/archive/2010/02/09/312395.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Tue, 09 Feb 2010 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/02/09/312395.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/312395.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/02/09/312395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/312395.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/312395.html</trackback:ping><description><![CDATA[这个模板在每个Hibernate发行版下project/etc下，名字为hibernate.properties.<br />
为方便查询，把3.3.2对应的内容转下来，方便以后查询：<br />
<br />
######################<br />
### Query Language ###<br />
######################<br />
<br />
## define query language constants / function names<br />
<br />
hibernate.query.substitutions yes 'Y', no 'N'<br />
<br />
<br />
## select the classic query parser<br />
<br />
#hibernate.query.factory_class org.hibernate.hql.classic.ClassicQueryTranslatorFactory<br />
<br />
<br />
<br />
#################<br />
### Platforms ###<br />
#################<br />
<br />
## JNDI Datasource<br />
<br />
#hibernate.connection.datasource jdbc/test<br />
#hibernate.connection.username db2<br />
#hibernate.connection.password db2<br />
<br />
<br />
## HypersonicSQL<br />
<br />
hibernate.dialect org.hibernate.dialect.HSQLDialect<br />
hibernate.connection.driver_class org.hsqldb.jdbcDriver<br />
hibernate.connection.username sa<br />
hibernate.connection.password<br />
hibernate.connection.url jdbc:hsqldb:./build/db/hsqldb/hibernate<br />
#hibernate.connection.url jdbc:hsqldb:hsql://localhost<br />
#hibernate.connection.url jdbc:hsqldb:test<br />
<br />
## H2 (www.h2database.com)<br />
#hibernate.dialect org.hibernate.dialect.H2Dialect<br />
#hibernate.connection.driver_class org.h2.Driver<br />
#hibernate.connection.username sa<br />
#hibernate.connection.password<br />
#hibernate.connection.url jdbc:h2:mem:./build/db/h2/hibernate<br />
#hibernate.connection.url jdbc:h2:testdb/h2test<br />
#hibernate.connection.url jdbc:h2:mem:imdb1<br />
#hibernate.connection.url jdbc:h2:tcp://dbserv:8084/sample; &nbsp;&nbsp; &nbsp;<br />
#hibernate.connection.url jdbc:h2:ssl://secureserv:8085/sample; &nbsp;&nbsp; &nbsp;<br />
#hibernate.connection.url jdbc:h2:ssl://secureserv/testdb;cipher=AES<br />
<br />
## MySQL<br />
<br />
#hibernate.dialect org.hibernate.dialect.MySQLDialect<br />
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect<br />
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect<br />
#hibernate.connection.driver_class com.mysql.jdbc.Driver<br />
#hibernate.connection.url jdbc:mysql:///test<br />
#hibernate.connection.username gavin<br />
#hibernate.connection.password<br />
<br />
<br />
## Oracle<br />
<br />
#hibernate.dialect org.hibernate.dialect.Oracle8iDialect<br />
#hibernate.dialect org.hibernate.dialect.Oracle9iDialect<br />
#hibernate.dialect org.hibernate.dialect.Oracle10gDialect<br />
#hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver<br />
#hibernate.connection.username ora<br />
#hibernate.connection.password ora<br />
#hibernate.connection.url jdbc:oracle:thin:@localhost:1521:orcl<br />
#hibernate.connection.url jdbc:oracle:thin:@localhost:1522:XE<br />
<br />
<br />
## PostgreSQL<br />
<br />
#hibernate.dialect org.hibernate.dialect.PostgreSQLDialect<br />
#hibernate.connection.driver_class org.postgresql.Driver<br />
#hibernate.connection.url jdbc:postgresql:template1<br />
#hibernate.connection.username pg<br />
#hibernate.connection.password<br />
<br />
<br />
## DB2<br />
<br />
#hibernate.dialect org.hibernate.dialect.DB2Dialect<br />
#hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver<br />
#hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver<br />
#hibernate.connection.url jdbc:db2://localhost:50000/somename<br />
#hibernate.connection.url jdbc:db2:somename<br />
#hibernate.connection.username db2<br />
#hibernate.connection.password db2<br />
<br />
## TimesTen<br />
<br />
#hibernate.dialect org.hibernate.dialect.TimesTenDialect<br />
#hibernate.connection.driver_class com.timesten.jdbc.TimesTenDriver<br />
#hibernate.connection.url jdbc:timesten:direct:test<br />
#hibernate.connection.username<br />
#hibernate.connection.password <br />
<br />
## DB2/400<br />
<br />
#hibernate.dialect org.hibernate.dialect.DB2400Dialect<br />
#hibernate.connection.username user<br />
#hibernate.connection.password password<br />
<br />
## Native driver<br />
#hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver<br />
#hibernate.connection.url jdbc:db2://systemname<br />
<br />
## Toolbox driver<br />
#hibernate.connection.driver_class com.ibm.as400.access.AS400JDBCDriver<br />
#hibernate.connection.url jdbc:as400://systemname<br />
<br />
<br />
## Derby (not supported!)<br />
<br />
#hibernate.dialect org.hibernate.dialect.DerbyDialect<br />
#hibernate.connection.driver_class org.apache.derby.jdbc.EmbeddedDriver<br />
#hibernate.connection.username<br />
#hibernate.connection.password<br />
#hibernate.connection.url jdbc:derby:build/db/derby/hibernate;create=true<br />
<br />
<br />
## Sybase<br />
<br />
#hibernate.dialect org.hibernate.dialect.SybaseDialect<br />
#hibernate.connection.driver_class com.sybase.jdbc2.jdbc.SybDriver<br />
#hibernate.connection.username sa<br />
#hibernate.connection.password sasasa<br />
#hibernate.connection.url jdbc:sybase:Tds:co3061835-a:5000/tempdb<br />
<br />
<br />
## Mckoi SQL<br />
<br />
#hibernate.dialect org.hibernate.dialect.MckoiDialect<br />
#hibernate.connection.driver_class com.mckoi.JDBCDriver<br />
#hibernate.connection.url jdbc:mckoi:///<br />
#hibernate.connection.url jdbc:mckoi:local://C:/mckoi1.0.3/db.conf<br />
#hibernate.connection.username admin<br />
#hibernate.connection.password nimda<br />
<br />
<br />
## SAP DB<br />
<br />
#hibernate.dialect org.hibernate.dialect.SAPDBDialect<br />
#hibernate.connection.driver_class com.sap.dbtech.jdbc.DriverSapDB<br />
#hibernate.connection.url jdbc:sapdb://localhost/TST<br />
#hibernate.connection.username TEST<br />
#hibernate.connection.password TEST<br />
#hibernate.query.substitutions yes 'Y', no 'N'<br />
<br />
<br />
## MS SQL Server<br />
<br />
#hibernate.dialect org.hibernate.dialect.SQLServerDialect<br />
#hibernate.connection.username sa<br />
#hibernate.connection.password sa<br />
<br />
## JSQL Driver<br />
#hibernate.connection.driver_class com.jnetdirect.jsql.JSQLDriver<br />
#hibernate.connection.url jdbc:JSQLConnect://1E1/test<br />
<br />
## JTURBO Driver<br />
#hibernate.connection.driver_class com.newatlanta.jturbo.driver.Driver<br />
#hibernate.connection.url jdbc:JTurbo://1E1:1433/test<br />
<br />
## WebLogic Driver<br />
#hibernate.connection.driver_class weblogic.jdbc.mssqlserver4.Driver<br />
#hibernate.connection.url jdbc:weblogic:mssqlserver4:1E1:1433<br />
<br />
## Microsoft Driver (not recommended!)<br />
#hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver<br />
#hibernate.connection.url jdbc:microsoft:sqlserver://1E1;DatabaseName=test;SelectMethod=cursor<br />
<br />
## The New Microsoft Driver <br />
#hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver<br />
#hibernate.connection.url jdbc:sqlserver://localhost<br />
<br />
## jTDS (since version 0.9)<br />
#hibernate.connection.driver_class net.sourceforge.jtds.jdbc.Driver<br />
#hibernate.connection.url jdbc:jtds:sqlserver://1E1/test<br />
<br />
## Interbase<br />
<br />
#hibernate.dialect org.hibernate.dialect.InterbaseDialect<br />
#hibernate.connection.username sysdba<br />
#hibernate.connection.password masterkey<br />
<br />
## DO NOT specify hibernate.connection.sqlDialect<br />
<br />
## InterClient<br />
<br />
#hibernate.connection.driver_class interbase.interclient.Driver<br />
#hibernate.connection.url jdbc:interbase://localhost:3060/C:/firebird/test.gdb<br />
<br />
## Pure Java<br />
<br />
#hibernate.connection.driver_class org.firebirdsql.jdbc.FBDriver<br />
#hibernate.connection.url jdbc:firebirdsql:localhost/3050:/firebird/test.gdb<br />
<br />
<br />
## Pointbase<br />
<br />
#hibernate.dialect org.hibernate.dialect.PointbaseDialect<br />
#hibernate.connection.driver_class com.pointbase.jdbc.jdbcUniversalDriver<br />
#hibernate.connection.url jdbc:pointbase:embedded:sample<br />
#hibernate.connection.username PBPUBLIC<br />
#hibernate.connection.password PBPUBLIC<br />
<br />
<br />
## Ingres<br />
<br />
## older versions (before Ingress 2006)<br />
<br />
#hibernate.dialect org.hibernate.dialect.IngresDialect<br />
#hibernate.connection.driver_class ca.edbc.jdbc.EdbcDriver<br />
#hibernate.connection.url jdbc:edbc://localhost:II7/database<br />
#hibernate.connection.username user<br />
#hibernate.connection.password password<br />
<br />
## Ingres 2006 or later<br />
<br />
#hibernate.dialect org.hibernate.dialect.IngresDialect<br />
#hibernate.connection.driver_class com.ingres.jdbc.IngresDriver<br />
#hibernate.connection.url jdbc:ingres://localhost:II7/database;CURSOR=READONLY;auto=multi<br />
#hibernate.connection.username user<br />
#hibernate.connection.password password<br />
<br />
## Mimer SQL<br />
<br />
#hibernate.dialect org.hibernate.dialect.MimerSQLDialect<br />
#hibernate.connection.driver_class com.mimer.jdbc.Driver<br />
#hibernate.connection.url jdbc:mimer:multi1<br />
#hibernate.connection.username hibernate<br />
#hibernate.connection.password hibernate<br />
<br />
<br />
## InterSystems Cache<br />
<br />
#hibernate.dialect org.hibernate.dialect.Cache71Dialect<br />
#hibernate.connection.driver_class com.intersys.jdbc.CacheDriver<br />
#hibernate.connection.username _SYSTEM<br />
#hibernate.connection.password SYS<br />
#hibernate.connection.url jdbc:Cache://127.0.0.1:1972/HIBERNATE<br />
<br />
<br />
#################################<br />
### Hibernate Connection Pool ###<br />
#################################<br />
<br />
hibernate.connection.pool_size 1<br />
<br />
<br />
<br />
###########################<br />
### C3P0 Connection Pool###<br />
###########################<br />
<br />
#hibernate.c3p0.max_size 2<br />
#hibernate.c3p0.min_size 2<br />
#hibernate.c3p0.timeout 5000<br />
#hibernate.c3p0.max_statements 100<br />
#hibernate.c3p0.idle_test_period 3000<br />
#hibernate.c3p0.acquire_increment 2<br />
#hibernate.c3p0.validate false<br />
<br />
<br />
<br />
##############################<br />
### Proxool Connection Pool###<br />
##############################<br />
<br />
## Properties for external configuration of Proxool<br />
<br />
hibernate.proxool.pool_alias pool1<br />
<br />
## Only need one of the following<br />
<br />
#hibernate.proxool.existing_pool true<br />
#hibernate.proxool.xml proxool.xml<br />
#hibernate.proxool.properties proxool.properties<br />
<br />
<br />
<br />
#################################<br />
### Plugin ConnectionProvider ###<br />
#################################<br />
<br />
## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in ConnectionProvider using hueristics)<br />
<br />
#hibernate.connection.provider_class org.hibernate.connection.DriverManagerConnectionProvider<br />
#hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider<br />
#hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider<br />
#hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider<br />
<br />
<br />
<br />
#######################<br />
### Transaction API ###<br />
#######################<br />
<br />
## Enable automatic flush during the JTA beforeCompletion() callback<br />
## (This setting is relevant with or without the Transaction API)<br />
<br />
#hibernate.transaction.flush_before_completion<br />
<br />
<br />
## Enable automatic session close at the end of transaction<br />
## (This setting is relevant with or without the Transaction API)<br />
<br />
#hibernate.transaction.auto_close_session<br />
<br />
<br />
## the Transaction API abstracts application code from the underlying JTA or JDBC transactions<br />
<br />
#hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory<br />
#hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory<br />
<br />
<br />
## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in JNDI<br />
## default is java:comp/UserTransaction<br />
## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class<br />
<br />
#jta.UserTransaction jta/usertransaction<br />
#jta.UserTransaction javax.transaction.UserTransaction<br />
#jta.UserTransaction UserTransaction<br />
<br />
<br />
## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager<br />
<br />
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup<br />
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup<br />
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup<br />
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup<br />
#hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup<br />
<br />
<br />
<br />
##############################<br />
### Miscellaneous Settings ###<br />
##############################<br />
<br />
## print all generated SQL to the console<br />
<br />
#hibernate.show_sql true<br />
<br />
<br />
## format SQL in log and console<br />
<br />
hibernate.format_sql true<br />
<br />
<br />
## add comments to the generated SQL<br />
<br />
#hibernate.use_sql_comments true<br />
<br />
<br />
## generate statistics<br />
<br />
#hibernate.generate_statistics true<br />
<br />
<br />
## auto schema export<br />
<br />
#hibernate.hbm2ddl.auto create-drop<br />
#hibernate.hbm2ddl.auto create<br />
#hibernate.hbm2ddl.auto update<br />
#hibernate.hbm2ddl.auto validate<br />
<br />
<br />
## specify a default schema and catalog for unqualified tablenames<br />
<br />
#hibernate.default_schema test<br />
#hibernate.default_catalog test<br />
<br />
<br />
## enable ordering of SQL UPDATEs by primary key<br />
<br />
#hibernate.order_updates true<br />
<br />
<br />
## set the maximum depth of the outer join fetch tree<br />
<br />
hibernate.max_fetch_depth 1<br />
<br />
<br />
## set the default batch size for batch fetching<br />
<br />
#hibernate.default_batch_fetch_size 8<br />
<br />
<br />
## rollback generated identifier values of deleted entities to default values<br />
<br />
#hibernate.use_identifer_rollback true<br />
<br />
<br />
## enable bytecode reflection optimizer (disabled by default)<br />
<br />
#hibernate.bytecode.use_reflection_optimizer true<br />
<br />
<br />
<br />
#####################<br />
### JDBC Settings ###<br />
#####################<br />
<br />
## specify a JDBC isolation level<br />
<br />
#hibernate.connection.isolation 4<br />
<br />
<br />
## enable JDBC autocommit (not recommended!)<br />
<br />
#hibernate.connection.autocommit true<br />
<br />
<br />
## set the JDBC fetch size<br />
<br />
#hibernate.jdbc.fetch_size 25<br />
<br />
<br />
## set the maximum JDBC 2 batch size (a nonzero value enables batching)<br />
<br />
#hibernate.jdbc.batch_size 5<br />
#hibernate.jdbc.batch_size 0<br />
<br />
<br />
## enable batch updates even for versioned data<br />
<br />
hibernate.jdbc.batch_versioned_data true<br />
<br />
<br />
## enable use of JDBC 2 scrollable ResultSets (specifying a Dialect will cause Hibernate to use a sensible default)<br />
<br />
#hibernate.jdbc.use_scrollable_resultset true<br />
<br />
<br />
## use streams when writing binary types to / from JDBC<br />
<br />
hibernate.jdbc.use_streams_for_binary true<br />
<br />
<br />
## use JDBC 3 PreparedStatement.getGeneratedKeys() to get the identifier of an inserted row<br />
<br />
#hibernate.jdbc.use_get_generated_keys false<br />
<br />
<br />
## choose a custom JDBC batcher<br />
<br />
# hibernate.jdbc.factory_class<br />
<br />
<br />
## enable JDBC result set column alias caching <br />
## (minor performance enhancement for broken JDBC drivers)<br />
<br />
# hibernate.jdbc.wrap_result_sets<br />
<br />
<br />
## choose a custom SQL exception converter<br />
<br />
#hibernate.jdbc.sql_exception_converter<br />
<br />
<br />
<br />
##########################<br />
### Second-level Cache ###<br />
##########################<br />
<br />
## optimize chache for minimal "puts" instead of minimal "gets" (good for clustered cache)<br />
<br />
#hibernate.cache.use_minimal_puts true<br />
<br />
<br />
## set a prefix for cache region names<br />
<br />
hibernate.cache.region_prefix hibernate.test<br />
<br />
<br />
## disable the second-level cache<br />
<br />
#hibernate.cache.use_second_level_cache false<br />
<br />
<br />
## enable the query cache<br />
<br />
#hibernate.cache.use_query_cache true<br />
<br />
<br />
## store the second-level cache entries in a more human-friendly format<br />
<br />
#hibernate.cache.use_structured_entries true<br />
<br />
<br />
## choose a cache implementation<br />
<br />
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider<br />
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider<br />
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider<br />
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider<br />
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider<br />
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider<br />
<br />
<br />
## choose a custom query cache implementation<br />
<br />
#hibernate.cache.query_cache_factory<br />
<br />
<br />
<br />
############<br />
### JNDI ###<br />
############<br />
<br />
## specify a JNDI name for the SessionFactory<br />
<br />
#hibernate.session_factory_name hibernate/session_factory<br />
<br />
<br />
## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction;<br />
## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which<br />
## is the best approach in an application server<br />
<br />
#file system<br />
#hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory<br />
#hibernate.jndi.url file:/<br />
<br />
#WebSphere<br />
#hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory<br />
#hibernate.jndi.url iiop://localhost:900/<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/sealyu/aggbug/312395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-02-09 11:05 <a href="http://www.blogjava.net/sealyu/archive/2010/02/09/312395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ORA-12519, TNS:no appropriate service handler found(转)</title><link>http://www.blogjava.net/sealyu/archive/2010/02/03/311753.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 03 Feb 2010 01:02:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/02/03/311753.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/311753.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/02/03/311753.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/311753.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/311753.html</trackback:ping><description><![CDATA[<div id="blog_text" class="cnt">
<p>遇到这种错误，一般是因为并发过大引起的。</p>
<p>查询解决方法:</p>
<p>查看一下数据库现有的进程数，是否已经达到参数processes的大小。</p>
<p>1.select count(*) from v$process;&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 />
2.select value from v$parameter where name = 'processes'; 取得进程数的上限。<br />
3.如已达到上限，修改initSID.ora中的processes的大小。<br />
4.重新启动数据库到nomount状态下，执行create spfile from pfile; 并startup open。</p>
<p><br />
查询数据库自启动以来最大的并发数量</p>
<p>select * from v$license</p>
</div>
<img src ="http://www.blogjava.net/sealyu/aggbug/311753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-02-03 09:02 <a href="http://www.blogjava.net/sealyu/archive/2010/02/03/311753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Hibernate报错org.hibernate.LazyInitializationException: illegal access to loading collection</title><link>http://www.blogjava.net/sealyu/archive/2010/01/21/310432.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 21 Jan 2010 12:36:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/01/21/310432.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/310432.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/01/21/310432.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/310432.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/310432.html</trackback:ping><description><![CDATA[org.hibernate.LazyInitializationException: illegal access to loading collection<br />
&nbsp;  at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:341)<br />
&nbsp;  at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)<br />
<br />
<br />
原因在与pojo里面的 &nbsp; public int hashCode() {... } 方法调用了set对象成员的hashCode()方法<br />
如this.getSets().hashCode();<br />
删除该方法的调用即可；调用非set对象成员的.hashCode()方法没有问题。
<img src ="http://www.blogjava.net/sealyu/aggbug/310432.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-01-21 20:36 <a href="http://www.blogjava.net/sealyu/archive/2010/01/21/310432.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于按annotation的hibernate主键生成策略（转）</title><link>http://www.blogjava.net/sealyu/archive/2010/01/21/310386.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 21 Jan 2010 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/01/21/310386.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/310386.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/01/21/310386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/310386.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/310386.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、JPA通用策略生成器通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id,其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法,JPA提供四种标准用法,由@GeneratedValue的源代码可以明显看出.Java代码 ...&nbsp;&nbsp;<a href='http://www.blogjava.net/sealyu/archive/2010/01/21/310386.html'>阅读全文</a><img src ="http://www.blogjava.net/sealyu/aggbug/310386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-01-21 13:57 <a href="http://www.blogjava.net/sealyu/archive/2010/01/21/310386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenSessionInViewFilter 的两个异常:Illegal attempt to associate a collection with two open sessions; Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL)</title><link>http://www.blogjava.net/sealyu/archive/2009/10/29/300275.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 29 Oct 2009 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/10/29/300275.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/300275.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/10/29/300275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/300275.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/300275.html</trackback:ping><description><![CDATA[<p>使用 Spring 整合 Hibernate, 在懒加载的情况下, 有时候需要在 JSP/View 层显示数据, 这时候就要用到Spring内置的: OpenSessionInViewFilter, 一般来说配置如下(web.xml):</p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter</span><span style="color: #0000ff;">&gt;</span><br />
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span>hibernateFilter<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;"><br />
&lt;</span><span style="color: #800000;">filter-class</span><span style="color: #0000ff;">&gt;</span><br />
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter<br />
<span style="color: #0000ff;">    &lt;/</span><span style="color: #800000;">filter-class</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;"><br />
&lt;</span><span style="color: #800000;">init-param</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;"><br />
&lt;</span><span style="color: #800000;">param-name</span><span style="color: #0000ff;">&gt;</span>singleSession<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">param-name</span><span style="color: #0000ff;">&gt;<br />
</span><span style="color: #0000ff;">        &lt;</span><span style="color: #800000;">param-value</span><span style="color: #0000ff;">&gt;</span>true<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">param-value</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;"><br />
&lt;/</span><span style="color: #800000;">init-param</span><span style="color: #0000ff;">&gt;</span><span style="color: #008000;">&lt;!-- 和 spring 中的sesssionfactory ID 一致 --&gt;<br />
</span><span style="color: #0000ff;"> </span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;"><br />
&lt;</span><span style="color: #800000;">filter-mapping</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span>hibernateFilter<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">url-pattern</span><span style="color: #0000ff;">&gt;</span>*.do<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">url-pattern</span><span style="color: #0000ff;">&gt;&lt;!</span><span style="color: #800000;">--</span> *.<span style="color: #ff0000;">jsp</span>, *.<span style="color: #ff0000;">do</span><span style="color: #ff0000;">--</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-mapping</span><span style="color: #0000ff;">&gt;</span></pre>
</div>
<div>不过, 这时候又会导致更新数据时抛出如下异常: </div>
<blockquote>
<div>Write
operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL):
Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly'
marker from transaction definition.</div>
</blockquote>
<p>这时候再去网上找解决方案, 会有人说: 把参数 singleSession改为false, 就行了. 不过, 改完后, 估计不久就会遇到另一个郁闷的异常:</p>
<blockquote>
<p>org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions</p>
</blockquote>
<p>这下完了, 两个方案都不行, 到底怎么办? 还好, 在<a title="http://xuliangyong.javaeye.com/blog/144818" href="http://xuliangyong.javaeye.com/blog/144818">http://xuliangyong.javaeye.com/blog/144818</a>的主页上, 给了一个方案, 就是改写 OpenSessionInViewFilter 的代码, 非常感谢, 下面给出的就是最终方案:
</p>
<p>web.xml
</p>
<p>
<span style="color: #0000ff;">&lt;</span>
<span style="color: #800000;">filter-name</span>
<span style="color: #0000ff;">&gt;</span>hibernateFilter<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span></p>
<p>
<span style="color: #0000ff;">&lt;</span>
<span style="color: #800000;">filter-class</span>
<span style="color: #0000ff;">&gt;</span> org.springframework.orm.hibernate3.support.OurOpenSessionInViewFilter <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-class</span><span style="color: #0000ff;">&gt;</span></p>
<p>OurOpenSessionInViewFilter.java 代码:
</p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">package org.springframework.orm.hibernate3.support;<br />
<br />
<br />
<br />
import org.hibernate.*;<br />
<br />
<br />
<br />
<span style="color: #008000;">/**</span><span style="color: #008000;"> * 单session模式下, 默认会发生无法提交的错误:</span><span style="color: #008000;"> * Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.</span><span style="color: #008000;"> * 需要设置FlushMode并刷新session.</span><span style="color: #008000;"> * 参考: http://xuliangyong.javaeye.com/blog/144818</span><span style="color: #008000;"> * @author 刘长炯</span><span style="color: #008000;"> */</span><span style="color: #0000ff;">public</span><span style="color: #0000ff;">class</span> OurOpenSessionInViewFilter extends OpenSessionInViewFilter {<br />
<br />
<br />
<br />
<span style="color: #0000ff;">public</span> OurOpenSessionInViewFilter() {<br />
<br />
super.setFlushMode(FlushMode.AUTO);<br />
<br />
}<br />
<br />
<br />
<br />
<span style="color: #0000ff;">protected</span><span style="color: #0000ff;">void</span> closeSession(Session session, SessionFactory sessionFactory) {<br />
<br />
session.flush();<br />
<br />
<br />
<br />
<span style="color: #0000ff;">try</span> {<br />
<br />
session.getTransaction().commit();<br />
<br />
} <span style="color: #0000ff;">catch</span> (HibernateException e) {<br />
<br />
<span style="color: #008000;">// TODO Auto-generated catch block</span><span style="color: #008000;">//e.printStackTrace();</span><br />
<br />
}<br />
<br />
<br />
<br />
super.closeSession(session, sessionFactory); <br />
<br />
} <br />
<br />
}<br />
<br />
</pre>
</div>
<p>如果各位有更好的解决方案, 欢迎讨论哦!!!</p>
<p>题外话:</p>
<p>感觉 Spring + Hibernate 的健壮性还是不够啊! 容易抛异常, 这是事实, 也许这是开源软件的通病吧.</p>
<img src ="http://www.blogjava.net/sealyu/aggbug/300275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-10-29 22:23 <a href="http://www.blogjava.net/sealyu/archive/2009/10/29/300275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Solving the Simultaneously Fetch Multiple Bags Exception using idbags（转）</title><link>http://www.blogjava.net/sealyu/archive/2009/08/27/292845.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 27 Aug 2009 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/08/27/292845.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/292845.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/08/27/292845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/292845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/292845.html</trackback:ping><description><![CDATA[<div>
<p style="text-align: justify;">About a year and an half ago I wrote an <a href="http://www.jroller.com/page/eyallupu?entry=hibernate_exception_simultaneously_fetch_multiple">entry</a>
about the problem that rises when mapping an entity with multiple bags using <em>eager</em>
fetching. At the end of the entry I suggested three different solutions: (a) to
use lazy fetching, (b) to use sets instead of bags, and (c) to use the
@IndexColumn annotation. Few months later I <a href="http://www.jroller.com/eyallupu/entry/solving_simultaneously_fetch_multiple_bags">elaborated</a>
on the usage of @IndexColumn, this time another way &#8211; using the @CollectionId
annotation.</p>
<p>Environment</p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: 10pt; font-family: Symbol;"><span>&#183;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span dir="LTR">Hibernate Entity Manager &#8211;
3.3.1.GA</span></p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: 10pt; font-family: Symbol;"><span>&#183;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span dir="LTR">Hibernate core &#8211; 3.2.5.GA</span></p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: 10pt; font-family: Symbol;"><span>&#183;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span dir="LTR">Hibernate annotations- 3.3.0.GA</span></p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: 10pt; font-family: Symbol;"><span>&#183;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span dir="LTR">Database &#8211; PostgreSQL 8.1</span></p>
<h3>First one, first&#8230;</h3>
<p style="text-align: justify;">Just before we start a warning &#8211; the
@CollectionId annotation is a Hibernate specific annotation &#8211; not a part of the
specification. And it doesn't work on one-to-many associations (but it can be
used in conjunction with one-to-many associations). After putting that behind
of us lets see the problem.</p>
<p style="text-align: center;" align="center">
<script type="text/javascript">
<!--
google_ad_client = "pub-7548643028974164";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text_image";
google_ad_channel ="";
google_color_border = "9191CD";
google_color_bg = "FFFFFF";
google_color_link = "0000FF";
google_color_url = "008000";
google_color_text = "000000";
//-->
</script>
<script>google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad);</script>
&nbsp;</p>
<h3>The Problem</h3>
<p style="margin-bottom: 0.0001pt; text-align: justify;">Assume
the following entities relation, a parent entity has two collections of child
entities. Both collections should be eagerly loaded.</p>
<img src="http://jroller.com/eyallupu/resource/idbag-class-diagram.gif" border="0" height="192" width="288"  alt="" /><br />
<p style="margin-bottom: 0.0001pt;">First try will be to just to
map it as is (Child1 has a many-to-many association; Child2 has a one-to-many):</p>
<div style="border: 1pt solid black; padding: 1pt; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">&nbsp;</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@<strong>ManyToMany</strong>( fetch = FetchType.EAGER, cascade=CascadeType.ALL)</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@JoinTable(name = "PARENT_CHILD1", </pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">joinColumns = @JoinColumn(name = "PARENT_ID", referencedColumnName = "ID"), </pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">inverseJoinColumns = @JoinColumn(name = "CHILD1_ID", referencedColumnName = "ID"))<br />
</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">List&lt;Child1&gt; child1s = new LinkedList&lt;Child1&gt;();</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">&nbsp;</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@<strong>OneToMany</strong>(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">List&lt;Child2&gt; child2s = new LinkedList&lt;Child2&gt;();</pre>
</div>
<p style="margin-bottom: 12pt; text-align: justify;">But
when loading a persistence unit with the above configuration the
"org.hibernate.HibernateException: cannot simultaneously fetch multiple
bags" will be thrown.</p>
<h3>Using
an idbag</h3>
<p style="margin-bottom: 12pt; text-align: justify;">The
reason is that when we add the @CollectionId to a List or a Collection its
semantics changes from "just a bag" to "a bag with primary
key" (a.k.a, idbag). It means that a surrogate key is assigned to each row
on the collection</p>
<p style="margin-bottom: 12pt; text-align: justify;">When
transforming the association to Child1 into an <a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/collections.html#collections-idbag">idbag</a>
(using the @CollectionId annotation) the problem is solved. The reason is that when
we switch the association semantics from "a simple bag" to "a
bag with primary key" (a.k.a, idbag) it means that a surrogate key is
assigned to each row on the collection.</p>
<div style="border: 1pt solid black; padding: 1pt; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@Entity</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">public class Parent {</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">&#8230;&#8230;&#8230;</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@ManyToMany( fetch = FetchType.EAGER, cascade=CascadeType.ALL)</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@JoinTable(name = "PARENT_CHILD1", </pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">joinColumns = @JoinColumn(name = "PARENT_ID", referencedColumnName = "ID"), </pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">inverseJoinColumns = @JoinColumn(name = "CHILD1_ID", referencedColumnName = "ID"))</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;"><strong>@GenericGenerator(name="uuid-gen", strategy = "uuid")</strong></pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;"><strong>@CollectionId(columns = @Column(name = "COL_ID"), type = @Type(type = "string"), generator = "uuid-gen")</strong>List&lt;Child1&gt; child1s = new LinkedList&lt;Child1&gt;();</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">&nbsp;</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">List&lt;Child2&gt; child2s = new LinkedList&lt;Child2&gt;();</pre>
<pre style="border: medium none ; padding: 0in; background: #cccccc none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">}</pre>
</div>
<p style="margin-bottom: 12pt; text-align: justify;">The
problem with bags is that when Hibernate eagerly loads multiple collections it
issues an outer join select to the RDBMS which can cause multiple entries on
some of the collections. But when using an idbag each row in the collections is
uniquely identified by the surrogate key, therefore Hibernate can identify it
within the collection, even if the SQL statement returns an entry more than
once.</p>
<p style="margin-bottom: 12pt; text-align: justify;">Notice
the usage of a generator assigned to the collection id, the generator is
responsible for creating the surrogate keys of the collection rows. I decided
to use the UUID strategy. You can, of course, use JPA standard generators (such
as Sequence or Table generators). The @CollectionId references the COL_ID
column on PARENT_CHILD1 table (the join table). The value of the collection id
is invisible to the application (it is not being mapped to a property).</p>
<p style="text-align: center;" align="center">
<script type="text/javascript">
<!--
google_ad_client = "pub-7548643028974164";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text_image";
google_ad_channel ="";
google_color_border = "9191CD";
google_color_bg = "FFFFFF";
google_color_link = "0000FF";
google_color_url = "008000";
google_color_text = "000000";
//-->
</script>
<script>google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad);</script>
&nbsp;</p>
<h3>So
why not on one-to-many</h3>
<p style="margin-bottom: 12pt; text-align: justify;">The
Hibernate <em>annotations</em> documentation says that to announce idbag
semantics you should assign the @CollectionId to a @ManyToMany,
@CollectionOfElements, or @OneToMany (look at the table on <a href="http://www.hibernate.org/hib_docs/annotations/reference/en/html/entity.html#entity-mapping-association-collections">this</a>
section), but the Hibernate <em>core</em> documentation it says "Hibernate
provides a feature that allows you to map <u>many to many</u> associations and <u>collections
of values</u> to a table with a surrogate key." (<a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/collections.html#collections-idbag">here</a>).
I've tried it and indeed when annotating a @OneToMany collection with the
@CollectionId an exception with the message "one-to-many collections with
identifiers are not supported " is thrown by Hibernate.</p>
<h3>Idbag - Not Just For Eager Fetching</h3>
<p style="text-align: justify;">Don't
forge that you can use idbag for reasons other than solving multiple eager
associations. For example it can give a major performance boost over simple
bags for mutative operations. If entries in a collection have surrogate keys
Hibernate will be able to locate the matching rows in the database using these
keys (each row in the association table becomes unique) &#8211; there is no need for
the fetch -&gt; delete-all -&gt; insert-all cycle when updating the collection.</p>
</div>
<br />
<a href="http://del.icio.us/post?url=http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1&amp;title=Solving%20Simultaneously%20Fetch%20Multiple%20Bags%20using%20idbags"><img src="http://jroller.com/resources/e/eyallupu/delicious.gif" border="0"  alt="" /></a>
<a href="http://digg.com/submit?phase=2&amp;url=http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1"><img src="http://jroller.com/resources/e/eyallupu/digg.gif" border="0"  alt="" /></a>
<a href="http://technorati.com/cosmos/search.html?url=http://jroller.com/page/eyallupu"><img src="http://jroller.com/resources/e/eyallupu/technorati.gif" border="0"  alt="" /></a>
<br />
<p>
Posted at <a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1">
03:49PM Jan 18, 2008</a>
by Eyal Lupu in Persistence &nbsp;|&nbsp;
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comments" class="commentsLink">Comments[6]</a>
</p>
<div id="comments">
<div>Comments:</div>
<br />
<div odd="" id="comment1">
Actually a @OneToMany @JoinTable would work (as opposed to @OneToMany @JoinColumn)
<p>
Posted by
<strong>Emmanuel Bernard</strong>
on January 21, 2008 at 09:33 PM GMT+02:00
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comment-1200943986000" class="entrypermalink" title="comment permalink">#</a>
</p>
</div>
<div even="" id="comment2">
Thanks Emmanuel,
<br />
<br />
Maybe it worth a comment in the documentation. I guess this is
actually an Hibernate core's issue (not an Hibernate annotation one -
is it?).
<p>
Posted by
<strong>Eyal Lupu</strong>
on January 21, 2008 at 11:56 PM GMT+02:00
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comment-1200952575000" class="entrypermalink" title="comment permalink">#</a>
</p>
</div>
<div odd="" id="comment3">
So, if I have 2 parallel OneToMany collections it's not fixable with:
<br />
<br />
@OneToMany @CollectionId
<br />
List&lt;Son&gt; getSons() {...}
<br />
<br />
@OneToMany @CollectionId
<br />
List&lt;Daughter&gt; getDaughter() {...}
<br />
<br />
But if they were ManyToMany collections it is fixable?
<br />
<br />
Strange :) Any particular reason?
<p>
Posted by
<strong>Geoffrey De Smet</strong>
on January 23, 2008 at 11:11 AM GMT+02:00
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comment-1201079492000" class="entrypermalink" title="comment permalink">#</a>
</p>
</div>
<div even="" id="comment4">
Hi Geoffrey,
<br />
Yes - you have understood it correctly.
<br />
<br />
I guess the reason is that regular one-to-many associations have a
foreign key on the child record and there is no place to store the
collection id there. <br />
<br />
However, see Emmanuel comment above - you can solve it using a join table.
<br />
<p>
Posted by
<a rel="nofollow" href="http://www.jroller.com/eyallupu"><strong>Eyal Lupu</strong></a>
on January 23, 2008 at 11:59 AM GMT+02:00
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comment-1201082349000" class="entrypermalink" title="comment permalink">#</a>
</p>
</div>
<div odd="" id="comment5">
Year the documentation should be clearer.
<p>
Posted by
<strong>Emmanuel Bernard</strong>
on January 23, 2008 at 04:48 PM GMT+02:00
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comment-1201099687000" class="entrypermalink" title="comment permalink">#</a>
</p>
</div>
<div even="" id="comment6">
There is fourth solution of this problem. Works for both @OneToMany and @ManyToMany:
<br />
<br />
@OneToMany(mappedBy="account", cascade=CascadeType.ALL)
<br />
@LazyCollection(LazyCollectionOption.FALSE)
<br />
private List&lt;Entry&gt; entries;
<br />
<br />
Annotation @LazyCollection(LazyCollectionOption.FALSE) makes that
collecion is loaded like with FetchType.EAGER and you can use it on two
and more collections. <br />
This solution is (in my opinion) better because it's simplier. :)
<p>
Posted by
<strong>Bartosz Jakubowski</strong>
on October 22, 2008 at 01:26 PM GMT+02:00
<a href="http://www.jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1#comment-1224674770000" class="entrypermalink" title="comment permalink">#</a>
</p>
</div>
</div>
<img src ="http://www.blogjava.net/sealyu/aggbug/292845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-08-27 16:56 <a href="http://www.blogjava.net/sealyu/archive/2009/08/27/292845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate中get和load方法的区别以及close()，clear()、evict()等的区别（转）</title><link>http://www.blogjava.net/sealyu/archive/2009/08/19/291759.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 19 Aug 2009 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/08/19/291759.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/291759.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/08/19/291759.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/291759.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/291759.html</trackback:ping><description><![CDATA[<div>
<div g_c_pdin="" g_p_center="" c07="" content="" id="blogtext_fks_082066082094085068080084081095085080088070084094094">
<div>
<p style="text-indent: 2em;">get和load方式是根据id取得一个记录 </p>
<p style="text-indent: 2em;">下边详细说一下get和load的不同，因为有些时候为了对比也会把find加进来。 </p>
<p style="text-indent: 2em;">1.从返回结果上对比： </p>
<p style="text-indent: 2em;">load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常 </p>
<p style="text-indent: 2em;">get方法检索不到的话会返回null </p>
<p style="text-indent: 2em;">2.从检索执行机制上对比： </p>
<p style="text-indent: 2em;">get方法和find方法都是直接从数据库中检索 </p>
<p style="text-indent: 2em;">而load方法的执行则比较复杂 </p>
<p style="text-indent: 2em;">■ 首先查找session的persistent Context中是否有缓存，如果有则直接返回 </p>
<p style="text-indent: 2em;">■ 如果没有则判断是否是lazy，如果不是直接访问数据库检索，查到记录返回，查不到抛出异常 </p>
<p style="text-indent: 2em;">■ 如果是lazy则需要建立代理对象，对象的initialized属性为false，target属性为null </p>
<p style="text-indent: 2em;">■ 在访问获得的代理对象的属性时,检索数据库，如果找到记录则把该记录的对象复制到代理对象的target上，并将initialized=true，如果找不到就抛出异常 。 </p>
<p style="text-indent: 2em;">3.根本区别说明 </p>
<p style="text-indent: 2em;">■
如果你使用load方法，hibernate认为该id对应的对象（数据库记录）在数据库中是一定存在的，所以它可以放心的使用，它可以放心的使用代理来
延迟加载该对象。在用到对象中的其他属性数据时才查询数据库，但是万一数据库中不存在该记录，那没办法，只能抛异常。所说的load方法抛异常是指在使用
该对象的数据时，数据库中不存在该数据时抛异常，而不是在创建这个对象时(注意：这就是由于&#8220;延迟加载&#8221;在作怪)。 </p>
<p style="text-indent: 2em;">由于session中的缓存对于hibernate来说是个相当廉价的资源，所以在load时会先查一下session缓存看看该id对应的对象是否存在，不存在则创建代理。所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。 </p>
<p style="text-indent: 2em;">■ 对于get方法，hibernate会确认一下该id对应的数据是否存在，首先在session缓存中查找，然后在二级缓存中查找，还没有就查数据库，数据库中没有就返回null。 </p>
<p style="text-indent: 2em;">对于load和get方法返回类型：虽然好多书中都这么说：&#8220;get()永远只返回实体
类&#8221;，但实际上这是不正确的，get方法如果在
session缓存中找到了该id对应的对象，如果刚好该对象前面是被代理过的，如被load方法使用过，或者被其他关联对象延迟加载过，那么返回的还是
原先的代理对象，而不是实体类对象，如果该代理对象还没有加载实体数据（就是id以外的其他属性数据），那么它会查询二级缓存或者数据库来加载数据，但是
返回的还是代理对象，只不过已经加载了实体数据。 </p>
<p style="text-indent: 2em;">get方法首先查询session缓存，没有的话查询二级缓存，最后查询数据库；反而load方法创建时首先查询session缓存，没有就创建代理，实际使用数据时才查询二级缓存和数据库。 </p>
<p style="text-indent: 2em;">4.简单总结 </p>
<p style="text-indent: 2em;">总之对于get和load的根本区别，一句话，hibernate对于load方法认为该数据在数据库中一定存在，可以放心的使用代理来延迟加载，如果在使用过程中发现了问题，只能抛异常；而对于get方法，hibernate一定要获取到真实的数据，否则返回null。</p>
<p style="text-indent: 2em;">文章出处：<a href="http://www.diybl.com/course/3_program/java/javajs/2008531/118292.html">http://www.diybl.com/course/3_program/java/javajs/2008531/118292.html</a></p>
<p style="text-indent: 2em;">hibernate的各种保存方式的区(save,persist,update,saveOrUpdte,merge,flush,lock)及 对象的三种状态</p>
<p style="text-indent: 2em;">hibernate的保存</p>
<p style="text-indent: 2em;">hibernate对于对象的保存提供了太多的方法，他们之间有很多不同，这里细说一下，以便区别。</p>
<p style="text-indent: 2em;">一、预备知识</p>
<p style="text-indent: 2em;">对于hibernate，它的对象有三种状态，transient、persistent、detached</p>
<p style="text-indent: 2em;">下边是常见的翻译办法：</p>
<p style="text-indent: 2em;">transient：瞬态或者自由态</p>
<p style="text-indent: 2em;">(new DeptPo(1,&#8221;行政部&#8221;,20,&#8221;行政相关&#8221;)，该po的实例和session没有关联，该po的实例处于transient)</p>
<p style="text-indent: 2em;">persistent：持久化状态</p>
<p style="text-indent: 2em;">(和数据库中记录想影射的Po实例，它的状态是persistent, 通过get和load等得到的对象都是persistent)</p>
<p style="text-indent: 2em;">detached：脱管状态或者游离态</p>
<p style="text-indent: 2em;">(1)当通过get或load方法得到的po对象它们都处于persistent,但如果执
行delete(po)时(但不能执行事务),该po状态就处于detached,
(表示和session脱离关联),因delete而变成游离态可以通过save或saveOrUpdate()变成持久态</p>
<p style="text-indent: 2em;">(2)当把session关闭时，session缓存中的persistent的po对象也变成detached</p>
<p style="text-indent: 2em;">因关闭session而变成游离态的可以通过lock、save、update变成持久态</p>
<p style="text-indent: 2em;">持久态实例可以通过调用 delete()变成脱管状态。</p>
<p style="text-indent: 2em;">通过get()或load()方法得到的实例都是持久化状态的。</p>
<p style="text-indent: 2em;">脱管状态的实例可以通过调用lock()或者replicate()进行持久化。</p>
<p style="text-indent: 2em;">save()和persist()将会引发SQL的INSERT，delete()会引发SQLDELETE，</p>
<p style="text-indent: 2em;">而update()或merge()会引发SQL UPDATE。对持久化（persistent）实例的修改在刷新提交的时候会被检测到，它也会引起SQL UPDATE。</p>
<p style="text-indent: 2em;">saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE</p>
<p style="text-indent: 2em;">二、save 和update区别</p>
<p style="text-indent: 2em;">把这一对放在第一位的原因是因为这一对是最常用的。</p>
<p style="text-indent: 2em;">save的作用是把一个新的对象保存</p>
<p style="text-indent: 2em;">update是把一个脱管状态的对象或自由态对象（一定要和一个记录对应）更新到数据库</p>
<p style="text-indent: 2em;">三、update 和saveOrUpdate区别</p>
<p style="text-indent: 2em;">这个是比较好理解的，顾名思义，saveOrUpdate基本上就是合成了save和update,而update只是update;引用hibernate reference中的一段话来解释他们的使用场合和区别</p>
<p style="text-indent: 2em;">通常下面的场景会使用update()或saveOrUpdate()： </p>
<p style="text-indent: 2em;">程序在第一个session中加载对象,接着把session关闭 </p>
<p style="text-indent: 2em;">该对象被传递到表现层 </p>
<p style="text-indent: 2em;">对象发生了一些改动 </p>
<p style="text-indent: 2em;">该对象被返回到业务逻辑层最终到持久层 </p>
<p style="text-indent: 2em;">程序创建第二session调用第二个session的update()方法持久这些改动 </p>
<p style="text-indent: 2em;">saveOrUpdate(po)做下面的事: </p>
<p style="text-indent: 2em;">如果该po对象已经在本session中持久化了，在本session中执行saveOrUpdate不做任何事 </p>
<p style="text-indent: 2em;">如果savaOrUpdate(新po)与另一个与本session关联的po对象拥有相同的持久化标识(identifier)，抛出一个异常 </p>
<p style="text-indent: 2em;">org.hibernate.NonUniqueObjectException: a
different object with the same identifier value was already associated
with the session: [org.itfuture.www.po.Xtyhb#5]</p>
<p style="text-indent: 2em;">saveOrUpdate如果对象没有持久化标识(identifier)属性，对其调用save() ，否则update() 这个对象 </p>
<p style="text-indent: 2em;">四、persist和save区别</p>
<p style="text-indent: 2em;">这个是最迷离的一对，表面上看起来使用哪个都行，在hibernate reference文档中也没有明确的区分他们.</p>
<p style="text-indent: 2em;">这里给出一个明确的区分。（可以跟进src看一下，虽然实现步骤类似，但是还是有细微的差别）</p>
<p style="text-indent: 2em;">主要内容区别：</p>
<p style="text-indent: 2em;">1，persist把一个瞬态的实例持久化，但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中，标识符的填入可能被推迟到flush的时候。</p>
<p style="text-indent: 2em;">2，save, 把一个瞬态的实例持久化标识符，及时的产生,它要返回标识符，所以它会立即执行Sql insert</p>
<p style="text-indent: 2em;">五、saveOrUpdate,merge和update区别</p>
<p style="text-indent: 2em;">比较update和merge</p>
<p style="text-indent: 2em;">update的作用上边说了，这里说一下merge的</p>
<p style="text-indent: 2em;">如果session中存在相同持久化标识(identifier)的实例，用用户给出的对象覆盖session已有的持久实例 </p>
<p style="text-indent: 2em;">(1)当我们使用update的时候，执行完成后，会抛出异常 </p>
<p style="text-indent: 2em;">(2)但当我们使用merge的时候，把处理自由态的po对象A的属性copy到session当中处于持久态的po的属性中，执行完成后原来是持久状态还是持久态，而我们提供的A还是自由态</p>
<p style="text-indent: 2em;">六、flush和update区别</p>
<p style="text-indent: 2em;">这两个的区别好理解</p>
<p style="text-indent: 2em;">update操作的是在自由态或脱管状态(因session的关闭而处于脱管状态)的对象//updateSQL</p>
<p style="text-indent: 2em;">而flush是操作的在持久状态的对象。</p>
<p style="text-indent: 2em;">默认情况下，一个持久状态的对象的改动（包含set容器）是不需要update的，只要你更改了对象的值，等待hibernate flush就自动更新或保存到数据库了。hibernate flush发生在以下几种情况中：</p>
<p style="text-indent: 2em;">1， 调用某些查询的和手动flush(),session的关闭、SessionFactory关闭结合 </p>
<p style="text-indent: 2em;">get()一个对象，把对象的属性进行改变,把资源关闭。</p>
<p style="text-indent: 2em;">2，transaction commit的时候（包含了flush）</p>
<p style="text-indent: 2em;">七、lock和update区别</p>
<p style="text-indent: 2em;">update是把一个已经更改过的脱管状态的对象变成持久状态</p>
<p style="text-indent: 2em;">lock是把一个没有更改过的脱管状态的对象变成持久状态(针对的是因Session的关闭而处于脱管状态的po对象(2)，不能针对因delete而处于脱管状态的po对象)</p>
<p style="text-indent: 2em;">对应更改一个记录的内容，两个的操作不同：</p>
<p style="text-indent: 2em;">update的操作步骤是：</p>
<p style="text-indent: 2em;">(1)属性改动后的脱管的对象的修改-&gt;调用update</p>
<p style="text-indent: 2em;">lock的操作步骤是：</p>
<p style="text-indent: 2em;">(2)调用lock把未修改的对象从脱管状态变成持久状态--&gt;更改持久状态的对象的内容--&gt;等待flush或者手动flush</p>
<p style="text-indent: 2em;">八、clear和evcit的区别</p>
<p style="text-indent: 2em;">clear完整的清除session缓存</p>
<p style="text-indent: 2em;">evcit(obj)把某个持久化对象从session的缓存中清空。</p>
</div>
</div>
</div>
<img src ="http://www.blogjava.net/sealyu/aggbug/291759.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-08-19 11:00 <a href="http://www.blogjava.net/sealyu/archive/2009/08/19/291759.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0中关于Jpa的复合主键（转）</title><link>http://www.blogjava.net/sealyu/archive/2009/08/19/291730.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 19 Aug 2009 00:23:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/08/19/291730.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/291730.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/08/19/291730.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/291730.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/291730.html</trackback:ping><description><![CDATA[当我们需要使用一个或多个属性变量（表中的一列或多列）联合起来作为主键，我们需要使用复合主键。在EJB3.0中复合主键要求我们编写一个复合主键类(
Composite Primary Key Class )。下面是个小例子，在Student中要用sid和name做复合主键。<br />
Student实体类：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.persistence.Column;<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.persistence.Entity;<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.persistence.Id;<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.persistence.IdClass;<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">@Entity<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">@IdClass(StudentPK.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Student&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;sid;<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;name;<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;age;<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Id<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getSid()&nbsp;{<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;sid;<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setSid(String&nbsp;sid)&nbsp;{<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sid;<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Id<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getName()&nbsp;{<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;name;<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setName(String&nbsp;name)&nbsp;{<br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;name;<br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Column<br />
</span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getAge()&nbsp;{<br />
</span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;age;<br />
</span><span style="color: #008080;">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setAge(String&nbsp;age)&nbsp;{<br />
</span><span style="color: #008080;">35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.age&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;age;<br />
</span><span style="color: #008080;">36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">37</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">38</span>&nbsp;<span style="color: #000000;">}</span></div>
主键<span style="color: #000000;">StudentPK类：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.Serializable;<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;StudentPK&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Serializable{<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">final</span>&nbsp;<span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;serialVersionUID&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">1L</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;sid;<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;name;<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;StudentPK(){}<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;StudentPK(String&nbsp;sid,String&nbsp;name){<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sid;<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;name;<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getSid()&nbsp;{<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;sid;<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setSid(String&nbsp;sid)&nbsp;{<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sid;<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getName()&nbsp;{<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;name;<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setName(String&nbsp;name)&nbsp;{<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;name;<br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
</span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;hashCode()&nbsp;{<br />
</span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;prime&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">31</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;prime&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;((name&nbsp;</span><span style="color: #000000;">==</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">?</span>&nbsp;<span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;:&nbsp;name.hashCode());<br />
</span><span style="color: #008080;">34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;prime&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;((sid&nbsp;</span><span style="color: #000000;">==</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">?</span>&nbsp;<span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;:&nbsp;sid.hashCode());<br />
</span><span style="color: #008080;">35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result;<br />
</span><span style="color: #008080;">36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">37</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">38</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
</span><span style="color: #008080;">39</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;equals(Object&nbsp;obj)&nbsp;{<br />
</span><span style="color: #008080;">40</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">this</span>&nbsp;<span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;obj)<br />
</span><span style="color: #008080;">41</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">true</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">42</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(obj&nbsp;</span><span style="color: #000000;">==</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">43</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(getClass()&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;obj.getClass())<br />
</span><span style="color: #008080;">45</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">46</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;StudentPK&nbsp;other&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(StudentPK)&nbsp;obj;<br />
</span><span style="color: #008080;">47</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(name&nbsp;</span><span style="color: #000000;">==</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
</span><span style="color: #008080;">48</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(other.name&nbsp;</span><span style="color: #000000;">!=</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">49</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">50</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span>&nbsp;<span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">name.equals(other.name))<br />
</span><span style="color: #008080;">51</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">52</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(sid&nbsp;</span><span style="color: #000000;">==</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
</span><span style="color: #008080;">53</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(other.sid&nbsp;</span><span style="color: #000000;">!=</span>&nbsp;<span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">54</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">55</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span>&nbsp;<span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">sid.equals(other.sid))<br />
</span><span style="color: #008080;">56</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">57</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span>&nbsp;<span style="color: #0000ff;">true</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">58</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">59</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">60</span>&nbsp;<span style="color: #000000;">}</span></div>
主键类必需满足下列条件：<br />
(1)必需被序列化<br />
(2)必需有一个公共的无参构造方法<br />
(3)必需实现equals()和hashCode()方法<br />
<br />
当你查询Student实体时必须使用主键类才能识别实体如:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp; StudentPK&nbsp;pk&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;StudentPK(</span><span style="color: #000000;">"</span><span style="color: #000000;">bj1001</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">jakin</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;Student&nbsp;student&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;entityManager.find(Student.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;pk);</span></div>
在测试本例时笔者犯了两个低级的错误，一是测试环境的数据库不是项目运行的数据库，二是实体类中的属性命名用了关键字，请引以为戒。
<img src ="http://www.blogjava.net/sealyu/aggbug/291730.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-08-19 08:23 <a href="http://www.blogjava.net/sealyu/archive/2009/08/19/291730.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>标注枚举类型@Enumerated（转）</title><link>http://www.blogjava.net/sealyu/archive/2009/06/30/284749.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Tue, 30 Jun 2009 05:18:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/06/30/284749.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/284749.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/06/30/284749.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/284749.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/284749.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">实体</span><font face="Times New Roman">Entity</font><span style="font-family: 宋体;">中通过</span><font face="Times New Roman">@Enumerated</font><span style="font-family: 宋体;">标注枚举类型，例如将</span><font face="Times New Roman">CustomerEO</font><span style="font-family: 宋体;">实体中增加一个</span><font face="Times New Roman">CustomerType</font><span style="font-family: 宋体;">类型的枚举型属性，标注实体后的代码如下所示。</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">@Entity</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">@Table(name = "customer")</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">public class CustomerEO implements java.io.Serializable {</font></p>
<p style="margin: 0cm 0cm 0pt auto; text-indent: 21pt;"><span style="font-family: 黑体;"><font style="background-color: #e0e0e0;">&#8230;&#8230;</font></span></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private CustomerType type;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Enumerated(EnumType.STRING)</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public CustomerType getType() {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return type;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setType(CustomerType type) {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.type = type;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public enum CustomerType {</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMPETITOR, INVESTOR, PARTNER, VENDER</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">}</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">在实体中虽然标注成枚举类型，但当实体持久化后，表中所对应的值仍旧是基本的数据类型，以上代码创建表的</span><font face="Times New Roman">SQL</font><span style="font-family: 宋体;">语句是：</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">CREATE TABLE customer (</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id int(20) NOT NULL auto_increment,</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name varchar(255),</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type varchar(255),</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRIMARY KEY (id)</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">)</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-family: 宋体;"><font size="3">使用枚举类型后，在创建实体时便可以直接引用枚举类型，例如以下代码所示。</font></span></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">CustomerEO customer = new CustomerEO();</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">customer.setName("Janet2");</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">customer.setType(<strong>CustomerType.PARTNER</strong>);</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">entityManager.persist(customer);</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">在使用</span><font face="Times New Roman">@Enumerated</font><span style="font-family: 宋体;">注释时，需要注意以下几个问题：</span></font></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span style="font-family: Wingdings;"><font size="3">l</font><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size="3"><span style="font-family: 宋体;">因为枚举类型的有名称和值两个属性，所以在持久化时可以选择持久化名称或是持久化值。通过</span><font face="Times New Roman">EnumType</font><span style="font-family: 宋体;">来定义，它有两个值如下所示。</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">public enum EnumType {</font></p>
<p style="margin: 0cm 0cm 0pt auto; text-indent: 21pt;"><font style="background-color: #e0e0e0;">ORDINAL,</font></p>
<p style="margin: 0cm 0cm 0pt auto; text-indent: 21pt;"><font style="background-color: #e0e0e0;">STRING</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">}</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><font face="Times New Roman">ORDINAL</font><span style="font-family: 宋体;">表示持久化的为枚举类型的值，</span><font face="Times New Roman">STRING</font><span style="font-family: 宋体;">表示持久化的为枚举类型的名称。默认为</span><font face="Times New Roman">ORDINAL</font><span style="font-family: 宋体;">，持久化值。例如以上示例中标注的为</span><font face="Times New Roman">STRING</font><span style="font-family: 宋体;">，这样持久化实体后，数据库中保存的是枚举类型的名称，如图</span><span style="font-family: 宋体;">所示。</span></font></p>
<p style="margin: 0cm 0cm 12pt;" align="center"><span style="font-family: 宋体;"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/EJB_JPA/5.5.jpg" /></span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">若此时改成</span><font face="Times New Roman">ORDINAL</font><span style="font-family: 宋体;">，代码如下：</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Enumerated(EnumType.ORDINAL)</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public CustomerType getType() {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return type;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">则同样持久化的实体后，数据库保存的结果如图</span><span style="font-family: 宋体;">所示。</span></font></p>
<p style="margin: 0cm 0cm 12pt;" align="center"><span style="font-family: 宋体;"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/EJB_JPA/5.6.jpg" /></span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span style="font-family: Wingdings;"><font size="3">l</font><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size="3"><span style="font-family: 宋体;">如何选择</span><font face="Times New Roman">STRING</font><span style="font-family: 宋体;">和</span><font face="Times New Roman">ORDINAL</font><span style="font-family: 宋体;">：</span></font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">如果使用</span><font face="Times New Roman">STRING</font><span style="font-family: 宋体;">保存，虽然从数据库中查询数据时非常直观，能够清楚的看出该类型代表意义，但这样也会带来其他的问题。若此时枚举类型的定义改变，例如上例中的枚举类型名称改为：</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public enum CustomerType {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CUST_COMPETITOR, INVESTOR, PARTNER, VENDER</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">则此时数据库中保存的&#8220;</span><font face="Times New Roman">COMPETITOR</font><span style="font-family: 宋体;">&#8221;的值将不能转化为枚举类型</span><font face="Times New Roman">CustomerType</font><span style="font-family: 宋体;">中的&#8220;</span><font face="Times New Roman">CUST_COMPETITOR</font><span style="font-family: 宋体;">&#8221;的值。但若使用</span><font face="Times New Roman">ORDINAL</font><span style="font-family: 宋体;">则不会带来这种问题。所以建议使用</span><font face="Times New Roman">ORDINAL</font><span style="font-family: 宋体;">类型来持久化枚举类型。</span></font></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span style="font-family: Wingdings;"><font size="3">l</font><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size="3"><span style="font-family: 宋体;">枚举类型的定义位置，实体外部</span><font face="Times New Roman">VS</font><span style="font-family: 宋体;">实体内部。</span></font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">上例中</span><font face="Times New Roman">CustomerType</font><span style="font-family: 宋体;">枚举类型定义在</span><font face="Times New Roman">CustomerEO</font><span style="font-family: 宋体;">实体内部，这是因为只有</span><font face="Times New Roman">CustomerEO</font><span style="font-family: 宋体;">这个实体会使用</span><font face="Times New Roman">CustomerType</font><span style="font-family: 宋体;">类型，其他的实体不会使用该类型。该类型与这个实体关系紧密联系。</span></font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">但若此时多个实体公用一个枚举类型时，则可以将枚举类型单独定义，定义在实体的外部。有这样一个枚举类型</span><font face="Times New Roman">BusinessLine</font><span style="font-family: 宋体;">，它定义在实体外部，代码如下：</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">public enum BusinessLine {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; REAL_ESTATE,FINANCE, NON_PROFIT</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">}</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="3"><span style="font-family: 宋体;">例如</span><font face="Times New Roman">CustomerEO</font><span style="font-family: 宋体;">实体增加一个</span><font face="Times New Roman">BusinessLine</font><span style="font-family: 宋体;">的枚举类型，代码如下所示。</span></font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">@Entity</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">@Table(name = "customer")</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">public class CustomerEO implements java.io.Serializable {</font></p>
<p style="margin: 0cm 0cm 0pt auto; text-indent: 21pt;"><span style="font-family: 黑体;"><font style="background-color: #e0e0e0;">&#8230;&#8230;</font></span></p>
<p style="margin: 0cm 0cm 0pt auto;"><strong><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private BusinessLine businessLine;</font></strong></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Enumerated(EnumType.STRING)</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public BusinessLine getBusinessLine() {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return businessLine;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setBusinessLine(BusinessLine businessLine) {</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.businessLine = businessLine;</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p style="margin: 0cm 0cm 0pt auto;"><font style="background-color: #e0e0e0;">}</font></p>
<img src ="http://www.blogjava.net/sealyu/aggbug/284749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-06-30 13:18 <a href="http://www.blogjava.net/sealyu/archive/2009/06/30/284749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>org.hibernate.HibernateException: Found shared references to a collection</title><link>http://www.blogjava.net/sealyu/archive/2009/05/06/269180.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 06 May 2009 02:45:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/05/06/269180.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/269180.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/05/06/269180.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/269180.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/269180.html</trackback:ping><description><![CDATA[<span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry">BeanUtil.copyProperties()的方式复制一个实体bean的时候，如果这个实体bean有一个集合属性，因为这个方法只是做了一个浅拷贝，所以新拷贝的实体跟旧的实体引用了同一个集合，而这在hibernate中是不允许的，所以报错。<br />
解决方法：<br />
在拷贝后，新建一个集合，将原来的集合元素添加进去，并赋值给新拷贝的实体。<br />
</span>
<img src ="http://www.blogjava.net/sealyu/aggbug/269180.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-05-06 10:45 <a href="http://www.blogjava.net/sealyu/archive/2009/05/06/269180.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sorted collections in Hibernate</title><link>http://www.blogjava.net/sealyu/archive/2009/05/05/268982.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Tue, 05 May 2009 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/05/05/268982.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/268982.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/05/05/268982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/268982.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/268982.html</trackback:ping><description><![CDATA[<h3>Problem</h3>
<p>We want a collection field belonging to an entity object to be sorted.</p>
<h3>Solution</h3>
<p>There are two possible solutions:</p>
<ul>
    <li>If you want the collection to be sorted when loaded, but not necessarily keep that sorting order all the time, use the <code>OrderBy</code> annotation where you set the actual <code>ORDER BY</code> SQL clause. In that case, the collection can be of any type (e.g. <code>Collection</code>).</li>
    <li>
    <p>If you want the collection to be sorted at all times, make it of type <code>SortedSet</code> or <code>SortedMap</code> and set the <code>Sort</code> annotation.</p>
    <ul>
        <li>If the objects in the collection implements <code>Comparable</code> set type to <code>SortType.NATURAL</code>.</li>
        <li>Otherwise set it to <code>SortType.COMPARATOR</code> and specify your own <code>Comparator</code> class in the <code>comparator</code> attribute.</li>
    </ul>
    </li>
</ul>
<h3>Remarks</h3>
<ul>
    <li>There exists an annotation with name <code>OrderBy</code> in both the <code>javax.persistence</code> package as well as the <code>org.hibernate.annotations</code> package. The former should be used.</li>
</ul>
<img src ="http://www.blogjava.net/sealyu/aggbug/268982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-05-05 15:09 <a href="http://www.blogjava.net/sealyu/archive/2009/05/05/268982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javax.persistence.PersistenceException: org.hibernate.MappingException: Cannot use identity column key generation with &lt;union-subclass&gt; mapping for xxxxxxxxxxxxxxxx</title><link>http://www.blogjava.net/sealyu/archive/2009/02/09/253902.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 09 Feb 2009 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/02/09/253902.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/253902.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/02/09/253902.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/253902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/253902.html</trackback:ping><description><![CDATA[今天在将ejb3的工程部署到jboss启动时报错：<br />
State: FAILED<br />
&nbsp; Reason: javax.persistence.PersistenceException: org.hibernate.MappingException: Cannot use identity column key generation with &lt;union-subclass&gt; mapping for: com.xxx.xxxx<br />
<br />
后来发现问题所在：<br />
<br />
继承策略我选择了@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)，<br />
同时在父类中设置了ID生成策略为：<br />
@Id<br />
&nbsp;&nbsp; &nbsp;@GeneratedValue(strategy=GenerationType.IDENTITY)<br />
&nbsp;&nbsp; &nbsp;public Long getId() {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return id;<br />
&nbsp;&nbsp; &nbsp;}<br />
而在这种策略下使用unnion-subclass 元素时 父类的标识属性生成器不能使用&#8220;<font color="#ff0000"><strong>indentity&#8221;</strong></font> ，将策略改为
@GeneratedValue(strategy=GenerationType.TABLE)<br />
问题解决。<br />
<img src ="http://www.blogjava.net/sealyu/aggbug/253902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-02-09 14:19 <a href="http://www.blogjava.net/sealyu/archive/2009/02/09/253902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB/JPA继承详解(转)</title><link>http://www.blogjava.net/sealyu/archive/2009/01/05/249911.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Mon, 05 Jan 2009 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/01/05/249911.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/249911.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/01/05/249911.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/249911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/249911.html</trackback:ping><description><![CDATA[因为关系数据库的表之间不存在继承关系，Entity 提供三种基本的继承映射策略：<br />
每个类分层结构一张表(table per class hierarchy)<br />
每个子类一张表(table per subclass)<br />
每个具体类一张表(table per concrete class)<br />
<br />
<font color="#ff0000">一、每个类分层结构一张表(table per class hierarchy)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    这种映射方式只需为基类创建一个表即可。在表中不仅提供基类所有属性对应的字段，还要提供所有子类属性对应的字段，此外还需要一个字段用于区分子类的具体类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    要使用每个类分层结构一张表(table per class hierarchy) 策略，需要把<font color="#ff0000">@javax.persistence.Inheritance</font> 注释的<font color="#0000ff">strategy</font>属性设置为<font color="#3366ff">InheritanceType.SINGLE_TABLE</font>。除非你要改变子类的映射策略，否则<strong><font color="#ff0000">@Inheritance</font> 注释只能放在继承层次的基类</strong>。通过鉴别字段的值，持久化引掣可以区分出各个类，并且知道每个类对应那些字段。<font color="#cc99ff">鉴别字段</font>通过<font color="#ff0000">@javax.persistence.DiscriminatorColumn</font> 注释进行定义，<font color="#0000ff">name</font> 属性定义<font color="#cc99ff">鉴别字段的列名</font><font color="#0000ff"><font color="#000000">，</font>discriminatorType </font>属性定义<font color="#cc99ff">鉴别字段的类型</font>（可选值有：String, Char, Integer），如果鉴别字段的类型为String 或Char，可以用length 属性定义其长度。<font color="#ff0000">@DiscriminatorValue</font> 注释为继承关系中的<font color="#cc99ff">每个类定义鉴别值</font>，如果不指定鉴别值，默认采用类名<br />
例:<br />
&nbsp;&nbsp;&nbsp;    @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;    @Entity<br />
&nbsp;&nbsp;&nbsp;    @Table(name="Vehicle_Hierarchy")<br />
&nbsp;&nbsp;&nbsp;    <font color="#ff0000">@Inheritance(strategy=InheritanceType.SINGLE_TABLE)</font><br />
&nbsp;&nbsp;&nbsp;    @DiscriminatorColumn(name="Discriminator",<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;    discriminatorType = DiscriminatorType.STRING,<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;    length=30)<br />
&nbsp;&nbsp;&nbsp;    @DiscriminatorValue("Vehicle")<br />
&nbsp;&nbsp;&nbsp;    <font color="#0000ff">public class Vehicle implements Serializable{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000"> //基类</font></font><br />
&nbsp;&nbsp;&nbsp;    private Long id;<br />
&nbsp;&nbsp;&nbsp;    private Short speed;//速度<br />
&nbsp;&nbsp;&nbsp;    @Id<br />
&nbsp;&nbsp;&nbsp;    @GeneratedValue<br />
&nbsp;&nbsp;&nbsp;    @Column(columnDefinition="integer")//指定使用适配Integer长度的数据类型<br />
&nbsp;&nbsp;&nbsp;    public Long getId() {<br />
&nbsp;&nbsp;&nbsp;    return id;<br />
&nbsp;&nbsp;&nbsp;    }<br />
&nbsp;&nbsp;&nbsp;    public void setId(Long id) {<br />
&nbsp;&nbsp;&nbsp;    this.id = id;<br />
&nbsp;&nbsp;&nbsp;    }<br />
<br />
&nbsp;&nbsp;&nbsp;   @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;   @Entity<br />
&nbsp;&nbsp;&nbsp;   @DiscriminatorValue("Car")<br />
&nbsp;&nbsp;&nbsp;   <font color="#0000ff">public class Car extends Vehicle{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000"> //Vehicle的子类</font></font><br />
&nbsp;&nbsp;&nbsp;   private String engine;//发动机<br />
&nbsp;&nbsp;&nbsp;   @Column(nullable=true,length=30)<br />
&nbsp;&nbsp;&nbsp;   public String getEngine() {<br />
&nbsp;&nbsp;&nbsp;   return engine;<br />
&nbsp;&nbsp;&nbsp;   }<br />
&nbsp;&nbsp;&nbsp;   public void setEngine(String engine) {<br />
&nbsp;&nbsp;&nbsp;   this.engine = engine;<br />
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   }<br />
&nbsp;&nbsp;&nbsp;   }<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;   @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;   @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;   @DiscriminatorValue("Camion")<br />
&nbsp;&nbsp;&nbsp;&nbsp;   <font color="#0000ff">public class Camion extends Car{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   <font color="#ff0000">//Car的子类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;   private String container;//集装箱<br />
&nbsp;&nbsp;&nbsp;&nbsp;   @Column(nullable=true,length=30)<br />
&nbsp;&nbsp;&nbsp;&nbsp;   public String getContainer() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;   return container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;   }<br />
&nbsp;&nbsp;&nbsp;&nbsp;   public void setContainer(String container) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;   this.container = container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   }<br />
&nbsp;&nbsp;&nbsp;&nbsp;   }<br />
<strong><font color="#ff0000">分析:</font></strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   <font color="#800080">可
以看出，每个子类没有单独的映射，在数据库中没有对应的表存在。而只有一个记录所有自身属性和子类所有属性的表，在基类为Vehicle
的时候，Discriminator 字段的值将为Vehicle,在子类为Car 的时候，Discriminator
字段的值将为Car，子类为Camion 的时候，Discriminator 字段的值将为Camion。那么，如果业务逻辑要求Car
对象的engine 属性不允许为null，显然无法在Vehicle_Hierarchy 表中为engine 字段定义not null
约束，可见这种映射方式无法保证关系数据模型的数据完整性。</font><br />
<br />
<font color="#ff0000">二、每个类分层结构一张表(table per class hierarchy)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
这种映射方式为每个类创建一个表。在每个类对应的表中只需包含和这个类本身的属性对应的字段，子类对应的表参照父类对应的表,使用每个子类一张表
(table per subclass)策略，需要把@javax.persistence.Inheritance 注释的<strong>strategy </strong>属性设置为<strong>InheritanceType.JOINED<br />
<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;  @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#ff0000">@Inheritance(strategy=InheritanceType.JOINED)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Table(name="Vehicle")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#0000ff">public class Vehicle implements Serializable{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000"> //基类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  private Long id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  private Short speed;//速度<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Id<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @GeneratedValue<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Column(columnDefinition="integer")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public Long getId() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setId(Long id) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.id = id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public Short getSpeed() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return speed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setSpeed(Short speed) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.speed = speed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Table(name="Car")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  <strong>@PrimaryKeyJoinColumn(name="CarID")&nbsp;&nbsp;&nbsp;&nbsp;  //把主键对应的列名更改为CarID</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#0000ff">public class Car extends Vehicle{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </font><font color="#0000ff"><font color="#ff0000">//Vehicle的子类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  private String engine;//发动机<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Column(nullable=true,length=30)<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public String getEngine() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return engine;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setEngine(String engine) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.engine = engine;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Table(name="Camion")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  <strong>@PrimaryKeyJoinColumn(name="CamionID")&nbsp;&nbsp;&nbsp;&nbsp;  //把主键对应的列名更改为CamionID</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#0000ff">public class Camion extends Car{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </font><font color="#0000ff"><font color="#ff0000">//Car的子类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  private String container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Column(nullable=true,length=30)<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public String getContainer() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setContainer(String container) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.container = container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
<font color="#800080">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这种映射方式支持多态关联和多态查询，而且符合关系数据模型的常规设计规则。在这种策略中你可以对子类的属性对应的字段定义not null 约束。该策略的缺点：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  它的查询性能不如上面介绍的映射策略。在这种映射策略下，必须通过表的内连接或左外连接来实现多态查询和多态关联。<br />
选择原则：子类属性非常多，需要对子类某些属性对应的字段进行not null 约束，且对性能要求不是很严格时，优先选择该策略</font><br />
<br />
<font color="#ff0000">三、每个具体类一张表(table per concrete class)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
这种映射方式为每个类创建一个表。在每个类对应的表中包含和这个类所有属性（包括从超类继承的属性）对应的字段,使用每个具体类一张表(table
per concrete class)策略，需要把@javax.persistence.Inheritance 注释的<strong>strategy </strong>属性设置为<strong>InheritanceType.TABLE_PER_CLASS</strong><br />
<br />
<font color="#ff0000"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  注意:一旦使用这种策略就意味着你不能使用AUTO generator 和IDENTITY generator，即主键值不能采用数据库自动生成.</strong></font><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#ff0000">@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Table(name="Vehicle")<br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff"> public class Vehicle implements Serializable{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </font><font color="#0000ff"><font color="#ff0000">//基类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  private Long id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  private Short speed;//速度<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Id<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Column(columnDefinition="integer")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public Long getId() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setId(Long id) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.id = id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public Short getSpeed() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return speed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setSpeed(Short speed) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.speed = speed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Table(name="Car")<br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">public class Car extends Vehicle{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;  </font><font color="#0000ff"><font color="#ff0000">//Vehicle的子类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  private String engine;//发动机<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Column(nullable=true,length=30)<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public String getEngine() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return engine;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setEngine(String engine) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.engine = engine;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @SuppressWarnings("serial")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Entity<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Table(name="Camion")<br />
&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#ff0000"><font color="#0000ff">public class Camion extends Car{&nbsp;&nbsp;&nbsp;</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </font><font color="#0000ff"><font color="#ff0000">//Car的子类</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;  private String container;//集装箱<br />
&nbsp;&nbsp;&nbsp;&nbsp;  @Column(nullable=true,length=30)<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public String getContainer() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  return container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  public void setContainer(String container) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;  this.container = container;<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;&nbsp;&nbsp;  }<br />
<br />
注意:在查询时,例如: <strong>from Vehicle v</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  查询所有Vehicle时，因为他是最继承树中的根，查询结果会得到所有继承于Vehicle类的记录<br />
<font color="#ff0000">(构造的SQL Where部分：<strong>where Discriminator in ('Car', 'Camion')</strong>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <font color="#000000"><strong>delete from Vehicle v</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  执行该操作会删除自身对应记录，还会删除所有继承Vehicle的记录,因为他是最继承树中的根，就相当于清除整个表的数据<br />
<br />
</font></font><font color="#800080">该策略的优点：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在这种策略中你可以对子类的属性对应的字段定义not null 约束。<br />
该策略的缺点：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
不符合关系数据模型的常规设计规则，每个表中都存在属于基类的多余的字段。同时，为了支持策略的映射，持久化管理者需要决定使用什么方法，一种方法是在
entity
载入或多态关联时，容器使用多次查询去实现，这种方法需要对数据库做几次来往查询，非常影响执行效率。另一种方法是容器通过使用SQLUNIOU
查询来实现这种策略。<br />
选择原则：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  除非你的现实情况必须使用这种策略，一般情况下不要选择。</font>
<img src ="http://www.blogjava.net/sealyu/aggbug/249911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-01-05 14:18 <a href="http://www.blogjava.net/sealyu/archive/2009/01/05/249911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Interceptor 中onFlushDirty()函数执行多次的问题（Hibernate 的一个小Bug）</title><link>http://www.blogjava.net/sealyu/archive/2008/05/09/199527.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Fri, 09 May 2008 07:59:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2008/05/09/199527.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/199527.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2008/05/09/199527.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/199527.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/199527.html</trackback:ping><description><![CDATA[最近在项目中遇到一个奇怪的问题，在使用Hibernate拦截器捕获实体变化并进行处理时，发现其中的onFlushDirty()函数执行了很多次，导致进行处理时产生很多重复数据。具体问题如下：<br />
使用一个类继承Hibernate的EmptyInterceptor类来对程序中的实体变化进行拦截，并在其中的onFlushDirty()函数中对捕获的数据进行处理，产生对应的event数据并保存到数据库中。 例如：<br />
public class EventInterceptor extends EmptyInterceptor {<br />
public boolean onFlushDirty(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object entity,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Serializable id,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object[] currentState,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object[] previousState,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] propertyNames,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type[] types ) throws CallbackException {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(isAuditable(entity)){//如果该实体需要被记录，生成对应的event。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //此处生成对应的event。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
在程序执行后，发现对应一条实体的变化生成了多条重复的event记录，非常不解。<br />
后来google发现，有人也碰到过对应的问题，并在Hibernage论坛中提出过这个问题，鉴定为Hibernate的一个小Bug。<br />
（原文地址：http://forum.hibernate.org/viewtopic.php?t=940410&amp;highlight=interceptor+onflushdirty）<br />
解决方法如下：<br />
将FlushMode改为：FlushMode.COMMIT<br />
或者也可以提前进行flush()<br />
都可以解决这个问题。<br />
<br />
<img src ="http://www.blogjava.net/sealyu/aggbug/199527.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2008-05-09 15:59 <a href="http://www.blogjava.net/sealyu/archive/2008/05/09/199527.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>