??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲精品成人AA片新蒲金,久久久影院亚洲精品,久久久久se色偷偷亚洲精品avhttp://www.tkk7.com/jjshcc/category/44963.htmlzh-cnMon, 03 Sep 2012 20:40:33 GMTMon, 03 Sep 2012 20:40:33 GMT60hibernate中set的排?/title><link>http://www.tkk7.com/jjshcc/archive/2012/09/03/386839.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 03 Sep 2012 02:03:00 GMT</pubDate><guid>http://www.tkk7.com/jjshcc/archive/2012/09/03/386839.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/386839.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2012/09/03/386839.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/386839.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/386839.html</trackback:ping><description><![CDATA[<object id="reader" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" height="500" width="450" align="center" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"> <param value="window" name="wmode" /><param value="true" name="allowfullscreen" /><param name="allowscriptaccess" value="always" /><param value="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&docid=cd885f6a1eb91a37f1115cd5&title=hibernate%E4%B8%ADset%E7%9A%84%E6%8E%92%E5%BA%8F&doctype=doc&fpn=5&npn=5&readertype=external&catal=0&cdnurl=http://txt.wenku.baidu.com/play" name="movie" /><embed width="450" align="center" height="500" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" name="reader" src="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&docid=cd885f6a1eb91a37f1115cd5&title=hibernate%E4%B8%ADset%E7%9A%84%E6%8E%92%E5%BA%8F&doctype=doc&fpn=5&npn=5&readertype=external&catal=0&cdnurl=http://txt.wenku.baidu.com/play" wmode="window" allowscriptaccess="always" bgcolor="#FFFFFF" ver="9.0.0" allowfullscreen="true"></embed></object><img src ="http://www.tkk7.com/jjshcc/aggbug/386839.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2012-09-03 10:03 <a href="http://www.tkk7.com/jjshcc/archive/2012/09/03/386839.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate主键生成{略 http://www.tkk7.com/jjshcc/archive/2012/08/31/386683.htmlEric_jiangEric_jiangFri, 31 Aug 2012 05:29:00 GMThttp://www.tkk7.com/jjshcc/archive/2012/08/31/386683.htmlhttp://www.tkk7.com/jjshcc/comments/386683.htmlhttp://www.tkk7.com/jjshcc/archive/2012/08/31/386683.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/386683.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/386683.html

 

1、自动增长identity

适用于MySQL、DB2、MS SQL ServerQ采用数据库生成的主键,用于为long、short、intcd生成唯一标识
使用SQL Server ?MySQL 的自增字D,q个Ҏ(gu)不能攑ֈ Oracle 中,Oracle 不支持自增字D,要设定sequenceQMySQL ?SQL Server 中很常用Q?br />数据库中的语法如下:
MySQLQcreate table t_user(id int auto_increment primary key, name varchar(20));
SQL ServerQcreate table t_user(id int identity(1,1) primary key, name varchar(20));

 

<id name="id" column="id" type="long">
    <generator class="identity" />
</id>
 
2、sequence

DB2、Oracle均支持的序列Q用于ؓlong、short或int生成唯一标识
数据库中的语法如下:
OracleQcreate sequence seq_name increment by 1 start with 1;
需要主键值时可以调用seq_name.nextval或者seq_name.curval得到Q数据库会帮助我们维护这个sequence序列Q保证每ơ取到的值唯一Q如Q?br />insert into tbl_name(id, name) values(seq_name.nextval, ‘Jimliu’);

 

<id name="id" column="id" type="long">
    <generator class="sequence">
       <param name="sequence">seq_name</param>
   </generator>
</id>
 
如果我们没有指定sequence参数Q则Hibernate会访问一个默认的sequenceQ是hibernate_sequenceQ我们也需要在数据库中建立q个sequence
此外Qsequenceq可以有另外一个参数是paramtersQ可以查看Hibernate的API了解它的用法Q见org.hibernate.id.SequenceGenerator
调用数据库的sequence来生成主键,要设定序列名Q不然hibernate无法扑ֈQ?br /><param name="sequence">NAME_SEQ</param>QOracle中很常用Q?/p>

 

 

3、hilo

使用一个高/低位法生成的long、short或intcd的标识符Q给定一个表和字D作为高位值的来源Q默认的表是hibernate_unique_keyQ默认的字段是next_hi。它?yu)id的生源分成两部分,DB+内存Q然后按照算法结合在一起生id|可以在很的q接ơ数内生多条记录,提高效率

MySQLQcreate table hi_value(next_hi integer not null);

 

insert into hi_value(next_hi) values(1);

 

 

<id name="id" column="id">
    <generator class="hilo">
       <param name="table">hi_value</param>
       <param name="column">next_hi</param>
       <param name="max_lo">100</param>
   </generator>
</id>
 
在hibernate持久化的时候,由hibernate负责生成低位倹{hilo标识W生成器在生成标识符旉要从hi_value表中取出next_hi的当前|然后修改该|q个操作是在单独的事务中完成的。最大的低值在属性max_lo中配|,但在Hibernate内存中生成的低位Dq此值时Q就有需要到数据库的hi_value表中再次d高位g
使用hilo生成{略Q要在数据库中徏立一张额外的表,默认表名为hibernate_unique_key,默认字段为integercdQ名U是next_hiQ比较少用)
我们也可以自p|自定义的表名和字段?br /><id name="id" type="integer">
   <column name="id"/>
   <generator class="hilo">
      <param name="my_unique_key"/>
      <param column="next_hi"/>
   </generator>
</id>

 

 


4、native

 

会根据底层数据库的能力,从identity、sequence、hilo中选择一个,灉|性更强,但此Ӟ如果选择sequence或者hiloQ则所有的表的主键都会从Hibernate默认的sequence或者hilo表中取。ƈ且,有的数据库对于默认情况主键生成测试的支持Q效率ƈ不是很高
     对于 oracle 采用 Sequence 方式Q对于MySQL ?SQL Server 采用identityQ自增主键生成机ӞQnative是主键的生成工作交由数据库完成,hibernate不管Q很常用Q?/p>

 

<id name="id" column="id">
    <generator class="native" />
</id>
 
5、seqhilo

sequence和hilo的结合,hilo的高位由sequence产生Q所以也需要底层数据库的支?br />通过hilo法实现Q但是主键历史保存在Sequence中,适用于支?Sequence 的数据库Q如 OracleQ比较少用)

 

<id name="id" column="id">
   <generator class="seqhilo">
      <param name="sequence">seq_name</param>
      <param name="max_lo">100</param>
   </generator>
</id>
 
6、increment

q个是由Hibernate在内存中生成主键Q每ơ增量ؓ1Q不依赖于底层的数据库,因此所有的数据库都可以使用Q但问题也随之而来Q由于是Hibernate生成的,所以只

 

 

能有一个Hibernate应用q程讉K数据库,否则׃产生主键冲突Q不能在集群情况下?br />插入数据的时候hibernate会给主键d一个自增的主键Q但是一个hibernate实例q护一个计数器Q所以在多个实例q行的时候不能用这个方?br /><id name="id" column="id">
    <generator class="increment" />
</id>
 
7?/p>

uuid.hex

 

 

使用一?28-bit的UUID法生成字符串类型的标识W,UUID被编码成一?2?6q制数字的字W串。UUID包含QIP地址、JVM启动旉、系l时__?/4U)和一个计数器|JVM中唯一Q?br />hibernate会算Z?28位的唯一值插?/p>

<id name="id" column="id">
    <generator class="uuid.hex" />
</id>

 


uuid.string
       hibernate会算Z?6位的值插?/p>

 


8、assigned

由应用程序负责生成主键标识符Q往往使用在数据库中没有代理主键,使用的主键与业务相关的情况,如:

 

 

<id name="id" column="id" type="string">
    <generator class="assigned" />
</id>
 
q种主键的生成方式不使用Q在数据库表设计时就应该使用代理主键Qsurrogate keyQ,不应使用自然主键Qnatural keyh业务含义Q,在没有指?lt;generator>标签Ӟ默认是assigned主键的生成方?br />在插入数据的时候主键由用户自己dQhibernate也不?/p>

 


9、foreign
使用外部表的字段作ؓ主键

 

10、select
使用触发器生成主键(主要用于早期的数据库主键生成机制Q少用)

ps:

代理主键是指与业务无关且能唯一标识数据库中记录,一般是数据库自动生成的,比如mysql可以使用auto_increment,Sql2000可以使用identity生成方式,oracle可以使用sequence生成方式自然主键指业务相?qh?且能唯一标识数据库中的Q意一条记?/span>


介版Q?/span>

incrementQ代理主键,适合于所有数据库Q由hibernatel护主键自增Q和底层数据库无养I但是不适合?个或以上hibernateq程?/p>

identityQ代理主键,适合于Mysql或ms sql server{支持自增的dbmsQ主键g由hibernatel护?/span>

sequenceQ代理主键,适合于oracle{支持序列的dbmsQ主键g由hibernatel护Q由序列产生?/span>

nativeQ代理主键,Ҏ(gu)底层数据库的具体Ҏ(gu)选择适合的主键生成策略,如果是mysql或sqlserverQ选择identityQ如果是oracleQ选择sequence?/p>

hiloQ代理主键,hibernate把特定表的字D作为hign|生成主键?/p>

uuid.hexQ代理主键,hibernate采用uuid 128位算法生成基于字W串的主键?/p>

assignQ适合于应用程序维护的自然主键?/p>

Eric_jiang 2012-08-31 13:29 发表评论
]]>
Equals and HashCodehttp://www.tkk7.com/jjshcc/archive/2011/07/02/353549.htmlEric_jiangEric_jiangSat, 02 Jul 2011 06:06:00 GMThttp://www.tkk7.com/jjshcc/archive/2011/07/02/353549.htmlhttp://www.tkk7.com/jjshcc/comments/353549.htmlhttp://www.tkk7.com/jjshcc/archive/2011/07/02/353549.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/353549.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/353549.htmlJava's Collections and Relational database (and thus Hibernate) relies heavily on being able to distinguish objects in a unified way. In Relational database's this is done with primary keys, in Java we have equals() and hashCode() methods on the objects. This page tries to discuss the best strategies for implementation of equals() and hashcode() in your persistent classes.

 
Why are equals() and hashcode() important
Normally, most Java objects provide a built-in equals() and hashCode() based on the object's identity; so each new() object will be different from all others.

This is generally what you want in ordinary Java programming. And if all your objects are in memory, this is a fine model. Hibernate's whole job, of course, is to move your objects out of memory. But Hibernate works hard to prevent you from having to worry about this.

Hibernate uses the Hibernate session to manage this uniqueness. When you create an object with new(), and then save it into a session, Hibernate now knows that whenever you query for an object and find that particular object, Hibernate should return you that instance of the object.  And Hibernate will do just that.

However, once you close the Hibernate session, all bets are off. If you keep holding onto an object that you either created or loaded in a Hibernate session that you have now closed, Hibernate has no way to know about those objects. So if you open another session and query for "the same" object, Hibernate will return you a new instance. Hence, if you keep collections of objects around between sessions, you will start to experience odd behavior (duplicate objects in collections, mainly).

The general contract is: if you want to store an object in a List, Map or a Set then it is an requirement that equals and hashCode are implemented so they obey the standard contract as specified in the  documentation.

 
What is the problem after all?
So let's say you do want to keep objects around from session to session, e.g. in a Set related to a particular application user or some other scope that spans several Hibernate sessions.

The most natural idea that comes to mind is implementing equals() and hashCode() by comparing the property you mapped as a database identifier (ie. the primary key attribute). This will cause problems, however, for newly created objects, because Hibernate sets the identifier value for you after storing new objects. Each new instance therefore has the same identifier, null (or <literal>0</literal>). For example, if you add some new objects to a Set:

// Suppose UserManager and User are Beans mapped with Hibernate
 
UserManager u = session.load(UserManager.class, id);
 
u.getUserSet().add(new User("newUsername1")); // adds a new Entity with id = null or id = 0
u.getUserSet().add(new User("newUsername2")); // has id=null, too so overwrites last added object.
 
// u.getUserSet() now contains only the second User
As you can see relying on database identifier comparison for persistent classes can get you into trouble if you use Hibernate generated ids, because the identifier value won't be set before the object has been saved. The identifier value will be set when session.save() is called on your transient object, making it persistent.

If you use manually assigned ids (e.g. the "assigned" generator), you are not in trouble at all, you just have to make sure to set the identifier value before adding the object to the Set. This is, on the other hand, quite difficult to guarantee in most applications.

 
Separating object id and business key
To avoid this problem we recommend using the "semi"-unique attributes of your persistent class to implement equals() (and hashCode()). Basically you should think of your database identifier as not having business meaning at all (remember, surrogate identifier attributes and automatically generated vales are recommended anyway). The database identifier property should only be an object identifier, and basically should be used by Hibernate only. Of course, you may also use the database identifier as a convenient read-only handle, e.g. to build links in web applications.

 
Instead of using the database identifier for the equality comparison, you should use a set of properties for equals() that identify your individual objects. For example, if you have an "Item" class and it has a "name" String and "created" Date, I can use both to implement a good equals() method. No need to use the persistent identifier, the so called "business key" is much better. It's a natural key, but this time there is nothing wrong in using it!

 
The combination of both fields is stable enough for the life duration of the Set containing your Items. It is not as good as a primary key, but it's certainly a candidate key. You can think of this as defining a "relational identity" for your object -- the key fields that would likely be your UNIQUE fields in your relational model, or at least immutable properties of your persistent class (the "created" Date never changes).

In the example above, you could probably use the "username" property.

 
Note that this is all that you have to know about equals()/hashCode() in most cases. If you read on, you might find solutions that don't work perfectly or suggestions that don't help you much. Use any of the following at your own risk.

 
Workaround by forcing a save/flush
If you really can't get around using the persistent id for equals() / hashCode(), and if you really have to keep objects around from session to session (and hence can't just use the default equals() / hashCode()), you can work around by forcing a save() / flush() after object creation and before insertion into the set:

// Suppose UserManager and User are Beans mapped with Hibernate
 
UserManager u = session.load(UserManager.class, id);
 
User newUser = new User("newUsername1");
// u.getUserSet().add(newUser); // DO NOT ADD TO SET YET!
session.save(newUser);
session.flush();             // The id is now assigned to the new User object
u.getUserSet().add(newUser); // Now OK to add to set.
newUser = new User("newUsername2");
session.save(newUser);
session.flush();
u.getUserSet().add(newUser); // Now userSet contains both users.
 
Note that it's highly inefficient and thus not recommended. Also note that it is fragile when using disconnected object graphs on a thin client:

// on client, let's assume the UserManager is empty:
UserManager u = userManagerSessionBean.load(UserManager.class, id);
User newUser = new User("newUsername1");
u.getUserSet().add(newUser); // have to add it to set now since client cannot save it
userManagerSessionBean.updateUserManager(u);
 
// on server:
UserManagerSessionBean updateUserManager (UserManager u) {
  // get the first user (this example assumes there's only one)
  User newUser = (User)u.getUserSet().iterator().next();
  session.saveOrUpdate(u);
  if (!u.getUserSet().contains(newUser)) System.err.println("User set corrupted.");
}
 
This will actually print "User set corrupted." since newUser's hashcode will change due to the saveOrUpdate call.

This is all frustrating because Java's object identity seems to map directly to Hibernate-assigned database identity, but in reality the two are different -- and the latter doesn't even exist until an object is saved. The object's identity shouldn't depend on whether it's been saved yet or not, but if your equals() and hashCode() methods use the Hibernate identity, then the object id does change when you save.

 
It's bothersome to write these methods, can't Hibernate help?
Well, the only "helping" hand Hibernate can provide is hbm2java.

hbm2java does not (anymore) generate equals/hashcode based on id's because of the described issues in this page.

You can though mark certain properties with <meta attribute="use-in-equals">true</meta> to tell hbm2java to generate a proper equals/hashcode.

 
Summary
To sum all this stuff up, here is a listing of what will work or won't work with the different ways to handle equals/hashCode:

 
 no eq/hC at all eq/hC with the id property eq/hC with buisness key
use in a composite-id No Yes Yes
multiple new instances in set Yes No Yes
equal to same object from other session No Yes Yes
collections intact after saving Yes No Yes
 
Where the various problems are as follows:

 
use in a composite-id:

To use an object as a composite-id, it has to implement equals/hashCode in some way, == identity will not be enough in this case.

 
multiple new instances in set:

Will the following work or not:

HashSet someSet = new HashSet();
someSet.add(new PersistentClass());
someSet.add(new PersistentClass());
assert(someSet.size() == 2);
 
equal to same object from another session:

Will the following work or not:

PersistentClass p1 = sessionOne.load(PersistentClass.class, new Integer(1));
PersistentClass p2 = sessionTwo.load(PersistentClass.class, new Integer(1));
assert(p1.equals(p2));
 
collections intact after saving:

Will the following work or not:

HashSet set = new HashSet();
User u = new User();
set.add(u);
session.save(u);
assert(set.contains(u));
 
Any best practicies for equals and hashcode
Read the links in 'Background material' and the API docs - they provide the gory details.

Furthermore I encourage anyone with information and tips about equals and hashcode implementations to come forward and show their "patterns" - I might even try to incorporate them inside hbm2java to make it even more helpful ;)

 
Background material:
Effective Java Programming Language Guide, sample chapter about equals() and hashCode()

Java theory and practice: Hashing it out, Article from IBM

Sam Pullara (BEA) comments on object identity: Blog comment

Article about how to implement equals and hashCode correctly by Manish Hatwalne: Equals and HashCode

Forum thread discussing implementation possibilities without defining a business identity: Equals and hashCode: Is there *any* non-broken approach?

According to The java.lang.Object documentation it should be perfectly ok to always return 0 for the hashCode(). The positive effect of implementing hashCode() to return unique numbers for unique objects, is that it might increase performance. The downside is that the behavior of hashCode() must be consistent with equals(). For object a and b, if a.equals(b) is true, than a.hashCode() == b.hashCode() must be true. But if a.equals(b) returns false, a.hashCode() == b.hashCode() may still be true. Implementing hashCode() as 'return 0' meets these criteria, but it will be extremely inefficient in Hash based collection such as a HashSet or HashMap.



Eric_jiang 2011-07-02 14:06 发表评论
]]>
hibernate ?Criteria 的用介l?/title><link>http://www.tkk7.com/jjshcc/archive/2010/08/16/329046.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 16 Aug 2010 14:43:00 GMT</pubDate><guid>http://www.tkk7.com/jjshcc/archive/2010/08/16/329046.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/329046.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/08/16/329046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/329046.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/329046.html</trackback:ping><description><![CDATA[要对资料库管理系l进行操作,最基本的就是用SQLQStandard Query LanguageQ语句,大部份的资料库都支援标准的SQL语句Q然而也有一些特定于资料库的SQL语句Q应用程式配合SQL语句q行资料库查询时Q若使用到特定于资料库的SQL语句Q程式本w会有相依于特定资料库的问题?br /> <br /> 使用HibernateӞ即(zhn)不了解SQL的用与撰写Q也可以使用它所提供的API来进行SQL语句查询Qorg.hibernate.Criteria对SQLq行装Q?zhn)可以从Java物g的观Ҏ(gu)l合各种查询条gQ由Hibernate自动为?zhn)产生SQL语句Q而不用特别管理SQL与资料库怾的问题?br /> <br /> 以最基本的查询来_如果(zhn)想要查询某个物件所对应的资料表中所有的内容Q?zhn)可以如下q行查询Q?br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> List users = criteria.list();<br /> <br /> for(Iterator it = users.iterator(); it.hasNext(); ) {<br /> User user = (User) it.next();<br /> System.out.println(user.getId() +<br /> " "t " + user.getName() +<br /> "/" + user.getAge());<br /> }<br /> <br /> <br /> Criteria建立后,若不l予M的条Ӟ预设是查询物件所对应表格之所有资料,如果(zhn)执行以上的E式片段Qƈ于设定档中设定了了Hibernate?#8221;show_sql”属性,则可以在L下看C下的SQL语句之生:<br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_<br /> <br /> Criteria基本查询条g讑֮<br /> <br /> org.hibernate.Criteria实际上是个条仉加的容器Q如果想要设定查询条Ӟ则要使用org.hibernate.criterion.Restrictions的各U静态方法传回org.hibernate.criterion.Criteria实例Q传回的每个org.hibernate.criterion.Criteria实例代表着一个条Ӟ(zhn)要使用org.hibernate.Criteria的add()Ҏ(gu)加入q些条g实例Q例如查?#8221;age”大于20且小?0的资料:<br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.add(Restrictions.gt("age", new Integer(20)));<br /> criteria.add(Restrictions.lt("age", new Integer(40)));<br /> List users = criteria.list();<br /> <br /> for(Iterator it = users.iterator(); it.hasNext(); ) {<br /> User user = (User) it.next();<br /> System.out.println(user.getId() +<br /> " "t " + user.getName() +<br /> "/" + user.getAge());<br /> }<br /> <br /> Restrictions的gt()Ҏ(gu)表示大于Qgreat thanQ的条gQ而lt表示于Qless thanQ的条gQ执行以上程式片D,观察所产生的SQL语句Q将使用where与and子句产来完成SQL的条件查询:<br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age>? and this_.age<br /> <br /> 使用add()Ҏ(gu)加入条gӞ预设是用and来组合条Ӟ如果要用or的方式来l合条gQ则可以使用Restrictions.or()Ҏ(gu)Q例如结合age{于QeqQ?0或(orQage为空QisNullQ的条gQ?br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.add(Restrictions.or(<br /> Restrictions.eq("age", new Integer(20)),<br /> Restrictions.isNull("age")<br /> ));<br /> List users = criteria.list();<br /> <br /> 观察所产生的SQL语句Q将使用where与or子句完成SQL的条件查询:<br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=? or this_.age is null)<br /> <br /> (zhn)也可以使用Restrictions.like()Ҏ(gu)来进行SQL中like子句的功能,例如查询”name”中名UCؓ”just”开头的资料Q?br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.add(Restrictions.like("name", "just%"));<br /> List users = criteria.list();<br /> <br /> 观察所产生的SQL语句如下Q?br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name like ?<br /> <br /> Restrictions的几个常用限定查询方法如下表所C:<br /> <br /> Ҏ(gu) 说明<br /> Restrictions.eq {于<br /> Restrictions.allEq 使用MapQ用key/valueq行多个{于的比?br /> Restrictions.gt 大于 ><br /> Restrictions.ge 大于{于 >=<br /> Restrictions.lt 于 <<br /> Restrictions.le 于{于 <=<br /> Restrictions.between 对应SQL的BETWEEN子句<br /> Restrictions.like 对应SQL的LIKE子句<br /> Restrictions.in 对应SQL的in子句<br /> Restrictions.and and关係<br /> Restrictions.or or关係<br /> <br /> Criteriaq阶查询条g讑֮<br /> <br /> 使用Criteriaq行查询Ӟ不仅仅能l合出SQL中where子句的功能,q可以组合出如排序、统计、分l等的查询功能?br /> <br /> 排序<br /> <br /> (zhn)可以用Criteriaq行查询Qƈ使用org.hibernate.criterion.Order对结果进行排序,例如使用Oder.asc()Q指定根?#8221;age”由小到大排序Q反之则使用desc()Q:<br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.addOrder(Order.asc("age"));<br /> List users = criteria.list();<br /> <br /> 注意在加入Order条gӞ使用的是addOrder()Ҏ(gu)Q而不是add()Ҏ(gu)Q在产生SQL语句Ӟ会用order by与ascQdescQ来q行排序指定Q?br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ order by this_.age asc<br /> <br /> 限定查询W数<br /> <br /> Criteria的setMaxResults()Ҏ(gu)可以限定查询回来的笔敎ͼ如果配合setFirstResult()讑֮传回查询l果W一W资料的位置Q就可以实现单的分页Q例如传回第51W之后的50W资料(如果有的话)Q?br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.setFirstResult(51);<br /> criteria.setMaxResults(50);<br /> List users = criteria.list();<br /> <br /> Ҏ(gu)(zhn)所指定得资料库QHibernate自动生与资料库相依的限定W数查询子句Q例如在MySQL中,用limit产生以下的SQL语句Q?br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ limit ?, ?<br /> <br /> l计动作<br /> <br /> (zhn)可以对查询l果q行l计动作Q用org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min()?countDistinct(){方法,再搭配Criteria的setProjection()Ҏ(gu)加入条g讑֮Q例如对查询l果?age"作^均:<br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.setProjection(Projections.avg("age"));<br /> List users = criteria.list();<br /> <br /> 上面的程式将由Hibernate自动产生SQL的avg函数q行q_计算Q?br /> <br /> Hibernate: select avg(this_.age) as y0_ from T_USER this_<br /> <br /> 分组<br /> <br /> q可以配合Projections的groupProperty()来对l果q行分组Q例如以"age"q行分组Q也是如果资料?age"如果?20?0?5?0Q则以下会显C?0?5?0Q?br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.setProjection(Projections.groupProperty("age"));<br /> List users = criteria.list();<br /> <br /> 上面的程式将由Hibernate自动产生SQL的group by子句q行分组计算Q?br /> <br /> Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age<br /> <br /> 如果惛_时结合统计与分组功能Q则可以使用org.hibernate.criterion.ProjectionListQ例如下面的E式会计每个年龄各有多个人:<br /> <br /> ProjectionList projectionList = Projections.projectionList();<br /> projectionList.add(Projections.groupProperty("age"));<br /> projectionList.add(Projections.rowCount());<br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.setProjection(projectionList);<br /> List users = criteria.list();<br /> <br /> 观察所产生的SQL语句Q将使用group by先进行分l,再针Ҏ(gu)个分l进行count函数的计?br /> <br /> Hibernate: select this_.age as y0_, count(*) as y1_ from T_USER this_ group by this_.age<br /> <br /> Ҏ(gu)已知物gq行查询<br /> <br /> 讑֮查询条gq一定要使用RestrictionsQ如果属性条件很多,使用Restrictions也不方便Q如果有一个已知的物gQ则可以Ҏ(gu)q个物g作ؓ查询的依据,看看是否有属性与之类似的物gQ例如:<br /> <br /> User user = new User();<br /> user.setAge(new Integer(30));<br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.add(Example.create(user));<br /> <br /> List users = criteria.list();<br /> <br /> (zhn)可以透过org.hibernate.criterion.Example的create()Ҏ(gu)来徏立Example实例QExample实作了Criteria介面Q因此可以用add()Ҏ(gu)加入至Criteria条g讑֮之中QHibernate自动过滤掉I属性,Ҏ(gu)已知物g上已讑֮的属性,判定是否产生于where子句之中Q?br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=?)<br /> <br /> 讑֮SQL范本<br /> <br /> 如果(zhn)了解如何撰写SQL语句Q想要设定一些Hibernate产生SQL时的范本Q?zhn)也可以用Restrictions的sqlRestriction()Ҏ(gu)Q提供SQL语法范本作限定查询,例如查询name以cater开头的资料Q?br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));<br /> List users = criteria.list();<br /> <br /> 其中alias被替换ZUsercd相关的名Uͼ?被替换为cater%Q也是W二个参数所提供的|sqlRestriction() Ҏ(gu)W一个参数所讑֮的是where子句的部份,所以在SQL撰写Ӟ不必再写whereQ观察所产生的SQL语句Q将使用(zhn)所讑֮的SQL范本作ؓ基础Q来完成SQL的条件查询:<br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name LIKE (?)<br /> <br /> 如果有多个查询条Ӟ例如between子句的查询,则可以如下:<br /> <br /> Criteria criteria = session.createCriteria(User.class);<br /> Integer[] ages = {new Integer(20), new Integer(40)};<br /> Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};<br /> criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));<br /> List users = criteria.list();<br /> <br /> 观察所产生的SQL语句如下Q?br /> <br /> Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age BETWEEN (?) AND (?)<br /> <br /> 使用DetchedCriteria<br /> <br /> Criteria与Sessionl定Q其生命週期跟随着Sessionl束而结束,使用Criteria时进行查询时Q每ơ都要于执行时期动态徏立物Ӟq加入各U查询条Ӟ随着Session的回ӞCriteria也跟着回收?br /> <br /> Z能够重複使用Criteria物gQ在Hibernate 3中新增了org.hibernate.criterion.DetchedCriteriaQ?zhn)可以先徏立DetchedCriteria实例Qƈ加入各种查询条gQƈ于需要查询时再与Sessionl定Q获得一个绑定Session的Criteria物gQ例如:<br /> <br /> // 先徏立DetchedCriteria物g<br /> DetachedCriteria detchedCriteria = DetachedCriteria.forClass(User.class);<br /> // 加入查询条g<br /> detchedCriteria.add(Restrictions.ge("age",new Integer(25)));<br /> <br /> Session session = sessionFactory.openSession();<br /> // l定Sessionq返回一个Criteria实例<br /> Criteria criteria = detchedCriteria.getExecutableCriteria(session);<br /> <br /> List users = criteria.list();<br /> <br /> l论<br /> <br /> Hibernate的Criteria API可以让?zhn)使用物g的方式,l合出查询资料库pȝ的条ӞHibernate会自动依(zhn)所使用的资料库Q动态生SQL语句Q让(zhn)的应用E式在存取资料库Ӟ不致于因撰写了特定的SQL而相依于特定的资料库Q如果?zhn)的开发h员不熟?zhn)SQL语句的撰写,也可以试着使用Criteria来解x询资料库的需求? <img src ="http://www.tkk7.com/jjshcc/aggbug/329046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-08-16 22:43 <a href="http://www.tkk7.com/jjshcc/archive/2010/08/16/329046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate 3.0 多条件查询方?http://www.tkk7.com/jjshcc/archive/2010/08/12/328714.htmlEric_jiangEric_jiangThu, 12 Aug 2010 13:02:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/08/12/328714.htmlhttp://www.tkk7.com/jjshcc/comments/328714.htmlhttp://www.tkk7.com/jjshcc/archive/2010/08/12/328714.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/328714.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/328714.html此方法可多条件查询且可以Ҏ(gu)兌的表条gq行查询
如查询某个商品:
表结构如下:
goods(商品?
goodsid(商品id) goodsname(名称) typeid(分类-外键)  supplierid(供应?外键)

type(分类?
typeid(id主键)   typename(分类名称)

supplier(供应商表)
supplierid(ID主键)   suppliername( 供应商名U?

你可Z个查询条件的c,里面包括你要查询的所有字D?br /> ? public class Query{
    private String suppliername;
    private String goodsname;
    private String typename;
..................
get/setҎ(gu)................
}

得到查询条g后,可以把此cȝ一个对象传入自己做的方法,此方法可以根据条件的个数及是否输入条件进行查询:
public static List query_goods(Query query){
        Session session = SessionFactory.getSession();
        Criteria criteria = session.createCriteria(Goods.class);
        Criteria type = criteria.createCriteria("type");
        Criteria  supplier= criteria.createCriteria("supplier");
    
        if(null!=query.getGoodsname() && !"".equels(query.getGoodsname() ))
            criteria.add(Restrictions.like("goodsname","%"+query.getGoodsname()+"%"));
      
       if(null!=query.getSuppliername() && !"".equels(query.getSuppliername() ))
            supplier.add(Restrictions.like("suppliername","%"+query.getSuppliername()+"%"));

        if(null!=query.getTypename() && !"".equels(query.getTypename() ))
            type.add(Restrictions.like("typename","%"+query.getTypename+"%"));
       
        List list = criteria.list();
       
        session.clear();
        session.close();
        return list;
    }

以上斚wq可多层的嵌套,如type里还有外键,可以按照以上Ҏ(gu)q行嵌套。注意,查询时所有涉及到的数据都一ơ性写入类的属性中Q包括有兌的,x时goods的关联gq加载无效,我觉得这一炚w常的好。呵呵,有什么好处,可以自己好好的想惟?br /> 有许多h曄提到q用ExampleQ就不用自己判断了,如果没有兌条g查询的话Q确实是好,可它的缺点就是不能查询关联中的条件?

 



Eric_jiang 2010-08-12 21:02 发表评论
]]>
Hibernate中Criteria的完整用?http://www.tkk7.com/jjshcc/archive/2010/08/12/328712.htmlEric_jiangEric_jiangThu, 12 Aug 2010 12:51:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/08/12/328712.htmlhttp://www.tkk7.com/jjshcc/comments/328712.htmlhttp://www.tkk7.com/jjshcc/archive/2010/08/12/328712.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/328712.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/328712.htmlq在目中?Spring ?Hibernate q行开发,有感?Criteria 比较好用Q在查询Ҏ(gu)

设计上可以灵zȝҎ(gu) Criteria 的特Ҏ(gu)方便地进行查询条件的l装。现在对 Hibernate的Criteria 的用法进行ȝQ?br />         Hibernate 设计?CriteriaSpecification 作ؓ Criteria 的父接口Q下面提供了 Criteria和DetachedCriteria ?
        Criteria ?DetachedCriteria 的主要区别在于创建的形式不一P Criteria 是在U的Q所以它是由 Hibernate Session q行创徏的;?DetachedCriteria 是离U的Q创建时无需 SessionQDetachedCriteria 提供?2 个静态方?forClass(Class) ?forEntityName(Name) q行DetachedCriteria 实例的创建?Spring 的框架提供了getHibernateTemplate().findByCriteria(detachedCriteria) Ҏ(gu)可以很方便地Ҏ(gu)DetachedCriteria 来返回查询结
果?
        Criteria ?DetachedCriteria 均可使用 Criterion ?Projection 讄查询条g。可以设|?FetchMode( 联合查询抓取的模?) Q设|排序方式。对?Criteria q可以设|?FlushModel Q冲?Session 的方式)?LockMode Q数据库锁模式)?
下面?Criterion ?Projection q行详细说明?br />          Criterion ?Criteria 的查询条件。Criteria 提供?add(Criterion criterion) Ҏ(gu)来添加查询条件?br />          Criterion 接口的主要实现包括: Example ?Junction ?SimpleExpression 。?Junction 的实际用是它的两个子类 conjunction ?disjunction Q分别是使用 AND ?OR 操作W进行来联结查询条g集合?br />          Criterion 的实例可以通过 Restrictions 工具cL创徏QRestrictions 提供了大量的静态方法,?eq Q等于)?ge Q大于等于)?between {来Ҏ(gu)的创?Criterion 查询条g QSimpleExpression 实例Q。除此之外, Restrictions q提供了Ҏ(gu)来创?conjunction ?disjunction 实例Q通过往该实例的 add(Criteria) Ҏ(gu)来增加查询条件Ş成一个查询条仉合?br />          至于 Example 的创建有所不同Q?Example 本n提供了一个静态方?create(Object entity) Q即Ҏ(gu)一个对象(实际使用中一般是映射到数据库的对象)来创建。然后可以设|一些过滤条Ӟ
Example exampleUser =Example.create(u)
.ignoreCase() // 忽略大小?
.enableLike(MatchMode.ANYWHERE);
/ / ?String cd的属性,无论在那里值在那里都匹配。相当于 %value%
Project 主要是让 Criteria 能够q行报表查询Qƈ可以实现分组?Project 主要?SimpleProjection ?ProjectionList ?Property 三个实现。其?SimpleProjection ?
ProjectionList 的实例化是由内徏?Projections 来完成,如提供的 avg ?count ?max ?min ?sum 可以让开发者很Ҏ(gu)Ҏ(gu)个字D进行统计查询?
        Property 是对某个字段q行查询条g的设|,如通过Porperty.forName(“color”).in (new String[]{“black”,”red”,”write”}); 则可以创Z?Project 实例。通过
criteria ?add(Project) Ҏ(gu)加入到查询条件中厅R?
       使用 Criteria q行查询Q主要要清晰的是 Hibernate 提供了那些类和方法来满开发中查询条g的创建和l装Q下面介l几U用法:
1. 创徏一个Criteria 实例
org.hibernate.Criteria接口表示特定持久cȝ一个查询。Session?Criteria实例的工厂?br /> Criteria crit = sess.createCriteria(Cat.class);
crit.setMaxResults(50);
List cats = crit.list();

2. 限制l果集内?br /> 一个单独的查询条g是org.hibernate.criterion.Criterion 接口的一个实例?/p>

org.hibernate.criterion.Restrictionsc?定义了获得某些内|Criterioncd的工厂方法?br /> List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .add( Restrictions.between("weight", minWeight, maxWeight) )
    .list();

U束可以按逻辑分组?

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .add( Restrictions.or(
        Restrictions.eq( "age", new Integer(0) ),
        Restrictions.isNull("age")
    ) )
    .list();

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
    .add( Restrictions.disjunction()
        .add( Restrictions.isNull("age") )
        .add( Restrictions.eq("age", new Integer(0) ) )
        .add( Restrictions.eq("age", new Integer(1) ) )
        .add( Restrictions.eq("age", new Integer(2) ) )
    ) )
    .list();

Hibernate提供了相当多的内|criterioncd(Restrictions 子类), 但是其有用的是可以允许

你直接用SQL?/p>

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%",

Hibernate.STRING) )
    .list();

{alias}占位W应当被替换查询实体的列别名?
Property实例是获得一个条件的另外一U途径。你可以通过调用Property.forName() 创徏一?/p>

Property?

Property age = Property.forName("age");
List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.disjunction()
        .add( age.isNull() )
        .add( age.eq( new Integer(0) ) )
        .add( age.eq( new Integer(1) ) )
        .add( age.eq( new Integer(2) ) )
    ) )
    .add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )
    .list();

3. l果集排?br /> 你可以用org.hibernate.criterion.Order来ؓ查询l果排序?

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "F%")
    .addOrder( Order.asc("name") )
    .addOrder( Order.desc("age") )
    .setMaxResults(50)
    .list();

List cats = sess.createCriteria(Cat.class)
    .add( Property.forName("name").like("F%") )
    .addOrder( Property.forName("name").asc() )
    .addOrder( Property.forName("age").desc() )
    .setMaxResults(50)
    .list();

4. 兌
你可以用createCriteria()非常Ҏ(gu)的在互相兌的实体间建立 U束?/p>

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "F%")
    .createCriteria("kittens")
        .add( Restrictions.like("name", "F%")
    .list();


注意W二?createCriteria()q回一个新?Criteria实例Q该实例引用kittens 集合中的元素?
接下来,替换形态在某些情况下也是很有用的?/p>

List cats = sess.createCriteria(Cat.class)
    .createAlias("kittens", "kt")
    .createAlias("mate", "mt")
    .add( Restrictions.eqProperty("kt.name", "mt.name") )
    .list();


(createAlias()q不创徏一个新?Criteria实例?
Cat实例所保存的之前两ơ查询所q回的kittens集合?没有被条仉qo的。如果你希望只获?/p>

W合条g的kittensQ?你必M用returnMaps()?

List cats = sess.createCriteria(Cat.class)
    .createCriteria("kittens", "kt")
    .add( Restrictions.eq("name", "F%") )
    .returnMaps()
    .list();
Iterator iter = cats.iterator();
while ( iter.hasNext() ) {
    Map map = (Map) iter.next();
    Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
    Cat kitten = (Cat) map.get("kt");
}

5. 动态关联抓?br /> 你可以用setFetchMode()在运行时定义动态关联抓取的语义?

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .setFetchMode("mate", FetchMode.EAGER)
    .setFetchMode("kittens", FetchMode.EAGER)
    .list();

q个查询可以通过外连接抓取mate和kittens?/p>

6. 查询CZ
org.hibernate.criterion.Examplecd怽通过一个给定实?构徏一个条件查询?/p>

Cat cat = new Cat();
cat.setSex('F');
cat.setColor(Color.BLACK);
List results = session.createCriteria(Cat.class)
    .add( Example.create(cat) )
    .list();


版本属性、标识符和关联被忽略。默认情况下gؓnull的属性将被排除?
可以自行调整Example使之更实用?

Example example = Example.create(cat)
    .excludeZeroes()           //exclude zero valued properties
    .excludeProperty("color") //exclude the property named "color"
    .ignoreCase()              //perform case insensitive string comparisons
    .enableLike();             //use like for string comparisons
List results = session.createCriteria(Cat.class)
    .add(example)
    .list();


甚至可以使用examples在关联对象上攄条g?/p>

List results = session.createCriteria(Cat.class)
    .add( Example.create(cat) )
    .createCriteria("mate")
        .add( Example.create( cat.getMate() ) )
    .list();


7. 投媄(Projections)、聚合(aggregationQ和分组QgroupingQ?br /> org.hibernate.criterion.Projections?Projection 的实例工厂。我们通过调用

setProjection()应用投媄C个查询?

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.rowCount() )
    .add( Restrictions.eq("color", Color.BLACK) )
    .list();

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount() )
        .add( Projections.avg("weight") )
        .add( Projections.max("weight") )
        .add( Projections.groupProperty("color") )
    )
    .list();


在一个条件查询中没有必要昑ּ的?"group by" 。某些投q型就是被定义?分组投媄Q他

们也出现在SQL的group by子句中?

可以选择把一个别名指z一个投影,q样可以使投影DU束或排序所引用。下面是两种不同?/p>

实现方式Q?/p>

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
    .addOrder( Order.asc("colr") )
    .list();

 

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.groupProperty("color").as("colr") )
    .addOrder( Order.asc("colr") )
    .list();

alias()和as()Ҏ(gu)便的一个投影实例包装到另外一?别名的Projection实例中。简而言之,

当你d一个投影到一个投影列表中?你可以ؓ它指定一个别名:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount(), "catCountByColor" )
        .add( Projections.avg("weight"), "avgWeight" )
        .add( Projections.max("weight"), "maxWeight" )
        .add( Projections.groupProperty("color"), "color" )
    )
    .addOrder( Order.desc("catCountByColor") )
    .addOrder( Order.desc("avgWeight") )
    .list();


List results = session.createCriteria(Domestic.class, "cat")
    .createAlias("kittens", "kit")
    .setProjection( Projections.projectionList()
        .add( Projections.property("cat.name"), "catName" )
        .add( Projections.property("kit.name"), "kitName" )
    )
    .addOrder( Order.asc("catName") )
    .addOrder( Order.asc("kitName") )
    .list();


也可以用Property.forName()来表C投影:

List results = session.createCriteria(Cat.class)
    .setProjection( Property.forName("name") )
    .add( Property.forName("color").eq(Color.BLACK) )
    .list();
List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount().as("catCountByColor") )
        .add( Property.forName("weight").avg().as("avgWeight") )
        .add( Property.forName("weight").max().as("maxWeight") )
        .add( Property.forName("color").group().as("color" )
    )
    .addOrder( Order.desc("catCountByColor") )
    .addOrder( Order.desc("avgWeight") )
    .list();


8. ȝ(detached)查询和子查询
DetachedCriteriacM你在一个session范围之外创徏一个查询,q且可以使用L?Session?/p>

执行它?/p>

DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
    .add( Property.forName("sex").eq('F') );
//创徏一个Session
Session session = .;
Transaction txn = session.beginTransaction();
List results = query.getExecutableCriteria(session).setMaxResults(100).list();
txn.commit();
session.close();


DetachedCriteria也可以用以表C子查询。条件实例包含子查询可以通过 Subqueries或?br /> Property获得?/p>

DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)
    .setProjection( Property.forName("weight").avg() );
session.createCriteria(Cat.class)
    .add( Property.forName("weight).gt(avgWeight) )
    .list();
DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)
    .setProjection( Property.forName("weight") );
session.createCriteria(Cat.class)
    .add( Subqueries.geAll("weight", weights) )
    .list();

怺兌的子查询也是有可能的Q?/p>

DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")
    .setProjection( Property.forName("weight").avg() )
    .add( Property.forName("cat2.sex").eqProperty("cat.sex") );
session.createCriteria(Cat.class, "cat")
    .add( Property.forName("weight).gt(avgWeightForSex) )
    .list();

 



Eric_jiang 2010-08-12 20:51 发表评论
]]>
Hibernate 对象 三种状?瞬时?持久?q?以及 save update saveOrUpdate merge{的使用http://www.tkk7.com/jjshcc/archive/2010/08/10/328454.htmlEric_jiangEric_jiangTue, 10 Aug 2010 15:39:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/08/10/328454.htmlhttp://www.tkk7.com/jjshcc/comments/328454.htmlhttp://www.tkk7.com/jjshcc/archive/2010/08/10/328454.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/328454.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/328454.html
    *  瞬时?br />
    由new命o开辟内存空间的java对象Q?br />
    eg. Person person = new Person("amigo", "?);

    如果没有变量对该对象q行引用Q它?yu)被java虚拟机回收?br />
     瞬时对象在内存孤立存在,它是携带信息的蝲体,不和数据库的数据有Q何关联关p,在Hibernate中,可通过session的save()?saveOrUpdate()Ҏ(gu)瞬时对象与数据库相兌Qƈ数据对应的插入数据库中Q此时该瞬时对象转变?span style="color: red;">持久化对?/span>?br />
    * 持久?br />
    处于该状态的对象在数据库中具有对应的记录Qƈ拥有一个持久化标识。如果是用hibernate的delete()Ҏ(gu)Q对应的持久对象变?span style="color: red;">瞬时对象Q因数据库中的对应数据已被删除,该对象不再与数据库的记录兌?br />     当一个session执行close()或clear()、evict()之后Q持久对象变?span style="color: red;">q对象Q此时持久对象会变成q对象Q此时该对象虽然h数据库识别|但它已不在HIbernate持久层的理之下?br />
    持久对象h如下特点Q?br />
    1. 和session实例兌Q?br />     2. 在数据库中有与之兌的记?/span>?br />
    * q?br />
    当与某持久对象关联的session被关闭后Q该持久对象转变对象。当q对象被重新关联到session上时Qƈ再次转变成持久对象?br />     q对象拥有数据库的识别|可通过update()、saveOrUpdate(){方法,转变?span style="color: red;">持久对象
?br />
    q对象h如下特点Q?br />
    1. 本质上与瞬时对象相同Q在没有M变量引用它时QJVM会在适当的时候将它回?/span>Q?br />     2. 比瞬时对象多了一个数据库记录标识?/span>?br />
 

    瞬?Transient)Q也叫(f)时态。处于这U状态的对象具备的特征如下:                          
                                                
        不在Session的缓存中Q不与Q何的Session实例相关联?nbsp;                                    
                                                
        在数据库中没有与之相对应的记录?nbsp;                                                       
                                                
    持久?Persistent)Q处于这U状态的对象具备的特征如下:                                   
                                                
        在Session的缓存中Q与Session实例相关联?nbsp;                                              
                                                
        在数据库中存在与之相对应的记录?nbsp;                                                       
                                                
    q?Detached)Q也叫游L。处于这U状态的对象具备的特征如下:                         
                                                
        不在Session的缓存中Q不与Q何的Session实例相关联?nbsp;                                    
                                            
        在数据库中存在与之相对应的记录?前提条g是没有其他Session实例删除该条记录)?nbsp;          
                                        
一、预备知?br /> 对于hibernateQ它的对象有三种状态,transient、persistent、detached
下边是常见的译办法Q?br /> transientQ瞬态或者自由?br />     (new DeptPo(1,”行政?#8221;,20,”行政相关”)Q该po的实例和session没有兌Q该po的实例处于transient)
persistentQ持久化状?br />     (和数据库中记录想影射的Po实例Q它的状态是persistent, 通过get和load{得到的对象都是persistent)
detachedQ脱状态或者游L?br />     (1)当通过get或loadҎ(gu)得到的po对象它们都处于persistent,但如果执行delete(po)?但不能执行事?,该po状态就处于detached, (表示和sessionq兌),因delete而变成游L可以通过save或saveOrUpdate()变成持久?br />     (2)当把session关闭Ӟsession~存中的persistent的po对象也变成detached

因关闭session而变成游L的可以通过lock、save、update变成持久?br /> 持久态实例可以通过调用 delete()变成q状态?br /> 通过get()或load()Ҏ(gu)得到的实例都是持久化状态的?br /> q状态的实例可以通过调用lock()或者replicate()q行持久化?br /> save()和persist()会引发SQL的INSERTQdelete()会引发SQLDELETEQ?br /> 而update()或merge()会引发SQL UPDATE。对持久化(persistentQ实例的修改在刷新提交的时候会被检到Q它也会引vSQL UPDATE?br /> saveOrUpdate()或者replicate()会引发SQL INSERT或者UPDATE

二、save 和update区别
    把这一Ҏ(gu)在第一位的原因是因一Ҏ(gu)最常用的?br />     save的作用是把一个新的对象保?br />     update是把一个脱状态的对象或自由态对象(一定要和一个记录对应)更新到数据库
三、update 和saveOrUpdate区别
    q个是比较好理解的,֐思义QsaveOrUpdate基本上就是合成了save和update,而update只是update;引用hibernate reference中的一D话来解释他们的使用场合和区?br />     通常下面的场景会使用update()或saveOrUpdate()Q?br />     E序在第一个session中加载对?接着把session关闭
    该对象被传递到表现?br />     对象发生了一些改?br />     该对象被q回C务逻辑层最l到持久?br />     E序创徏W二session调用W二个session的update()Ҏ(gu)持久q些改动
    saveOrUpdate(po)做下面的?
    如果该po对象已经在本session中持久化了,在本session中执行saveOrUpdate不做M?br />     如果savaOrUpdate(新po)与另一个与本session兌的po对象拥有相同的持久化标识(identifier)Q抛Z个异?br />     org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.itfuture.www.po.Xtyhb#5]
    saveOrUpdate如果对象没有持久化标?identifier)属性,对其调用save() Q否则update() q个对象
四、persist和save区别
    q个是最qL(fng)的一对,表面上看h使用哪个都行Q在hibernate reference文档中也没有明确的区分他?
    q里l出一个明的区分。(可以跟进src看一下,虽然实现步骤cMQ但是还是有l微的差别)
    主要内容区别Q?br />     1Qpersist把一个瞬态的实例持久化,但是q?不保?标识W?identifier主键对应的属?被立d入到持久化实例中Q标识符的填入可能被推迟到flush的时候?br />     2Qsave, 把一个瞬态的实例持久化标识符Q及时的产生,它要q回标识W,所以它会立x行Sql insert
五、saveOrUpdate,merge和update区别
    比较update和merge
    update的作用上边说了,q里说一下merge?br />     如果session中存在相同持久化标识(identifier)的实例,用用L(fng)出的对象覆盖session已有的持久实?br />     (1)当我们用update的时候,执行完成后,会抛出异?br />     (2)但当我们使用merge的时候,把处理自由态的po对象A的属性copy到session当中处于持久态的po的属性中Q执行完成后原来是持久状态还是持久态,而我们提供的Aq是自由?br /> 六、flush和update区别
    q两个的区别好理?br />     update操作的是在自由态或q状?因session的关闭而处于脱状?的对?/updateSQL
    而flush是操作的在持久状态的对象?br />     默认情况下,一个持久状态的对象的改动(包含set容器Q是不需要update的,只要你更改了对象的|{待hibernate flushp动更新或保存到数据库了。hibernate flush发生在以下几U情况中Q?br />     1Q?调用某些查询的和手动flush(),session的关闭、SessionFactory关闭l合
    get()一个对象,把对象的属性进行改?把资源关闭?br />     2Qtransaction commit的时候(包含了flushQ?br /> 七、lock和update区别
    update是把一个已l更改过的脱状态的对象变成持久状?br />     lock是把一个没有更改过的脱状态的对象变成持久状?针对的是因Session的关闭而处于脱状态的po对象(2)Q不能针对因delete而处于脱状态的po对象)
    对应更改一个记录的内容Q两个的操作不同Q?br />     update的操作步骤是Q?br />     (1)属性改动后的脱的对象的修?>调用update
    lock的操作步骤是Q?br />     (2)调用lock把未修改的对象从q状态变成持久状?->更改持久状态的对象的内?->{待f(xi)lush或者手动flush
八、clear和evcit的区?br />     clear完整的清除session~存
    evcit(obj)把某个持久化对象从session的缓存中清空?nbsp;                                                                            



Eric_jiang 2010-08-10 23:39 发表评论
]]>
解决hibernate 删除异常Qdeleted object would be re-saved by cascade (remove deleted object fromhttp://www.tkk7.com/jjshcc/archive/2010/07/31/327664.htmlEric_jiangEric_jiangSat, 31 Jul 2010 12:58:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/07/31/327664.htmlhttp://www.tkk7.com/jjshcc/comments/327664.htmlhttp://www.tkk7.com/jjshcc/archive/2010/07/31/327664.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/327664.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/327664.html

我遇到到是第三种

解决hibernate 删除异常Q?deleted object would be re-saved by cascade (remove deleted object from associations) 收藏
在hibernate 删除兌时会出现eleted object would be re-saved by cascade (remove deleted object from associations)的异常,l合别h的和自己的经验通常有三U解决的Ҏ(gu)Q?/font>

Ҏ(gu)1 删除Set方的cascadeQ?br /> Ҏ(gu)2 解决兌关系后,再删?/font>

    onside.getManys().remove(thisMany);   //在所兌的一方的set中移走当前要删除的对?br />     thisMany.setOne(null);                          //讄所对应的一方ؓI,解除它们之间的关p?br />     manyDao.delete(thisMany);
Ҏ(gu)3 在many-to-one方增加cascade 但g能是none



Eric_jiang 2010-07-31 20:58 发表评论
]]>
解决could not initialize proxy - the owning Session was closed的方?/title><link>http://www.tkk7.com/jjshcc/archive/2010/06/23/324285.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Wed, 23 Jun 2010 15:23:00 GMT</pubDate><guid>http://www.tkk7.com/jjshcc/archive/2010/06/23/324285.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/324285.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/06/23/324285.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/324285.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/324285.html</trackback:ping><description><![CDATA[<p><font>其实q个异常写的非常之清楚,是会话关闭Q无法对Hibernate实体q行操作。造成q样的情冉|很多Q什么书写错误啊Q逻辑错误 ?{等.不过,偶是因ؓLAZY.</font></p> <p><font style="background-color: #ffffff;" color="#339966">? 于lazy机制Q?/font></p> <p><font color="#0000ff">延迟初始化错误是q用Hibernate开发项目时最常见的错误。如果对一个类或者集合配|了延迟 索策略,那么必须当代理类实例或代理集合处于持久化状态(卛_于Session范围内)Ӟ才能初始化它。如果在游离状态时才初始化它,׃产生延迟初始 化错误?/font></p> <p><font>下面把Customer.hbm.xml文g?lt;class>元素的lazy属性设为trueQ表CZ用gq检索策略:</font></p> <p><font><class name="mypack.Customer" table="CUSTOMERS" lazy="true"></font></p> <p><font>当执行Session的load()Ҏ(gu)ӞHibernate不会立即执行查询CUSTOMERS表的select语句Q仅仅返? Customercȝ代理cȝ实例Q这个代理类L(fng)以下特征Q?/font></p> <p><font>Q?Q? 由Hibernate在运行时动态生成,它扩展了Customerc,因此它承了Customercȝ所有属性和Ҏ(gu)Q但它的实现对于应用E序是透明 的?br /> Q?Q? 当Hibernate创徏Customer代理cd例时Q仅仅初始化了它的OID属性,其他属性都为nullQ因此这个代理类实例占用的内存很?br /> Q?Q当应用E序W一ơ访问Customer代理cd例时Q例如调用customer.getXXX()或customer.setXXX()Ҏ(gu)Q, Hibernate会初始化代理cd例,在初始化q程中执行select语句Q真正从数据库中加蝲Customer对象的所有数据。但有个例外Q那是? 应用E序讉KCustomer代理cd例的getId()Ҏ(gu)ӞHibernate不会初始化代理类实例Q因为在创徏代理cd例时OID存在了Q不? 到数据库中去查询?/font></p> <p><font>提示QHibernate采用CGLIB工具来生成持久化cȝ代理cRCGLIB是一个功能强大的Java字节码生成工P它能够在E? 序运行时动态生成扩? JavacL者实现Java接口的代理类。关于CGLIB的更多知识,请参考:</font></p> <p><font>http://cglib.sourceforge.net/?/font></p> <p><font>以下代码先通过Session的load()Ҏ(gu)加蝲Customer对象Q然后访问它的name属性: </font></p> <p><font>tx = session.beginTransaction();<br /> Customer customer=(Customer)session.load(Customer.class,new Long(1));<br /> customer.getName();<br /> tx.commit();</font></p> <p><font>在运行session.load()Ҏ(gu)时Hibernate不执行Q何select语句Q仅仅返回Customercȝ代理cȝ? 例,它的OID?Q这是由load()Ҏ(gu)的第二个参数指定的。当应用E序调用customer.getName()Ҏ(gu)ӞHibernate会初? 化Customer代理cd例,从数据库中加载Customer对象的数据,执行以下select语句Q?/font></p> <p><font>select * from CUSTOMERS where ID=1;<br /> select * from ORDERS where CUSTOMER_ID=1;</font></p> <p><font>?lt;class>元素的lazy属性ؓtrueQ会影响Session的load()Ҏ(gu)的各U运行时行ؓQ下面D例说 明?/font></p> <p><font>1Q如果加载的Customer对象在数据库中不存在QSession的load()Ҏ(gu)不会抛出异常Q只有当q行 customer.getName()Ҏ(gu)时才会抛Z下异常:</font></p> <p><font>ERROR LazyInitializer:63 - Exception initializing proxy<br /> net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class: <br /> mypack.Customer</font></p> <p><font>2Q如果在整个Session范围内,应用E序没有讉KqCustomer对象Q那么Customer代理cȝ实例一直不会被初始 化,Hibernate不会执行Mselect语句。以下代码试囑֜关闭Session后访问Customer游离对象Q?/font></p> <p><font>tx = session.beginTransaction();<br /> Customer customer=(Customer)session.load(Customer.class,new Long(1));<br /> tx.commit();<br /> session.close();<br /> customer.getName();</font></p> <p><font>׃引用变量customer引用的Customer代理cȝ实例在Session范围内始l没有被初始化,因此在执? customer.getName()Ҏ(gu)ӞHibernate会抛Z下异常:</font></p> <p><font>ERROR LazyInitializer:63 - Exception initializing proxy<br /> net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed</font></p> <p><font>由此可见QCustomer代理cȝ实例只有在当前Session范围内才能被初始化?/font></p> <p><font>3Qnet.sf.hibernate.Hibernatecȝinitialize()静态方法用于在Session范围内显式初? 化代理类实例QisInitialized()Ҏ(gu)用于判断代理cd例是否已l被初始化。例如:</font></p> <p><font>tx = session.beginTransaction();<br /> Customer customer=(Customer)session.load(Customer.class,new Long(1));<br /> if(!Hibernate.isInitialized(customer)) <br /> Hibernate.initialize(customer);<br /> tx.commit();<br /> session.close();<br /> customer.getName();</font></p> <p><font>以上代码在Session范围内通过Hibernatecȝinitialize()Ҏ(gu)昑ּ初始化了Customer代理cd例,? 此当Session关闭后,可以正常讉KCustomer游离对象?/font></p> <p><font>4Q当应用E序讉K代理cd例的getId()Ҏ(gu)Ӟ不会触发Hibernate初始化代理类实例的行为,例如Q?/font></p> <p><font>tx = session.beginTransaction();<br /> Customer customer=(Customer)session.load(Customer.class,new Long(1));<br /> customer.getId();<br /> tx.commit();<br /> session.close();<br /> customer.getName();</font></p> <p><font>当应用程序访问customer.getId()Ҏ(gu)Ӟ该方法直接返回Customer代理cd例的OID|无需查询数据库。由? 引用变量 customer始终引用的是没有被初始化的Customer代理cd例,因此当Session关闭后再执行customer.getName()Ҏ(gu)Q? Hibernate会抛Z下异常:</font></p> <p><font>ERROR LazyInitializer:63 - Exception initializing proxy<br /> net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed</font></p> <font> <p><br /> 解决Ҏ(gu)Q?/p> <p>׃hibernate采用了lazy=true,q样当你用hibernate查询?q回实际为利用cglib增强的代理类,但其q没有实际填 ?当你在前?利用它来取?getXXX)?q时Hibernate才会到数据库执行查询,q填充对?但此时如果和q个代理cȝ关的 session已关闭掉,׃产生U错?<br /> 在做一对多Ӟ有时会出?could not initialize proxy - clothe owning Session was sed,q个好像是hibernate的缓存问?问题解决:需要在<many-to-one>里设|lazy="false". 但有可能会引发另一个异常叫</p> <p>failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed</p> <p>此异常解x案请察看本h博客Qhttp://hi.baidu.com/kekemao1Q的Hibernate异常中的《failed to lazily initialize a collection of role异常?/p> <p>?<br /> 解决Ҏ(gu):在web.xml中加?br /> <filter><br />     <filter-name>hibernateFilter</filter-name><br />     <filter-class><br />      org.springframework.orm.hibernate3.support.OpenSessionInViewFilter<br />     </filter-class><br /> </filter<br /> <filter-mapping><br />     <filter-name>hibernateFilter</filter-name><br />     <url-pattern>*.do</url-pattern><br /> </filter-mapping><br /> 可以了;</p> <p>参考了:<br /> Hibernate与gq加载:</p> <p>Hibernate对象关系映射提供延迟的与非gq的对象初始化。非延迟加蝲在读取一个对象的时候会与q个对象所有相关的其他对象一赯取出来? q有时会D成百的(如果不是成千的话Qselect语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,l常会导致整个数据库都在初始? 的阶D被d来了。当Ӟ你可以不厌其烦地查每一个对象与其他对象的关p,q把那些最昂贵的删除,但是到最后,我们可能会因此失M本想在ORM工具? 获得的便利?/p> <p><br /> 一个明昄解决Ҏ(gu)是用Hibernate提供的gq加载机制。这U初始化{略只在一个对象调用它的一对多或多对多关系时才关pd象读取出来。这个过 E对开发者来说是透明的,而且只进行了很少的数据库操作hQ因此会得到比较明显的性能提升。这Ҏ(gu)术的一个缺h延迟加蝲技术要求一? Hibernate会话要在对象使用的时候一直开着。这会成为通过使用DAO模式持久层抽象出来时的一个主要问题。ؓ了将持久化机制完全地抽象出来Q所 有的数据库逻辑Q包括打开或关闭会话,都不能在应用层出现。最常见的是Q一些实C单接口的DAO实现cd数据库逻辑完全装h了。一U快速但是笨? 的解x法是攑ּDAO模式Q将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效,但是在大的系l中Q这是一个严重的设计~陷Q妨了pȝ? 可扩展性?/p> <p>在Web层进行gq加?/p> <p>q运的是QSpring框架为Hibernate延迟加蝲与DAO模式的整合提供了一U方便的解决Ҏ(gu)。对那些不熟(zhn)Spring? Hibernate集成使用的hQ我不会在这里讨多的l节Q但是我你去了解Hibernate与Spring集成的数据访问。以一个Web应用? 例,Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我们可以随意选择 一个类来实现相同的功能。两U方法唯一的不同就在于interceptor在Spring容器中运行ƈ被配|在web应用的上下文中,而Filter? Spring之前q行q被配置在web.xml中。不用哪个Q他们都在请求将当前会话与当前(数据库)U程l定时打开Hibernate会话。一旦已l? 定到U程Q这个打开了的Hibernate会话可以在DAO实现cM透明C用。这个会话会为gq加载数据库中值对象的视图保持打开状态。一旦这个逻辑? 囑֮成了QHibernate会话会在Filter的doFilterҎ(gu)或者Interceptor的postHandleҎ(gu)中被关闭。下面是每个l? 件的配置CZQ?/p> <p> </p> <p>Interceptor的配|?</p> <p><br /> <beans> <br /> <bean id="urlMapping" <br /> class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <br /> <property name="interceptors"> <br /> <list> <br /> <ref bean="openSessionInViewInterceptor"/> <br /> </list> <br /> </property> <br /> <property name="mappings"> </p> <p></bean> </p> <p><bean name="openSessionInViewInterceptor" <br /> class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor"> <br /> <property name="sessionFactory"><ref bean="sessionFactory"/></property> <br /> </bean> <br /> </beans> </p> <p>Filter的配|?/p> <p><br /> <web-app> </p> <p><filter> <br /> <filter-name>hibernateFilter</filter-name> <br /> <filter-class> <br /> org.springframework.orm.hibernate.support.OpenSessionInViewFilter <br /> </filter-class> <br /> </filter> </p> <p><filter-mapping> <br /> <filter-name>hibernateFilter</filter-name> <br /> <url-pattern>*. spring </url-pattern> <br /> </filter-mapping> </p> <p></web-app> </p> <p><br /> 实现Hibernate的Dao接口来用打开的会话是很容易的。事实上Q如果你已经使用了Spring框架来实C的Hibernate Dao,很可能你不需要改变Q何东ѝ方便的HibernateTemplate公用lg使访问数据库变成菜一,而DAO接口只有通过q个lg才可? 讉K到数据库。下面是一个示例的DAOQ?/p> <p><br /> public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO { </p> <p>public Product getProduct(Integer productId) { <br /> return (Product)getHibernateTemplate().load(Product.class, productId); <br /> } </p> <p>public Integer saveProduct(Product product) { <br /> return (Integer) getHibernateTemplate().save(product); <br /> } </p> <p>public void updateProduct(Product product) { <br /> getHibernateTemplate().update(product); <br /> } <br /> } </p> <p><br /> 在业务逻辑层中使用延迟加蝲</p> <p>即在视囑֤面,Spring框架也通过使用AOP 拦截? HibernateInterceptor来得gq加载变得很Ҏ(gu)实现。这个Hibernate 拦截器透明地将调用配置在Spring应用E序上下文中的业务对象中Ҏ(gu)的请求拦截下来,在调用方法之前打开一个Hibernate会话Q然后在Ҏ(gu)执行 完之后将会话关闭。让我们来看一个简单的例子Q假设我们有一个接口BussinessObjectQ?/p> <p><br /> public     interface    BusinessObject     { <br /> public     void    doSomethingThatInvolvesDaos(); <br /> } <br /> cBusinessObjectImpl实现了BusinessObject接口:</p> <p>public     class    BusinessObjectImpl    implements    BusinessObject     { <br /> public     void    doSomethingThatInvolvesDaos()     { <br /> //    lots of logic that calls <br /> //    DAO classes Which access <br /> //    data objects lazily  <br /> }  <br /> }  </p> <p> </p> <p>通过在Spring应用E序上下文中的一些配|,我们可以让将调用BusinessObject的方法拦截下来,再o它的Ҏ(gu)支持延迟加蝲。看看下 面的一个程序片D:</p> <p> </p> <p><beans> <br /> <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor"> <br /> <property name="sessionFactory"> <br /> <ref bean="sessionFactory"/> <br /> </property> <br /> </bean> <br /> <bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl"> <br /> <property name="someDAO"><ref bean="someDAO"/></property> <br /> </bean> <br /> <bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean"> <br /> <property name="target"><ref bean="businessObjectTarget"/></property> <br /> <property name="proxyInterfaces"> <br /> <value>com.acompany.BusinessObject</value> <br /> </property> <br /> <property name="interceptorNames"> <br /> <list> <br /> <value>hibernateInterceptor</value> <br /> </list> <br /> </property> <br /> </bean> <br /> </beans></p> <p>当businessObject被调用的时候,HibernateInterceptor打开一个Hibernate会话Qƈ调用请求传递给 BusinessObjectImpl对象。当BusinessObjectImpl执行完成后,HibernateInterceptor透明地关闭了 会话。应用层的代码不用了解Q何持久层逻辑Q还是实C延迟加蝲?/p> <p><br /> 在单元测试中试延迟加蝲</p> <p>最后,我们需要用J-Unit来测试我们的延迟加蝲E序。我们可以轻易地通过重写TestCasecM的setUp和tearDownҎ(gu)来实现这 个要求。我比较喜欢用这个方便的抽象cM为我所有测试类的基cR?/p> <p><br /> public abstract class MyLazyTestCase extends TestCase { </p> <p>private SessionFactory sessionFactory; <br /> private Session session; </p> <p>public void setUp() throws Exception { <br /> super.setUp(); <br /> SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory"); <br /> session = SessionFactoryUtils.getSession(sessionFactory, true); <br /> Session s = sessionFactory.openSession(); <br /> TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s)); </p> <p>} </p> <p>protected Object getBean(String beanName) { <br /> //Code to get objects from Spring application context <br /> } </p> <p>public void tearDown() throws Exception { <br /> super.tearDown(); <br /> SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); <br /> Session s = holder.getSession(); <br /> s.flush(); <br /> TransactionSynchronizationManager.unbindResource(sessionFactory); <br /> SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory); <br /> } </p> </font> <img src ="http://www.tkk7.com/jjshcc/aggbug/324285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-06-23 23:23 <a href="http://www.tkk7.com/jjshcc/archive/2010/06/23/324285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于An association from the table refers to an unmapped classhttp://www.tkk7.com/jjshcc/archive/2010/05/12/320705.htmlEric_jiangEric_jiangWed, 12 May 2010 07:24:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/05/12/320705.htmlhttp://www.tkk7.com/jjshcc/comments/320705.htmlhttp://www.tkk7.com/jjshcc/archive/2010/05/12/320705.html#Feedback3http://www.tkk7.com/jjshcc/comments/commentRss/320705.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/320705.html 2,查你的hibernate.cfg.xml文g中的相关联的两个<mapping resource=""/>的顺序,可能有其中一个需要引用另一个,但是另一个却q没有编译,是说被用作外键的表要放在前?br /> 3,查你?.hbm.xml文g名是否正?br /> 4, 查你?.hbm.xml里面cd?

Eric_jiang 2010-05-12 15:24 发表评论
]]>
Hibernate的基本映数据类?/title><link>http://www.tkk7.com/jjshcc/archive/2010/05/11/320601.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Tue, 11 May 2010 09:15:00 GMT</pubDate><guid>http://www.tkk7.com/jjshcc/archive/2010/05/11/320601.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/320601.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/05/11/320601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/320601.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/320601.html</trackback:ping><description><![CDATA[     摘要: ?-4  3U数据类型之间的对应关系 Hibernate映射cd Javacd 标准SQLcd ...  <a href='http://www.tkk7.com/jjshcc/archive/2010/05/11/320601.html'>阅读全文</a><img src ="http://www.tkk7.com/jjshcc/aggbug/320601.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-05-11 17:15 <a href="http://www.tkk7.com/jjshcc/archive/2010/05/11/320601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java数据cdQHibernate数据cdQ标准sql数据cd之间的对应表 http://www.tkk7.com/jjshcc/archive/2010/05/11/320599.htmlEric_jiangEric_jiangTue, 11 May 2010 08:49:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/05/11/320599.htmlhttp://www.tkk7.com/jjshcc/comments/320599.htmlhttp://www.tkk7.com/jjshcc/archive/2010/05/11/320599.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/320599.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/320599.htmlJava数据cdQHibernate数据cdQ标准sql数据cd之间的对应表
Java数据cd Hibernate数据cd 标准SQL数据cd
(PS:对于不同的DB可能有所差异)
byte、java.lang.Byte byte TINYINT
short、java.lang.Short short SMALLINT
int、java.lang.Integer integer INGEGER
long、java.lang.Long long BIGINT
float、java.lang.Float float FLOAT
double、java.lang.Double double DOUBLE
java.math.BigDecimal big_decimal NUMERIC
char、java.lang.Character character CHAR(1)
boolean、java.lang.Boolean boolean BIT
java.lang.String string VARCHAR
boolean、java.lang.Boolean yes_no CHAR(1)('Y'?N')
boolean、java.lang.Boolean true_false CHAR(1)('Y'?N')
java.util.Date、java.sql.Date date DATE
java.util.Date、java.sql.Time time TIME
java.util.Date、java.sql.Timestamp timestamp TIMESTAMP
java.util.Calendar calendar TIMESTAMP
java.util.Calendar calendar_date DATE
byte[] binary VARBINARY、BLOB
java.lang.String text CLOB
java.io.Serializable serializable VARBINARY、BLOB
java.sql.Clob clob CLOB
java.sql.Blob blob BLOB
java.lang.Class class VARCHAR
java.util.Locale locale VARCHAR
java.util.TimeZone timezone VARCHAR
java.util.Currency currency VARCHAR


Eric_jiang 2010-05-11 16:49 发表评论
]]>
hibernate的表l构以及表之间的关系的 *.hbm.xmlhttp://www.tkk7.com/jjshcc/archive/2010/05/11/320584.htmlEric_jiangEric_jiangTue, 11 May 2010 06:06:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/05/11/320584.htmlhttp://www.tkk7.com/jjshcc/comments/320584.htmlhttp://www.tkk7.com/jjshcc/archive/2010/05/11/320584.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/320584.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/320584.html假设有一个实体类Q用于存攄户信息,其定义如下:

package events;
import java.util.*;
public class Person {
    private Long id;
    private int age;
    private String firstname;
    private String lastname;
    public Person() {}

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    private Set emailAddresses = new HashSet();
    public Set getEmailAddresses() {
        return emailAddresses;
    }
    public void setEmailAddresses(Set emailAddresses) {
        this.emailAddresses = emailAddresses;
    }

    private Set events = new HashSet();
    // Defensive, convenience methods
    protected Set getEvents() {
        return events;
    }
    protected void setEvents(Set events) {
        this.events = events;
    }
    public void addToEvent(Event event) {
        this.getEvents().add(event);
        event.getParticipants().add(this);
    }
    public void removeFromEvent(Event event) {
        this.getEvents().remove(event);
        event.getParticipants().remove(this);
    }
}

 
则相应的描述POJO--->Person.hbm.xml中的配置信息如下Q?br />
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        " <hibernate-mapping>
    <class name="events.Person" table="PERSON">
        <id name="id" column="PERSON_ID">
            <generator class="identity" />
        </id>
        <property name="age" />
        <property name="firstname" />
        <property name="lastname" />
        <set name="events" table="PERSON_EVENT">
            <key column="PERSON_ID" />
            <many-to-many column="EVENT_ID" class="events.Event" />
        </set>
        <set name="emailAddresses" table="PERSON_EMAIL_ADDR">
            <key column="PERSON_ID" />
            <element type="string" column="EMAIL_ADDR" />
        </set>
    </class>
</hibernate-mapping>


说明Q?/div>
Q.class 节点

name: cd

table: cd应表名,默认为类名称

dynamic-update: 生成更新字段Ӟ只包含发生变动的字段Q默认ؓfalse?br />
dynamic-insert: 生成insert语句时仅包含非null字段

Proxy: 代理c,默认为空

discriminator-value: 子类辨别标识用于多态支?br />
where: 通过限定条g查询l果集。如Q查询有c在校学生的信息可以使用"where studentstatus='0'"

2.id节点

1.column               字段名称
2.type                 字段cd
3.length               字段长度
4.unsaved-value        用于判断对象值是否已l保?br /> 5.generator-class      主键产生方式
                       assigned
                       hilo
                       seqhilo
                       increment
                       identity
                       sequence
                       native
                       uuid.hex
                       uuid.string
                       foreign



3.property 节点

1.column               数据库表字段名称
2.type                 cd
3.length               长度
4.not-null             字段是否允许为空
5.unique               字段是否允许唯一Q是否允讔R复|
6.insert               insert操作Ӟ是否允许包含本字D|?br /> 7.update               update操作Ӟ是否包含本字D|?/p>





Event.hbm.xml


Eric_jiang 2010-05-11 14:06 发表评论
]]>使用Hibernate的客户化映射cd http://www.tkk7.com/jjshcc/archive/2010/05/11/320575.htmlEric_jiangEric_jiangTue, 11 May 2010 03:40:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/05/11/320575.htmlhttp://www.tkk7.com/jjshcc/comments/320575.htmlhttp://www.tkk7.com/jjshcc/archive/2010/05/11/320575.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/320575.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/320575.html     W一个例子是使用UserType映射枚Dcd。假设Account表中含有一sex列,cd为tinyintQ当前其0代表P1代表奻I来可能出现2{代表其他性别cdQ;我们当然可以在对应的AccountcMdintcd的sex属性,但这U数字化无显C意义且cd不安全的枚D不是很好的解x式,q里采用了java5的enum来作为Accountcȝ性别属性(如果不熟(zhn)java5的enumQ也可采用《effective java》中提到的经典的cd安全的枚举方案)。在Accountdenum GenderQ?br />
public class Account extends AbstractDomain<Long>{
    
    
public enum Gender{
        Male(
"male",0),
        Female(
"female",1);
        
        
private String name;
        
private int value;
        
        
public String getName() {
            
return name;
        }
        
public int getValue() {
            
return value;
        }
        
        
private Gender(String name,int value){
            
this.name = name;
            
this.value = value;
        }
        
        
public static Gender getGender(int value){
            
if(0 == value)return Male;
            
else if(1 == value)return Female;
            
else throw new RuntimeException();
        }
        
    }
    
    
private Gender gender;
    
public Gender getGender() {
        
return gender;
    }
    
public void setGender(Gender gender) {
        
this.gender = gender;
    }
       
//省略其他    
}

    接下来定义实现UserType接口的GenderUserTypeQ?br />
public class GenderUserType implements UserType{

    
public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
        
return null;
    }

    
/*
     *  q是用于Hibernate~存生成的快照,׃Gender是不可变的,直接q回好了?br />      
*/
    
public Object deepCopy(Object arg0) throws HibernateException {
        
return arg0;
    }

    
public Serializable disassemble(Object arg0) throws HibernateException {
        
return null;
    }

    
/*
     * ׃Gender是不可变的,因此直接==了,q个Ҏ(gu)在insert、update时用到?br />      
*/
    
public boolean equals(Object x, Object y) throws HibernateException {
        
return x == y;
    }

    
public int hashCode(Object o) throws HibernateException {
        
return o.hashCode();
    }

    
/*
     * 表明Gender是不是可变类Q很重要的概念哦Q,q里的Gender׃是枚举所以是不可变的
     
*/
    
public boolean isMutable() {
        
return false;
    }

    
/*
     *  从ResultSetdsexq返回Gender实例Q这个方法是在从数据库查询数据时用到?br />      
*/
    
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        
int value = rs.getInt(names[0]);
        
return Account.Gender.getGender(value);
    }

    
/*
     *  Gender的value讄到PreparedStatement?br />      
*/
    
public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException {
        if(value == null){
            ps.setInt(index,Account.Gender.Male.getValue());
        }else{
            ps.setInt(index,((Account.Gender)value).getValue());
        }

    }

    
public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
        
return null;
    }

    
/*
     * 讄映射的Genderc?br />      
*/
    
public Class returnedClass() {
        
return Account.Gender.class;
    }

    
/*
     *  讄Gender枚D中的value属性对应的Account表中的sex列的SQLcd
     
*/
    
public int[] sqlTypes() {
        
int[] typeList = {Types.TINYINT};
        
return typeList;
    }
}

    最后在Account的配|文件中配置gender属性就好了Q?br /> <property name="gender" type="org.prague.domain.util.GenderUserType" column="sex"></property>
    除了可以使用 UserType映射枚DcdQ也可以使用Hibernate的PersistentEnum来实现同L(fng)功能Q感兴趣的朋友可以参考文章http://www.hibernate.org/203.html?br />
    
    W二个例子是关于email的。假设Account表中email是一个varchar型的字段Q而Account中的Email是如下的c:

public class Email {
    String username;

    String domain;

    
public Email() {
    }

    
public Email(String username, String domain) {
        
this.username = username;
        
this.domain = domain;
    }

    
public String getUsername() {
        
return username;
    }

    
public String getDomain() {
        
return domain;
    }

    
    
public void setDomain(String domain) {
        
this.domain = domain;
    }

    
public void setUsername(String username) {
        
this.username = username;
    }

    
public String toString() {
        
return username + '@' + domain;
    }

    
public static Email parse(String email) {
        Email e 
= new Email();
        
int at = email.indexOf('@');
        
if (at == -1) {
            
throw new IllegalArgumentException("Invalid email address");
        }

        e.username 
= email.substring(0, at);
        e.domain 
= email.substring(at + 1);

        
return e;
    }

    @Override
    
public int hashCode() {
        
final int PRIME = 31;
        
int result = 1;
        result 
= PRIME * result + ((domain == null? 0 : domain.hashCode());
        result 
= PRIME * result + ((username == null? 0 : username.hashCode());
        
return result;
    }

    @Override
    
public boolean equals(Object obj) {
        
if (this == obj)    return true;
      
if(null == obj)return false;
        
if (getClass() != obj.getClass())
            
return false;
        
final Email other = (Email) obj;
        
if (domain == null) {
            
if (other.domain != null)
                
return false;
        } 
else if (!domain.equals(other.domain))
            
return false;
        
if (username == null) {
            
if (other.username != null)
                
return false;
        } 
else if (!username.equals(other.username))
            
return false;
        
return true;
    }
}
    email是Accountcȝ一个属性:
public class Account extends AbstractDomain<Long>{
    
    
private Email email;
    
public Email getEmail() {
        
return email;
    }
    
public void setEmail(Email email) {
        
this.email = email;
    }

    
//省略其他    
}

    q样的情况下Q需要将email的username + '@' + domain映射到Account表的email列,定义一个EmailUserType如下Q?br />  
   public class EmailUserType implements UserType{

    
public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
        
return null;
    }

    
public Object deepCopy(Object o) throws HibernateException {
        
if(null == o)return null;
        Email e 
= (Email)o;
        
return new Email(e.getUsername(),e.getDomain());
    }

    
public Serializable disassemble(Object arg0) throws HibernateException {
        
return null;
    }

    
public boolean equals(Object x, Object y) throws HibernateException {
        
if(x == y)return true;
        
if(x == null || y == null)return false;
        
boolean  f = x.equals(y);
        
return f;
    }

    
public int hashCode(Object o) throws HibernateException {
        
return o.hashCode();
    }

    
public boolean isMutable() {
        
return true;
    }

    
public Object nullSafeGet(ResultSet rs, String[] names, Object o) throws HibernateException, SQLException {
        String email 
= rs.getString(names[0]);
        
if(email == null)return null;
        
int index = email.indexOf("@");
        
if(index < 0)throw new RuntimeException();
        
return new Email(email.substring(0,index),email.substring(index+1));
    }

    
public void nullSafeSet(PreparedStatement ps, Object o, int index) throws HibernateException, SQLException {
        
if(o == null )ps.setNull(index, Types.VARCHAR);
        
else{
            Email e 
= (Email)o;
            
if(e.getDomain() == null || e.getUsername() == null)ps.setNull(index, Types.VARCHAR);
            
else{
                String email 
= e.getUsername() + "@" + e.getDomain();
                ps.setString(index, email);
            }
        }
        
    }

    
public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
        
return null;
    }

    
public Class returnedClass() {
        
return Email.class;
    }

    
public int[] sqlTypes() {
        
int[] typeList = {Types.VARCHAR};
        
return typeList;
    }
}

    最后配|下 email 属性:
<property name="email" type="org.prague.domain.util.EmailUserType" column="email"></property>
    相比于GednerQEmail是一个可变类Q如果想其变ؓ不可变类Q只需要去掉属性的setҎ(gu)Q,因此EmailUserType中的equals要用到Email的equalsQhashCode()Q方法,而deepCopy(Object o) 要做到是深拷贝,否则即便Email属性内Ҏ(gu)变,׃Hibernate~存中的快照指向的对象不变,在update时可能不起作用(在指定了dynamic-update属性的清况下)?br />

Eric_jiang 2010-05-11 11:40 发表评论
]]>
վ֩ģ壺 ߹ۿƬ˳Ƶ| ڵɫƵѹۿɫ| ޾Ʒ˾þվ| 2020þþƷ| þù޾Ʒ| ޹VA߹ۿ| Ʒ޸жƪ| 4huĻѵַ| ޹ľƷ| aɫëƬ| ߹ۿƵ| ͼƬһ| ִֻˬƵ| ŷһ| ߾þ֮ۺ߾þ| Ʒþþþù| ѴƬavֻƬ| þƷww47| Ƶ߹ۿ| ձһþ| һ| þþþþAVվ| պͼƬר1ҳ| 91ƷѸ| 2022| ޵һҳۺͼƬ| Ƶ97Ӱ| ĻۺϾþ| ޾þһح| þ޾Ʒվ| ޾Ʒþþþϼ| 91Ʒ| ɫ˵| ۺ| 91Ʒѹۿ| ۺϾþ| þۺɫHEZYO| Դѹۿ| պӰ߹ۿ| ߹ۿAVÿո| AŮAVۺϾþþ|