﻿<?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-Yako-随笔分类-转载好文</title><link>http://www.blogjava.net/Yako/category/6333.html</link><description>－－－寻找java</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 06:47:34 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 06:47:34 GMT</pubDate><ttl>60</ttl><item><title>转载：hibernate要点</title><link>http://www.blogjava.net/Yako/archive/2006/01/08/27175.html</link><dc:creator>Yako的Java天地</dc:creator><author>Yako的Java天地</author><pubDate>Sun, 08 Jan 2006 12:09:00 GMT</pubDate><guid>http://www.blogjava.net/Yako/archive/2006/01/08/27175.html</guid><wfw:comment>http://www.blogjava.net/Yako/comments/27175.html</wfw:comment><comments>http://www.blogjava.net/Yako/archive/2006/01/08/27175.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Yako/comments/commentRss/27175.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Yako/services/trackbacks/27175.html</trackback:ping><description><![CDATA[<H2 class=diaryTitle>hibernate要点</H2><B>关键词</B>： <A href="http://tag.bokee.com/tag/hibernate" target=_blank>hibernate</A> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<P>1.两种配置文件： <BR>&nbsp; A.hibernate.cfg.xml&nbsp;&nbsp; 和&nbsp;&nbsp; B.hibernate.properties 
<P>&nbsp; A中可含映射文件的配置，而B中hard codes加映射文件。</P>
<P>&nbsp; A。Configuration config=new Configuration().config(); <BR>&nbsp; B. Configuration config=new Configuration(); <BR>&nbsp;&nbsp;&nbsp;&nbsp; config.addClass(TUser.class); </P>
<P><BR>2.你不必一定用hibernate.cfg.xml或hibernate.properties这两文件名， <BR>&nbsp;&nbsp; 你也不一定非得把配置文件放在Classes下， <BR>&nbsp;&nbsp; File file=new File("c:\\sample\\myhibernate.xml"); <BR>&nbsp;&nbsp; Configuration config=new Configuration().config(file); </P>
<P>3. session.Flush() <BR>&nbsp;&nbsp; 强制数据库立即同步，当用事务时，不必用flush,事务提交自动调用flush <BR>&nbsp;&nbsp; 在session关闭时也会调用flush </P>
<P><BR>4. Hibernate总是使用对象类型作为字段类型 </P>
<P>5. XDoclet专门建立了hibernate doclet,就是在java代码上加上一些 <BR>&nbsp;&nbsp; java docTag，后来再让XDoclet分析该java代码，生成映射文件; </P>
<P>6.HQL子句本身大小写无关，但是其中出现的类名和属性名必须注意大小写区分。</P>
<P>7.关系： <BR>&nbsp; Constrained : 约束，表明主控表的主键上是否存在一个外键（foreigh key） <BR>&nbsp;&nbsp; 对其进行约束。 </P>
<P>&nbsp; property-ref:关联类中用于与主控类相关联的属性名，默认为关联类的主键属性名</P>
<P>&nbsp; 单向一对多需在一方配置，双向一对多需在双方进行配置</P>
<P>8.lazy=false:被动方的记录由hibernate负责记取，之后存放在主控方指定的 <BR>&nbsp; Collection类型属性中 </P>
<P>9. java.util.Set或net.sof.hibernate.collecton.Bag类型的Collection</P>
<P><BR>10.重要：inverse:用于标识双向关联中的被动方一端。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inverse=false的一方（主控方）负责维护关联关系.默认值：false </P>
<P>11.batch-size:采用延迟加载特征时，一次读入的数据数昨。</P>
<P>12.一对多通过主控方更新（主控方为一方时）</P>
<P>&nbsp;&nbsp; user.getAddresses().add(addr); <BR>&nbsp;&nbsp; session.save(user);//通过主控对象级联更新 &nbsp; </P>
<P>13.在one-to-many 关系中，将many 一方设为主动方（inverse=false）将有助性能 <BR>&nbsp;&nbsp; 的改善。在一方设置关系时，inverse=true,即将主控权交给多方， <BR>&nbsp;&nbsp; 这样多方可主动从一方获得foreign key,然后一次insert即可完工。 </P>
<P><BR>&nbsp;&nbsp; addr.setUser(user);//设置关联的TUser对象 <BR>&nbsp;&nbsp; user.getAddresses().add(addr); <BR>&nbsp;&nbsp; session.save(user);//级联更新&nbsp; </P>
<P>14.只有设为主控方的一方才关心（访问）对方的属性，被动方是不关心对方的属性的。</P>
<P>15.one-to-many与many-to-one节点的配置属性不同： <BR>&nbsp;&nbsp; 一对多关系多了lazy和inverse两个属性 <BR>&nbsp;&nbsp; 多对多节点属性：column:中间映射表中，关联目标表的关联字段 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class:类名，关联目标类 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outer-join:是否使用外联接&nbsp;&nbsp; &nbsp; </P>
<P>&nbsp;&nbsp; 注意:access是设置属性值的读取方式。</P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column是设置关联字段。 </P>
<P><BR>16.多对多，注意两方都要设置inverse和lazy,cascade只能设为insert-update <BR>&nbsp;&nbsp; 多对多关系中，由于关联关系是两张表相互引用，因此在保存关系状态时必须对双方同时保存。 </P>
<P>&nbsp;&nbsp; group1.getRoles().add(role1); <BR>&nbsp;&nbsp; role1.getGroups().add(group1); </P>
<P>&nbsp;&nbsp; session.save(role1); <BR>&nbsp;&nbsp; session.save(group1); </P>
<P>17.关于vo和po <BR>&nbsp;&nbsp; vo经过hibernate容量处理，就变成了po(该vo的引用将被容器保存，并且在session关闭时flush,因此po如果再传到其它地方改变了，就危险了) <BR>&nbsp; <BR>&nbsp;&nbsp; vo和po相互转换：BeanUtils.copyProperties(anotherUser,user); </P>
<P>18.对于save操作而言，如果对象已经与Session相关联（即已经被加入Session的实体容器中），则无需进行具体的操作。因为之后的Session.flush过程中，Hibernate <BR>会对此实体容器中的对象进行遍历，查找出发生变化的实体，生成并执行相应的update <BR>语句。 </P>
<P>19.如果我们采用了延迟加载机制，但希望在一些情况下，实现非延迟加 <BR>载时的功能，也就是说，我们希望在Session关闭后，依然允许操作user的addresses <BR>属性 <BR>Hibernate.initialize方法可以通过强制加载关联对象实现这一功能： <BR>这也正是我们为什么在编写POJO时，必须用JDK Collection接口（如Set,Map）, <BR>而非特定的JDK Collection实现类（如HashSet、HashMap）申明Collection属性的 <BR>原因。 </P>
<P>20.事务：从sessionFactory获得session,其自动提交属性就已经关闭(AutoCommit=false),此时若执行了jdbc操作，如果不显式调用session.BeginTransaction(),是不会执行事务操作的。</P>
<P>&nbsp;&nbsp; jdbc transaction:基于同一个session(就是同一个connection)的事务; <BR>&nbsp;&nbsp; jta&nbsp; transaction:跨session（跨connection）事务. </P>
<P>&nbsp;&nbsp; 对于jta事务，有三种实现方法： <BR>&nbsp;&nbsp;&nbsp;&nbsp; A。UserTransaction tx=new InitialContext().lookup("..."); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx.commit(); <BR>&nbsp;&nbsp;&nbsp;&nbsp; B. 使用hibernate封装的方法：(不推荐) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transaction tx=session.beginTransaction(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx.commit(); <BR>&nbsp;&nbsp;&nbsp;&nbsp; C. 使用ejb之sessionBean的事务技持方法，你只要在把需要在发布描述符中，把需要jta事务的方法声明为require即可 </P>
<P>21.悲观锁，乐观锁： <BR>&nbsp;&nbsp; 乐观锁一般通过version来实现，注意version节点必须出现在id后。 </P>
<P><BR>22.Hibernate中，可以通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围。 <BR>&nbsp;&nbsp; Query接口中也提供了与其一致的方法，hibernate主要在dialect类中实现在这个功能。 </P>
<P><BR>23.cache <BR>&nbsp;&nbsp; <HIBERNATE-CONFIGURATION /><BR>&nbsp;<SESSION-FACTORY /> <BR>&nbsp;…… <BR>&nbsp;&nbsp;<property name="hibernate.cache.provider_class"> <BR>&nbsp;&nbsp;&nbsp;net.sf.ehcache.hibernate.Provider <BR>&nbsp;&nbsp;</property>&nbsp; </P>
<P>&nbsp; 还需对ecache本身进配置 <BR>&nbsp; <EHCACHE /><BR>&nbsp;<DISKSTORE path="java.io.tmpdir" /> <BR>&nbsp;<DEFAULTCACHE <br="" />&nbsp;maxElementsInMemory="10000" //Cache中最大允许保存的数据数量 <BR>&nbsp;eternal="false" //Cache中数据是否为常量 <BR>&nbsp;timeToIdleSeconds="120" //缓存数据钝化时间 <BR>&nbsp;timeToLiveSeconds="120" //缓存数据的生存时间 <BR>&nbsp;overflowToDisk="true" //内存不足时，是否启用磁盘缓存 <BR>&nbsp;/&gt; <BR>&nbsp; </EHCACHE /></P>
<P>&nbsp; 之后在映射文件中指定各个映射实体的cache策略 <BR>&nbsp; <CLASS name=" org.hibernate.sample.TUser" ....="" /><BR>&nbsp;<CACHE usage="read-write" /> <BR>&nbsp;.... <BR>&nbsp;<SET name="addresses" ....="" /> <BR>&nbsp;&nbsp;<CACHE usage="read-only" /> <BR>&nbsp;.... <BR>&nbsp;</SET /> <BR>&nbsp;</CLASS /> </P>
<P>&nbsp;***************************************************** <BR>&nbsp;Query.list()跟Query.iterate()的不同： <BR>&nbsp;对于query.list()总是通过一条sql语句获取所有记录,然后将其读出，填入pojo返回; <BR>&nbsp;但是query.iterate()，则是首先通过一条Select SQL 获取所有符合查询条件的记录的 <BR>id，再对这个id 集合进行循环操作，通过单独的Select SQL 取出每个id 所对应的记 <BR>录，之后填入POJO中返回。 </P>
<P>&nbsp;也就是说，对于list 操作，需要一条SQL 完成。而对于iterate 操作，需要n+1 <BR>条SQL。，list方法将不会从Cache中读取数据。iterator却会。 </P>
<P><BR>24.ThreadLocal:它会为每个线程维护一个私有的变量空间。实际上， <BR>其实现原理是在JVM 中维护一个Map，这个Map的key 就是当前的线程对象，而value则是 <BR>线程通过ThreadLocal.set方法保存的对象实例。当线程调用ThreadLocal.get方法时， <BR>ThreadLocal会根据当前线程对象的引用，取出Map中对应的对象返回。 </P>
<P>&nbsp;这样，ThreadLocal通过以各个线程对象的引用作为区分，从而将不同线程的变量隔离开 <BR>来。 </P>
<P><BR>25.Hibernate官方开发手册标准示例: <BR>&nbsp; public class HibernateUtil { <BR>private static SessionFactory sessionFactory; <BR>static { <BR>try { <BR>// Create the SessionFactory <BR>sessionFactory = new <BR>Configuration().configure().buildSessionFactory(); <BR>} catch (HibernateException ex) { <BR>throw new RuntimeException( <BR>"Configuration problem: " + ex.getMessage(), <BR>ex <BR>); <BR>} <BR>} <BR>public static final ThreadLocal session = new ThreadLocal(); <BR>public static Session currentSession() throws HibernateException <BR>{ <BR>Session s = (Session) session.get(); <BR>// Open a new Session, if this Thread has none yet <BR>if (s == null) { <BR>s = sessionFactory.openSession(); <BR>session.set(s); <BR>} <BR>return s; <BR>} <BR>public static void closeSession() throws HibernateException { <BR>Session s = (Session) session.get(); <BR>session.set(null); <BR>if (s != null) <BR>s.close(); <BR>} <BR>}&nbsp; </P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>26.通过filter实现session的重用： <BR>&nbsp;&nbsp; public class PersistenceFilter implements Filter <BR>{ <BR>protected static ThreadLocal hibernateHolder = new ThreadLocal(); <BR>public void doFilter(ServletRequest request, ServletResponse <BR>response, FilterChain chain) <BR>throws IOException, ServletException <BR>{ <BR>hibernateHolder.set(getSession()); <BR>try <BR>{ <BR>…… <BR>chain.doFilter(request, response); <BR>…… <BR>} <BR>finally <BR>{ <BR>Session sess = (Session)hibernateHolder.get(); <BR>if (sess != null) <BR>{ <BR>hibernateHolder.set(null); <BR>try <BR>{ <BR>sess.close(); <BR>} <BR>catch (HibernateException ex) { <BR>throw new ServletException(ex); <BR>} <BR>} <BR>} <BR>} <BR>……}</P><img src ="http://www.blogjava.net/Yako/aggbug/27175.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Yako/" target="_blank">Yako的Java天地</a> 2006-01-08 20:09 <a href="http://www.blogjava.net/Yako/archive/2006/01/08/27175.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>