??xml version="1.0" encoding="utf-8" standalone="yes"?>中文字幕精品一区二区精品绿巨人,美女久久久久久,亚洲第一福利视频http://www.aygfsteel.com/stevenjohn/category/51097.html那些青春的岁?/description>zh-cnFri, 19 Apr 2013 18:44:49 GMTFri, 19 Apr 2013 18:44:49 GMT60请问hibernate中session应该什么时候关?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398111.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 19 Apr 2013 13:28:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398111.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/398111.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398111.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/398111.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/398111.html</trackback:ping><description><![CDATA[<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;">我是一个初学? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;">我徏了一个classes表和一个students?表示班和学?其中学生里面有一个外键关联到班? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;">然后学生c里面徏了一个classes的属? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;">用session取出学生?如果关闭session的话,无法读取到学生c里的classes?没有关闭pd? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;">请问q个session会不会媄响到其他用户的访问呢? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;">是说如果有两个用户q行操作数据库的?一个用Lsession不关闭媄不媄响另一个用户呢?<br /><br /><br /><br /><br /><br /><br /><br /></span><p style="margin: 10px 0px; padding: 0px; line-height: 24px; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #fbeded;">J2EE中最大的一个观念就是分?. <br /><br />session是持久层的东?不可H到别的?. <br /><br />你的q个问题其实是延迟加蝲的问? <br /><br />从理论的角度?最好是用一个就关一?防止资源消? <br />但由于hibernate中的延迟加蝲,所以出C你的关闭session的话,无法读取到学生c里的classes值问? <br />q个问题可以用Hibernate.initialize()来解?也可׃用opensessionview的方?spring中提供了q样的filter <br />不知道这在用中有没有用spring.用了比较方?也不会出C所说的 <br /></p><div id="wmqeeuq" class="quote_title" style="font-weight: bold; padding: 5px; margin: 5px 0px 0px 15px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;">引用</div><div id="wmqeeuq" class="quote_div" style="border: 1px solid #cccccc; margin: 0px 5px 5px 15px; padding: 3px; background-color: #fafafa; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px;">一个用Lsession不关闭媄不媄响另一个用?/div><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;">因ؓsession由spring来管?很安?不会出现q个Uƈ发问? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;">如果只是使用了Hibernate的话,那得注意?你在servlet中直接创建session可能出现ƈ发问?因ؓsession不是U程安全?而servlet是多U程? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;">q时可以使用ThreadLocal来解册个问? </span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #fbeded;">希望对你有所帮助!</span><br /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f2f8ef;"><br /><br /><br /></span><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/398111.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2013-04-19 21:28 <a href="http://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398111.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate4之getCurrentSession和openSessionhttp://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398110.htmlabinabinFri, 19 Apr 2013 13:22:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398110.htmlhttp://www.aygfsteel.com/stevenjohn/comments/398110.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2013/04/19/398110.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/398110.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/398110.html在一个应用程序中Q?/span>如果DAO层用Spring的hibernate模板Q通过Spring来控制session的生命周期,则首选getCurrentSession 

使用Hibernate的大多数应用E序需要某UŞ式的“上下文相关的”sessionQ特定的session在整个特定的上下文范围内始终有效。然而,对不同类型的应用E序而言Q要lؓ什么是l成q种“上下?#8221;下一个定义通常是困隄Q不同的上下文对“当前”q个概念定义了不同的范围。在3.0版本之前Q用Hibernate的程序要么采用自行编写的ZThreadLocal的上下文sessionQ如下面代码Q,要么采用HibernateUtilq样的辅助类Q要么采用第三方框架Q比如Spring或Pico)Q它们提供了Z代理(proxy)或者基于拦截器(interception)的上下文相关session 

?.0.1版本开始,Hibernate增加了SessionFactory.getCurrentSession()Ҏ(gu)。一开始,它假定了采用JTA事务QJTA事务 定义了当前session的范围和上下?scope and context)。Hibernate开发团队坚信,因ؓ有好几个独立的JTA TransactionManager实现E_可用Q不论是否被部vC个J2EE容器中,大多?假若不是所有的Q应用程序都应该采用JTA事务理?Zq一点,采用JTA的上下文相关session可以满你一切需要?nbsp;

更好的是Q从3.1开始,SessionFactory.getCurrentSession()的后台实现是可拔插的。因此,我们引入了新的扩展接?(org.hibernate.context.CurrentSessionContext)和新的配|参?(hibernate.current_session_context_class)Q以便对什么是“当前session”的范围和上下?scope and context)的定义进行拔插?nbsp;

org.hibernate.context.JTASessionContext - 当前sessionҎ(gu)JTA来跟t和界定。这和以前的仅支持JTA的方法是完全一L?nbsp;

org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线E来跟踪和界定?nbsp;

q两U实现都提供?#8220;每数据库事务对应一个session”的编E模型,也称作一h一事务。即Hibernate的session的生命周期由数据库事务的生存来控制。假若你采用自行~写代码来管理事务(比如Q在Ua的J2SE,或?JTA/UserTransaction/BMTQ,你用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行,事务边界是声明式定义的,你不需要在代码中进行Q何事务或session理操作?nbsp;

1、getCurrentSession()与openSession()的区?/span> 
* 采用getCurrentSession()创徏的session会绑定到当前U程中,而采用openSession() 
创徏的session则不?nbsp;
* 采用getCurrentSession()创徏的session在commit或rollback时会自动关闭Q而采用openSession()创徏的session必须手动关闭 

2、用getCurrentSession()需要在hibernate.cfg.xml文g中加入如下配|: 
* 如果使用的是本地事务Qjdbc事务Q?nbsp;
<property name="hibernate.current_session_context_class">thread</property> 
* 如果使用的是全局事务Qjta事务Q?nbsp;
<property name="hibernate.current_session_context_class">jta</property> 

在SessionFactory启动的时候,Hibernate会根据配|创建相应的CurrentSessionContextQ在 getCurrentSession()被调用的时候,实际被执行的Ҏ(gu)是CurrentSessionContext.currentSession()。在currentSession()执行Ӟ如果当前Session 为空QcurrentSession 会调用SessionFactory 的openSession?/span>所以getCurrentSession() 对于Java EE 来说是更好的获取Session 的方法?/span> 

sessionFactory.getCurrentSession()可以完成一pd的工作,当调用时Qhibernatesessionl定到当前线E,事务l束后,hibernatesession从当前线E中释放Qƈ且关闭sessionQ当再次调用getCurrentSession()Ӟ得C个新的sessionQƈ重新开始这一pd工作?nbsp;
q样调用Ҏ(gu)如下Q?nbsp;
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
session.save(theEvent);
session.getTransaction().commit();



不需要close session?nbsp;

利于ThreadLocal模式理Session 
   早在Java1.2推出之时QJavaq_中就引入了一个新的支持:java.lang.ThreadLocalQ给我们在编写多U程E序时提供了一U新的选择。ThreadLocal是什么呢Q其实ThreadLocalq是一个线E的本地实现版本Q它q不是一个ThreadQ而是thread local variable(U程局部变?。也许把它命名ؓThreadLocalVar更加合适。线E局部变?ThreadLocal)其实的功用非常简单,是为每一个用某变量的线E都提供一个该变量值的副本Q是每一个线E都可以独立地改变自q副本Q而不会和其它U程的副本冲H。从U程的角度看Q就好像每一个线E都完全拥有一个该变量。ThreadLocal是如何做Cؓ每一个线E维护变量的副本的呢Q其实实现的思\很简单,在ThreadLocalcM有一个MapQ用于存储每一个线E的变量的副本?nbsp;


public class HibernateUtil {
    
    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
    
    //创徏一个局部线E变?/span>
    private static final ThreadLocal<Session> THREAD_LOCAL = new ThreadLocal<Session>();
    
    private static final Configuration cfg = new Configuration();
    
    private static SessionFactory sessionFactory;
    
    /*
     * 取得当前session对象
     
*/
    @SuppressWarnings("deprecation")
    public static Session currentSession() throws HibernateException {
        Session session = (Session)THREAD_LOCAL.get();
        if (session == null) {
            if (sessionFactory == null) {
                try {
                    cfg.configure(CONFIG_FILE_LOCATION);
                    sessionFactory = cfg.buildSessionFactory();
                } catch (Exception e) {
                    System.out.println("【ERROR】创建SessionFactory对象出错Q原因是Q?);
                    e.printStackTrace();
                }
            }
            
            session = sessionFactory.openSession();
            THREAD_LOCAL.set(session);
        }
        return session;
    }

    public static void closeSession() throws HibernateException {
        Session session = (Session) THREAD_LOCAL.get();
        THREAD_LOCAL.set(null);
        if(session != null){
            session.close();
        }
    }
}













abin 2013-04-19 21:22 发表评论
]]>
Hibernate hql 查询指定字段q获取结果集http://www.aygfsteel.com/stevenjohn/archive/2012/10/25/390219.htmlabinabinThu, 25 Oct 2012 06:32:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/10/25/390219.htmlhttp://www.aygfsteel.com/stevenjohn/comments/390219.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/10/25/390219.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/390219.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/390219.html在hibernate中,用hql语句查询实体c,采用listҎ(gu)的返回结果ؓ一个ListQ该List中封装的对象分ؓ以下三种情况Q?br />1.查询全部字段的情况下Q如"from 实体c?Qlist中封装的对象为实体类本nQ各属性都得到填充?br />2.只查询一个字D,默认情况下,list中封装的是Object对象?/span>
3.查询两个或两个以上的字段Q默认情况下Qlist中封装的?span style="color: rgb(255,0,0)">Object[]
,长度与所查询的字D|一致?br />

对于后两U情况,用标{N历时不太方便Q因为无法直接{换成实体cȝ对象。比较简单的解决Ҏ(gu)是:

の:在hql中?span style="color: rgb(255,0,0)">select new 包名.cd(属?Q属?……) from 实体c,同时在实体类中添加带参的构造方法,参数的个数和序与(属?Q属?……) 保持一?/span>Q这h们得到的list中存攄依然是实体类的对象,所查询到的属性得C填充Q用v来更为方ѝ?br />

  の:hql查询多表部分字段Q?span style="color: rgb(255,0,0)">select new 包名.?实体cd(?.属?Q表2.属?……) from ?实体c??实体c?where ?.ID=?.IDQ即相关联的字段Q?/span>Q同时在要返回的?实体cMd?的属性和带参的构造方法,参数的个数和序与(?.属?Q表2.属?2……) 保持一?/span>

例如要查询Problem 中的pidQscoreQtitleQtotalAccept,totalSubmission,unSee

public class Problem {  
    private int pid;  
    private int score;  
    private int timeLimit;  
    private int memoryLimit;  
    private int totalAccept;  
    private int totalSubmission;  
    private int unSee;  
    private String title;  
    private String description;  
    private String input;  
    private String output;  
      
    public Problem(int pid, int score,String title, int totalAccept, int totalSubmission,  
             int unSee) {  
        super();  
        this.pid = pid;  
        this.score = score;  
        this.totalAccept = totalAccept;  
        this.totalSubmission = totalSubmission;  
        this.unSee = unSee;  
        this.title = title;  
    }  
    //省略getter ?setter   
}  
查询语句如下
      Query query=session.createQuery("select new Problem(pid,score,title,totalAccept,totalSubmission,unSee) from Problem order by pid");  
        //query.setFirstResult(firstResult); //分页函数   
        //query.setMaxResults(maxResutl);   
      
        List<Problem> problems=query.list();//q回的还是Problem对象 









关于hibernate的问题: 
我现在有?nbsp;
hql="select s.id,s.name,t.id,t.name from User s,Useraddress t where t.id=s.id" 

q条sql里面的User和Useraddress是两个实体类Q现在组合查询分别取出来两个实体c里面的两个字段Q然后我惛_建立一个实体类ResultQ里面定义这四个l果集里面的字段Q能不能执行完这条hqlQ正好把q个l果集对应到实体cResult里面呢,Resultq个实体c,没写映射文gResult.hbm.xml. 
希望能帮下忙 

2U做?nbsp;
创徏一个class temp 
有属性sid,name,tid,sname,tname 
创徏一个构造函?nbsp;
public temp(sid,name,tid,sname,tname) 



1.hql?nbsp;
List<temp> 

select new temp(s.id,s.name,t.id,t.name) from User s,Useraddress t where t.id=s.id 

2.List 
记录的每一行是object[] 遍历 
object[0] ==s.id 
object[1] ==s.name 
object[2] ==t.id 
object[3] ==t.name 

 



感谢glamey兄弟的文章,正好解决了当前遇到的问题。原文链接如下:http://glamey.iteye.com/blog/721019
        假设我们现在有一个DTOQ其属性包括两张表的属性,我们现在需要将sql语句查询得到的内容{Z个DTO对象Q其解决Ҏ(gu)如下Q?nbsp; 

String sql = "select u.userName as userName Qp.title as title ,p.addTime as addTime from user as u,post as p where u.id=p.userId"  
Query q = factory.getCurrentSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(PostVO.class));

      上面select中as后面的内容必dPostVO中属性名一_q样可以返回一个针对PostVO的一个集合?nbsp;
        其实大家可以看下hibernateq一部分的源码就会发玎ͼ主要是用了AliasToBeanResultTransformerq个c,通过sql的查询,会返回数l,然后hibernateҎ(gu)数据表的映射Q自动帮我们来set对应的字D属性,所以标U的部分务必要跟VO中的属性g_要不然会报错的?nbsp;
        如果需要的话,大家也可以重写这个类。例如VOResultTransformer。然后在dao中更Ҏ(gu)Q?nbsp; 

setResultTransformer(new VOResultTransformer(PostVO.class));

  另外Q除了以上glamey的方法外Q还有一U方法:  
Query q = session.createQuery("select new com.hibernate.MsgInfo(m.id, m.cont, m.topic.title, m.topic.category.name) from Msg m");
List<MsgInfo> list=q.list();

     其中QMsgInfo是DTO?/span>值得注意的是Q第二种Ҏ(gu)中DTO必须提供带参数的构造方法,q且HQL语句中属性的位置要与构造方法中的位|一一对应?/span> 


abin 2012-10-25 14:32 发表评论
]]>
Hibernate 命名查询NamedQuery http://www.aygfsteel.com/stevenjohn/archive/2012/09/10/387383.htmlabinabinMon, 10 Sep 2012 05:28:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/09/10/387383.htmlhttp://www.aygfsteel.com/stevenjohn/comments/387383.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/09/10/387383.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/387383.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/387383.html/**
 * UserBean entity. @author MyEclipse Persistence Tools
 */

public class UserBean implements java.io.Serializable {

 // Fields

 private String id1;
 private String name1;
 private java.util.Date createtime1;
 private String address;

 // Constructors

 /** default constructor */
 public UserBean() {
 }

 /** minimal constructor */
 public UserBean(String id1) {
  this.id1 = id1;
 }

 /** full constructor */
 public UserBean(String id1, String name1, java.util.Date createtime1, String address) {
  this.id1 = id1;
  this.name1 = name1;
  this.createtime1 = createtime1;
  this.address = address;
 }

 // Property accessors

 public String getId1() {
  return this.id1;
 }

 public void setId1(String id1) {
  this.id1 = id1;
 }

 public String getName1() {
  return this.name1;
 }

 public void setName1(String name1) {
  this.name1 = name1;
 }

 public java.util.Date getCreatetime1() {
  return this.createtime1;
 }

 public void setCreatetime1(java.util.Date createtime1) {
  this.createtime1 = createtime1;
 }

 public String getAddress() {
  return this.address;
 }

 public void setAddress(String address) {
  this.address = address;
 }

}



<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.lcdbtsf.air.po.UserBean" table="ABIN5" schema="ABIN" dynamic-update="true">
        <id name="id1" type="string">
            <column name="ID1" precision="0" />
            <generator class="assigned" />
        </id>
        <property name="name1" type="string">
            <column name="NAME1" default="defaultname1"/>
        </property>
        <property name="createtime1" type="java.util.Date">
            <column name="CREATETIME1" length="19" />
        </property>
        <property name="address" type="string" update="true"  access="field" insert="true">
            <column name="ADDRESS" default="defaultaddress" />
        </property>
    </class>
   
    <query name="getUserBeanByAddress">
     <![CDATA[select o from UserBean o where o.address=:address order by o.createtime1 desc]]>
    </query>
   
     <!-- 命名查询中用sqlQ不推荐使用Q媄响跨数据?br />    <sql-query name="getUserBeanByAddress">
     <![CDATA[select o from UserBean o where o.address=:address order by o.createtime1 desc]]>
    </sql-query>
    -->
   
</hibernate-mapping>




package com.abin.lee.hibernate;

import java.util.List;

import junit.framework.TestCase;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Order;

import com.lcdbtsf.air.po.UserBean;

public class UserDao extends TestCase {

 public  List<UserBean> getAll(){
  Configuration cfg = new Configuration().configure(); // 获取hibernate的配|信?br />  SessionFactory sf = cfg.buildSessionFactory(); // Ҏ(gu)config建立sessionFactory
  Session session = sf.openSession(); // factory用于建立sessionQ开启SessionQ相当于开启JDBC的Connection
  Transaction ts = session.beginTransaction(); // 创徏事务的对象ts
  List<UserBean> list=null;
  try {
   Criteria criteria=session.createCriteria(UserBean.class);
   criteria.addOrder(Order.desc("createtime1"));
   list=criteria.list();
   ts.commit();
  } catch (HibernateException he) {
   he.printStackTrace();
   ts.rollback();
  }
  return list;
 }
 
 public  List<UserBean> getAllByAddress(String address){
  Configuration cfg = new Configuration().configure(); // 获取hibernate的配|信?br />  SessionFactory sf = cfg.buildSessionFactory(); // Ҏ(gu)config建立sessionFactory
  Session session = sf.openSession(); // factory用于建立sessionQ开启SessionQ相当于开启JDBC的Connection
  Transaction ts = session.beginTransaction(); // 创徏事务的对象ts
  List<UserBean> list=null;
  try {
   Query query=session.getNamedQuery("getUserBeanByAddress");
   query.setParameter("address", address);
   list=query.list();
   ts.commit();
  } catch (HibernateException he) {
   he.printStackTrace();
   ts.rollback();
  }
  return list;
 }

}





package com.abin.lee.hibernate;

import java.util.List;

import junit.framework.TestCase;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import com.lcdbtsf.air.po.UserBean;

public class UserDaoTest extends TestCase {

 public void test() {
   List<UserBean> list=new UserDao().getAllByAddress("shanghai");
  try {
   if(list.size()>0){
    UserBean user =list.get(0);
    System.out.println(list.get(0).getId1());
   }
  } catch (HibernateException he) {
   he.printStackTrace();  }
 }

}

 



abin 2012-09-10 13:28 发表评论
]]>
hibernate ?Criteria 的用介l?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2012/09/07/387209.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 06 Sep 2012 16:04:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2012/09/07/387209.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/387209.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2012/09/07/387209.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/387209.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/387209.html</trackback:ping><description><![CDATA[     摘要: 要对资料库管理系l进行操作,最基本的就是用SQLQStandard Query LanguageQ语句,大部份的资料库都支援标准的SQL语句Q然而也有一些特定于资料库的SQL语句Q应用程式配合SQL语句q行资料库查询时Q若使用到特定于资料库的SQL语句Q程式本w会有相依于特定资料库的问题。用HibernateӞ即(zhn)不了解SQL的用与撰写Q也可以使用它所提供的API来进行SQL语句查询Qo...  <a href='http://www.aygfsteel.com/stevenjohn/archive/2012/09/07/387209.html'>阅读全文</a><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/387209.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2012-09-07 00:04 <a href="http://www.aygfsteel.com/stevenjohn/archive/2012/09/07/387209.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate Criteriahttp://www.aygfsteel.com/stevenjohn/archive/2012/09/06/387208.htmlabinabinThu, 06 Sep 2012 15:59:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/09/06/387208.htmlhttp://www.aygfsteel.com/stevenjohn/comments/387208.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/09/06/387208.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/387208.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/387208.html

hibernate ?span class="Apple-converted-space"> Criteria 的用介l?/a>


http://blog.csdn.net/alex197963/article/details/2628196


abin 2012-09-06 23:59 发表评论
]]>
Hibernate 调用oracle存储q程http://www.aygfsteel.com/stevenjohn/archive/2012/09/06/387203.htmlabinabinThu, 06 Sep 2012 15:21:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/09/06/387203.htmlhttp://www.aygfsteel.com/stevenjohn/comments/387203.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/09/06/387203.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/387203.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/387203.htmlpackage com.abin.lee.bean;

/**
 * Userbean entity. @author MyEclipse Persistence Tools
 */

public class UserBean implements java.io.Serializable {

 // Fields

 private String id;
 private String username;
 private String password;

 // Constructors

 /** default constructor */
 public UserBean() {
 }

 /** minimal constructor */
 public UserBean(String id) {
  this.id = id;
 }

 /** full constructor */
 public UserBean(String id, String username, String password) {
  this.id = id;
  this.username = username;
  this.password = password;
 }

 // Property accessors

 public String getId() {
  return this.id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getUsername() {
  return this.username;
 }

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

 public String getPassword() {
  return this.password;
 }

 public void setPassword(String password) {
  this.password = password;
 }

}





<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.abin.lee.bean.UserBean" table="USERBEAN" schema="ABING">
        <id name="id" type="string">
            <column name="ID" length="80" />
            <generator class="assigned" />
        </id>
        <property name="username" type="string">
            <column name="USERNAME" length="80" />
        </property>
        <property name="password" type="string">
            <column name="PASSWORD" length="80" />
        </property>
    </class>
</hibernate-mapping>






package com.abin.lee.dao;

import java.sql.SQLException;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class UserDao {
 private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
 private static SessionFactory sessionFactory;
 static {
  sessionFactory=new Configuration().configure().buildSessionFactory();
 }
 public static Session GetSession(){
  Session session=(Session)threadLocal.get();
  if(null == session|| !session.isOpen()){
   if(null==sessionFactory){
    sessionFactory=new Configuration().configure().buildSessionFactory();
   }
   session=(sessionFactory!=null)?sessionFactory.openSession():null;
   threadLocal.set(session);
  }
  return session;
 }
 
 public static int insert(String id,String usr,String pwd) throws SQLException{
  UserDao UserDao=new UserDao();
  Session session=UserDao.GetSession();
  Transaction tx=session.beginTransaction();
  SQLQuery sqlQuery = session.createSQLQuery("{call insertObj(?,?,?)}");
  sqlQuery.setParameter(0, id);
  sqlQuery.setParameter(1, usr);
  sqlQuery.setParameter(2, pwd);
  int result=sqlQuery.executeUpdate();
  System.out.println("result="+result);
  return result;
 }
 
}






package com.abin.lee.test;

import java.sql.SQLException;

import junit.framework.TestCase;

import com.abin.lee.dao.UserDao;

public class UserTest extends TestCase{
 public void test() throws SQLException{
  UserDao user=new UserDao();
  int success=user.insert("abin","abing","bing");
  System.out.println("success="+success);
 }
}








<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

 <session-factory>
  <property name="dialect">
   org.hibernate.dialect.OracleDialect
  </property>
  <property name="connection.url">
   jdbc:oracle:thin:@localhost:1521:xe
  </property>
  <property name="connection.username">abing</property>
  <property name="connection.password">abing</property>
  <property name="connection.driver_class">
   oracle.jdbc.driver.OracleDriver
  </property>
  <property name="myeclipse.connection.profile">
   OracleConnection
  </property>
  <mapping resource="com/abin/lee/bean/UserBean.hbm.xml" />
   
    </session-factory>

</hibernate-configuration>










abin 2012-09-06 23:21 发表评论
]]>
hibernate 分页Ҏ(gu)http://www.aygfsteel.com/stevenjohn/archive/2012/05/17/378423.htmlabinabinThu, 17 May 2012 08:54:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/05/17/378423.htmlhttp://www.aygfsteel.com/stevenjohn/comments/378423.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/05/17/378423.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/378423.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/378423.html* 使用hql 语句q行操作

   * @param hql
* @param offset
* @param length
* @return List
*/
public List getListForPage(final String hql, final int offset,
    final int length) {
   List list = getHibernateTemplate().executeFind(new HibernateCallback() {
    public Object doInHibernate(Session session)
      throws HibernateException, SQLException {
     Query query = session.createQuery(hql);
     query.setFirstResult(offset);
     query.setMaxResults(length);
     List list = query.list();
     return list;
    }
   });
   return list;
}/**
* 使用criterionq行操作
* @param arg
* @param criterions
* @param offset
* @param length
* @return List
*/
protected List getListForPage(final Class arg, final Criterion[] criterions,final int offset, final int length) {
   List list = getHibernateTemplate().executeFind(new HibernateCallback() {
    public Object doInHibernate(Session session)
      throws HibernateException, SQLException {
     Criteria criteria = session.createCriteria(arg);
     //循环遍历dU束条g
     for (int i = 0; i < criterions.length; i++) {
      criteria.add(criterions[i]);
     }
     criteria.setFirstResult(offset);
     criteria.setMaxResults(length);
     return criteria.list();
    }
   });
   return list;
}

你不是说你用HibernateTemplate了,如果你用的是spring的HibernateTemplateQ那么就直接用就行了Q如果你是自己写的templateQ?br />那你也应该会准备一个HibernateCallbackcdQ这才是典型的模板加回调?

了Q把HibernateCallback也给你脓(chung)出来

import org.hibernate.HibernateException;
import org.hibernate.Session;

/*************************************
* ?Hibernate 所提供的一?回调接口Q?br />* 此接口定义了 l一 Hibernate的业务操作;
* @author kenshin
*
*/
public interface HibernateCallback {

/**************************************
  * 回调接口的回调方法,此方法用者无需调用,
  * 它由 模板cLq行回调Qƈ传入一?session参数Q?br />  * 以便让用者完成相关业?br />  * @param ses
  * @return 执行l果
  * @throws HibernateException
  */
Object doInHibernate(Session ses)
       throws HibernateException;

}

abin 2012-05-17 16:54 发表评论
]]>
Spring+Hibernate下配|Hibernate二~存EhCache http://www.aygfsteel.com/stevenjohn/archive/2012/05/13/378025.htmlabinabinSat, 12 May 2012 18:07:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/05/13/378025.htmlhttp://www.aygfsteel.com/stevenjohn/comments/378025.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/05/13/378025.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/378025.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/378025.html假设cA为持久化对象Q对应表为tableAQ这里没有考虑A和其他表兌的情c?/p>

在spring下配|用二U缓存:

<property name="hibernateProperties">
<props>
........
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
</props>
</property>

其中${hibernate.cache.provider_class}为net.sf.ehcache.hibernate.EhCacheProviderQ?{hibernate.cache.use_query_cache}属性gؓtrueQ对l常使用的List查询方式Q只有在使用查询~存Ӟ才会从缓存中通过id去get~存的|查询~存一般缓存查询语句和查询l果的idQ?/p>

A的持久化映射文g中加上cache元素Qusage属性的取值根据自q情况自己指定相应的?/p>

<cache usage="read-write"/>

配置spring的HibernateTemplateҎ(gu)询语句和l果~存QcacheQueriesgؓtrue)Q?/p>

<bean id="hibernateTemplate"
        <property name="sessionFactory"><ref bean="sessionFactory"/></property>
    <property name="cacheQueries" value="${hibernate.cache.use_query_cache}"></property>
</bean>
开发的spring daoQ集成HibernateDaoSupportQ应该配|实用这个hibernateTemplateQ?/p>

<bean id="myDao" of HibernateDaoSupport">
<property name="hibernateTemplate" ref="hibernateTemplate" />
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

在src下新建ehcache.xml文gQ文件内容如下:

<ehcache>
<diskStore path="java.io.tmpdir"/>

<!--
        eternal:元素是否怹?
        MemoryStoreEvictionPolicy:default is LRU
    -->
<defaultCache         maxElementsInMemory="10000"
            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"
            overflowToDisk="true"            diskPersistent="false"           diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"/>

<cache name="cn.hnisi.persistence.mmedia.Dmtjbxx"
               maxElementsInMemory="500"               eternal="false"
               timeToIdleSeconds="2400"      timeToLiveSeconds="3600"
               overflowToDisk="false"/>

<cache name="org.hibernate.cache.StandardQueryCache"
        maxElementsInMemory="50" eternal="false" timeToIdleSeconds="600"
        timeToLiveSeconds="1200" overflowToDisk="false"/>

<cache name="org.hibernate.cache.UpdateTimestampsCache"
        maxElementsInMemory="500" eternal="true" overflowToDisk="false"/>

</ehcache>
然后你可以用HQL查询对象了,比如"from A where name=Q?Q?/p>

跟踪查询的sql日志可以看出第一ơ是查询数据库,W二ơ是从缓存中get(见Hibernate ReadWriteCachecȝgetҎ(gu)Q?/p>

问题Q什么样的数据适合存放到第二~存中?

1 很少被修改的数据
2 不是很重要的数据Q允许出现偶ƈ发的数据
3 不会被ƈ发访问的数据
4 参考数?指的是供应用参考的帔R数据Q它的实例数目有限,它的实例会被许多其他cȝ实例引用Q实例极或者从来不会被修改?/p>


本文来自CSDN博客Q{载请标明出处Q?a rel="nofollow">http://blog.csdn.net/selley/archive/2008/03/13/2177479.aspx



abin 2012-05-13 02:07 发表评论
]]>
HibernateTransactionManager ?hibernateTemplate的区?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2012/03/27/372857.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Tue, 27 Mar 2012 14:30:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2012/03/27/372857.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/372857.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2012/03/27/372857.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/372857.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/372857.html</trackback:ping><description><![CDATA[<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 20px/30px 'Microsoft YaHei'; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><a style="color: rgb(102,102,102); text-decoration: none" ><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"> <div id="wmqeeuq" class="bct fc05 fc11 nbw-blog ztag js-fs2"> <div> <p><span style="font-size: 18px">在applicationContext.xml中有如下配置Q?/span></p> <p><span style="font-size: 18px"><bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"><br />    <property name="sessionFactory"><br />       <ref bean="sessionFactory"/><br />    </property><br /></bean></span></p> <p><br /><span style="font-size: 18px">也可以:<br /><bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><br />    <property name="sessionFactory"><br />       <ref bean="sessionFactory"/><br />    </property><br /></bean></span></p> <p><span style="font-size: 18px">两种实现方式其实没有区别Q尤其是W二U不要自己去关闭sessionQsession在事务结束后都会自动关闭?但是一定要注意延迟加蝲的问题,当对象在session关闭前没有从数据库中取得Q而jsp中需要展C对象时Q会提示LazyInitializationExceptionQ你可以通过OpenSessionInViewFilter来保证gq加载不会出现错误,卻I<br /><filter><br />     <filter-name>opensession</filter-name><br />     <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class><br /></filter><br /><filter-mapping><br />     <filter-name>opensession</filter-name><br />     <url-pattern>*.do</url-pattern><br /></filter-mapping></span></p></div></div></span><br class="Apple-interchange-newline" /></a></span><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/372857.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2012-03-27 22:30 <a href="http://www.aygfsteel.com/stevenjohn/archive/2012/03/27/372857.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate泛型DAOQ结合spring模板支持Q?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2012/03/20/372320.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Tue, 20 Mar 2012 14:20:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2012/03/20/372320.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/372320.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2012/03/20/372320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/372320.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/372320.html</trackback:ping><description><![CDATA[<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(246,246,246); text-indent: 0px; font: 14px/21px simsun; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(73,73,73); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span">详细介绍 Hibernate 泛型 DAO 及其使用Ҏ(gu)<br />~写Spring+Hibernate框架下的应用QLM了编写一个通用的泛型GenericHibernateDao。查阅了|上不少的GenericHibernateDao实现Q归Ux理ؓ如下实现Q供后箋~码参考?br /><br />首先定义接口泛型DAO接口 GenericDao<br /><br />package com.th.huz;<br /><br />import java.io.Serializable;<br />import java.util.Collection;<br />import java.util.Iterator;<br />import java.util.List;<br />import org.hibernate.Criteria;<br />import org.hibernate.LockMode;<br />import org.hibernate.criterion.DetachedCriteria;<br /><br /><br />public interface GenericDao<T extends Serializable, PK extends Serializable> {<br />// -------------------- 基本索、增加、修攏V删除操?--------------------<br /><br />// Ҏ(gu)主键获取实体。如果没有相应的实体Q返?null?br />public T get(PK id);<br /><br />// Ҏ(gu)主键获取实体q加锁。如果没有相应的实体Q返?null?br />public T getWithLock(PK id, LockMode lock);<br /><br />// Ҏ(gu)主键获取实体。如果没有相应的实体Q抛出异常?br />public T load(PK id);<br /><br />// Ҏ(gu)主键获取实体q加锁。如果没有相应的实体Q抛出异常?br />public T loadWithLock(PK id, LockMode lock);<br /><br />// 获取全部实体?br />public List<T> loadAll();<br /><br />// loadAllWithLock() ?<br /><br />// 更新实体<br />public void update(T entity);<br /><br />// 更新实体q加?br />public void updateWithLock(T entity, LockMode lock);<br /><br />// 存储实体到数据库<br />public void save(T entity);<br /><br />// saveWithLock()<br /><br />// 增加或更新实?br />public void saveOrUpdate(T entity);<br /><br />// 增加或更新集合中的全部实?br />public void saveOrUpdateAll(Collection<T> entities);<br /><br />// 删除指定的实?br />public void delete(T entity);<br /><br />// 加锁q删除指定的实体<br />public void deleteWithLock(T entity, LockMode lock);<br /><br />// Ҏ(gu)主键删除指定实体<br />public void deleteByKey(PK id);<br /><br />// Ҏ(gu)主键加锁q删除指定的实体<br />public void deleteByKeyWithLock(PK id, LockMode lock);<br /><br />// 删除集合中的全部实体<br />public void deleteAll(Collection<T> entities);<br /><br />// -------------------- HSQL ----------------------------------------------<br /><br />// 使用HSQL语句直接增加、更新、删除实?br />public int bulkUpdate(String queryString);<br /><br />// 使用带参数的HSQL语句增加、更新、删除实?br />public int bulkUpdate(String queryString, Object[] values);<br /><br />// 使用HSQL语句索数?br />public List find(String queryString);<br /><br />// 使用带参数的HSQL语句索数?br />public List find(String queryString, Object[] values);<br /><br />// 使用带命名的参数的HSQL语句索数?br />public List findByNamedParam(String queryString, String[] paramNames,<br />Object[] values);<br /><br />// 使用命名的HSQL语句索数?br />public List findByNamedQuery(String queryName);<br /><br />// 使用带参数的命名HSQL语句索数?br />public List findByNamedQuery(String queryName, Object[] values);<br /><br />// 使用带命名参数的命名HSQL语句索数?br />public List findByNamedQueryAndNamed<wbr>Param(String queryName,<br />String[] paramNames, Object[] values);<br /><br />// 使用HSQL语句索数据,q回 Iterator<br />public Iterator iterate(String queryString);<br /><br />// 使用带参数HSQL语句索数据,q回 Iterator<br />public Iterator iterate(String queryString, Object[] values);<br /><br />// 关闭索返回的 Iterator<br />public void closeIterator(Iterator it);<br /><br />// -------------------------------- Criteria ------------------------------<br /><br />// 创徏与会话无关的索标准对?br />public DetachedCriteria createDetachedCriteria();<br /><br />// 创徏与会话绑定的索标准对?br />public Criteria createCriteria();<br /><br />// 使用指定的检索标准检索数?br />public List findByCriteria(DetachedCriteria criteria);<br /><br />// 使用指定的检索标准检索数据,q回部分记录<br />public List findByCriteria(DetachedCriteria criteria, int firstResult,<br />int maxResults);<br /><br />// 使用指定的实体及属性检索(满除主键外属性=实体|数据<br />public List<T> findEqualByEntity(T entity, String[] propertyNames);<br /><br />// 使用指定的实体及属?非主?索(满属?like 串实体|数据<br />public List<T> findLikeByEntity(T entity, String[] propertyNames);<br /><br />// 使用指定的检索标准检索数据,q回指定范围的记?br />public Integer getRowCount(DetachedCriteria criteria);<br /><br />// 使用指定的检索标准检索数据,q回指定l计?br />public Object getStatValue(DetachedCriteria criteria, String propertyName,<br />String StatName);<br /><br />// -------------------------------- Others --------------------------------<br /><br />// 加锁指定的实?br />public void lock(T entity, LockMode lockMode);<br /><br />// 强制初始化指定的实体<br />public void initialize(Object proxy);<br /><br />// 强制立即更新~冲数据到数据库Q否则仅在事务提交时才更斎ͼ<br />public void flush();<br /><br />}<br /><br />实现GenericDao接口的Hibernate的实现类 GenericHibernateDao<br /><br />package com.th.huz;<br /><br />import java.io.Serializable;<br />import java.lang.reflect.ParameterizedType;<br />import java.lang.reflect.Type;<br />import java.util.Collection;<br />import java.util.Iterator;<br />import java.util.List;<br />import org.apache.commons.beanutils.PropertyUtils;<br />import org.hibernate.Criteria;<br />import org.hibernate.LockMode;<br />import org.hibernate.criterion.DetachedCriteria;<br />import org.hibernate.criterion.Example;<br />import org.hibernate.criterion.MatchMode;<br />import org.hibernate.criterion.Order;<br />import org.hibernate.criterion.Projections;<br />import org.hibernate.criterion.Restrictions;<br />import org.springframework.orm.hibernate3.support.HibernateDaoSupport;<br /><br /><br />@SuppressWarnings("unchecked")<br />public class GenericHibernateDao<T extends Serializable, PK extends Serializable><br />extends HibernateDaoSupport implements GenericDao<T, PK> {<br />// 实体cȝ?由构造方法自动赋?<br />private Class<T> entityClass;<br /><br />// 构造方法,Ҏ(gu)实例c自动获取实体类cd<br />public GenericHibernateDao() {<br />this.entityClass = null;<br />Class c = getClass();<br />Type t = c.getGenericSuperclass();<br />if (t instanceof ParameterizedType) {<br />Type[] p = ((ParameterizedType) t).getActualTypeArguments();<br />this.entityClass = (Class<T>) p[0];<br />}<br />}<br /><br />// -------------------- 基本索、增加、修攏V删除操?--------------------<br /><br />// Ҏ(gu)主键获取实体。如果没有相应的实体Q返?null?br />public T get(PK id) {<br />return (T) getHibernateTemplate().get(entityClass, id);<br />}<br /><br />// Ҏ(gu)主键获取实体q加锁。如果没有相应的实体Q返?null?br />public T getWithLock(PK id, LockMode lock) {<br />T t = (T) getHibernateTemplate().get(entityClass, id, lock);<br />if (t != null) {<br />this.flush(); // 立即hQ否则锁不会生效?br />}<br />return t;<br />}<br /><br />// Ҏ(gu)主键获取实体。如果没有相应的实体Q抛出异常?br />public T load(PK id) {<br />return (T) getHibernateTemplate().load(entityClass, id);<br />}<br /><br />// Ҏ(gu)主键获取实体q加锁。如果没有相应的实体Q抛出异常?br />public T loadWithLock(PK id, LockMode lock) {<br />T t = (T) getHibernateTemplate().load(entityClass, id, lock);<br />if (t != null) {<br />this.flush(); // 立即hQ否则锁不会生效?br />}<br />return t;<br />}<br /><br />// 获取全部实体?br />public List<T> loadAll() {<br />return (List<T>) getHibernateTemplate().loadAll(entityClass);<br />}<br /><br />// loadAllWithLock() ?<br /><br />// 更新实体<br />public void update(T entity) {<br />getHibernateTemplate().update(entity);<br />}<br /><br />// 更新实体q加?br />public void updateWithLock(T entity, LockMode lock) {<br />getHibernateTemplate().update(entity, lock);<br />this.flush(); // 立即hQ否则锁不会生效?br />}<br /><br />// 存储实体到数据库<br />public void save(T entity) {<br />getHibernateTemplate().save(entity);<br />}<br /><br />// saveWithLock()Q?br /><br />// 增加或更新实?br />public void saveOrUpdate(T entity) {<br />getHibernateTemplate().saveOrUpdate(entity);<br />}<br /><br />// 增加或更新集合中的全部实?br />public void saveOrUpdateAll(Collection<T> entities) {<br />getHibernateTemplate().saveOrUpdateAll(entities);<br />}<br /><br />// 删除指定的实?br />public void delete(T entity) {<br />getHibernateTemplate().delete(entity);<br />}<br /><br />// 加锁q删除指定的实体<br />public void deleteWithLock(T entity, LockMode lock) {<br />getHibernateTemplate().delete(entity, lock);<br />this.flush(); // 立即hQ否则锁不会生效?br />}<br /><br />// Ҏ(gu)主键删除指定实体<br />public void deleteByKey(PK id) {<br />this.delete(this.load(id));<br />}<br /><br />// Ҏ(gu)主键加锁q删除指定的实体<br />public void deleteByKeyWithLock(PK id, LockMode lock) {<br />this.deleteWithLock(this.load(id), lock);<br />}<br /><br />// 删除集合中的全部实体<br />public void deleteAll(Collection<T> entities) {<br />getHibernateTemplate().deleteAll(entities);<br />}<br /><br />// -------------------- HSQL ----------------------------------------------<br /><br />// 使用HSQL语句直接增加、更新、删除实?br />public int bulkUpdate(String queryString) {<br />return getHibernateTemplate().bulkUpdate(queryString);<br />}<br /><br />// 使用带参数的HSQL语句增加、更新、删除实?br />public int bulkUpdate(String queryString, Object[] values) {<br />return getHibernateTemplate().bulkUpdate(queryString, values);<br />}<br /><br />// 使用HSQL语句索数?br />public List find(String queryString) {<br />return getHibernateTemplate().find(queryString);<br />}<br /><br />// 使用带参数的HSQL语句索数?br />public List find(String queryString, Object[] values) {<br />return getHibernateTemplate().find(queryString, values);<br />}<br /><br />// 使用带命名的参数的HSQL语句索数?br />public List findByNamedParam(String queryString, String[] paramNames,<br />Object[] values) {<br />return getHibernateTemplate().findByNamedParam(queryString, paramNames,<br />values);<br />}<br /><br />// 使用命名的HSQL语句索数?br />public List findByNamedQuery(String queryName) {<br />return getHibernateTemplate().findByNamedQuery(queryName);<br />}<br /><br />// 使用带参数的命名HSQL语句索数?br />public List findByNamedQuery(String queryName, Object[] values) {<br />return getHibernateTemplate().findByNamedQuery(queryName, values);<br />}<br /><br />// 使用带命名参数的命名HSQL语句索数?br />public List findByNamedQueryAndNamed<wbr>Param(String queryName,<br />String[] paramNames, Object[] values) {<br />return getHibernateTemplate().findByNamedQueryAndNamed<wbr>Param(queryName,<br />paramNames, values);<br />}<br /><br />// 使用HSQL语句索数据,q回 Iterator<br />public Iterator iterate(String queryString) {<br />return getHibernateTemplate().iterate(queryString);<br />}<br /><br />// 使用带参数HSQL语句索数据,q回 Iterator<br />public Iterator iterate(String queryString, Object[] values) {<br />return getHibernateTemplate().iterate(queryString, values);<br />}<br /><br />// 关闭索返回的 Iterator<br />public void closeIterator(Iterator it) {<br />getHibernateTemplate().closeIterator(it);<br />}<br /><br />// -------------------------------- Criteria ------------------------------<br /><br />// 创徏与会话无关的索标?br />public DetachedCriteria createDetachedCriteria() {<br />return DetachedCriteria.forClass(this.entityClass);<br />}<br /><br />// 创徏与会话绑定的索标?br />public Criteria createCriteria() {<br />return this.createDetachedCriteria().getExecutableCriteria(<br />this.getSession());<br />}<br /><br />// 索满x准的数据<br />public List findByCriteria(DetachedCriteria criteria) {<br />return getHibernateTemplate().findByCriteria(criteria);<br />}<br /><br />// 索满x准的数据Q返回指定范围的记录<br />public List findByCriteria(DetachedCriteria criteria, int firstResult,<br />int maxResults) {<br />return getHibernateTemplate().findByCriteria(criteria, firstResult,<br />maxResults);<br />}<br /><br />// 使用指定的实体及属性检索(满除主键外属性=实体|数据<br />public List<T> findEqualByEntity(T entity, String[] propertyNames) {<br />Criteria criteria = this.createCriteria();<br />Example exam = Example.create(entity);<br />exam.excludeZeroes();<br />String[] defPropertys = getSessionFactory().getClassMetadata(<br />entityClass).getPropertyNames();<br />for (String defProperty : defPropertys) {<br />int ii = 0;<br />for (ii = 0; ii < propertyNames.length; ++ii) {<br />if (defProperty.equals(propertyNames[ii])) {<br />criteria.addOrder(Order.asc(defProperty));<br />break;<br />}<br />}<br />if (ii == propertyNames.length) {<br />exam.excludeProperty(defProperty);<br />}<br />}<br />criteria.add(exam);<br />return (List<T>) criteria.list();<br />}<br /><br />// 使用指定的实体及属性检索(满属?like 串实体|数据<br />public List<T> findLikeByEntity(T entity, String[] propertyNames) {<br />Criteria criteria = this.createCriteria();<br />for (String property : propertyNames) {<br />try {<br />Object value = PropertyUtils.getProperty(entity, property);<br />if (value instanceof String) {<br />criteria.add(Restrictions.like(property, (String) value,<br />MatchMode.ANYWHERE));<br />criteria.addOrder(Order.asc(property));<br />} else {<br />criteria.add(Restrictions.eq(property, value));<br />criteria.addOrder(Order.asc(property));<br />}<br />} catch (Exception ex) {<br />// 忽略无效的检索参考数据?br />}<br />}<br />return (List<T>) criteria.list();<br />}<br /><br />// 使用指定的检索标准获取满x准的记录?br />public Integer getRowCount(DetachedCriteria criteria) {<br />criteria.setProjection(Projections.rowCount());<br />List list = this.findByCriteria(criteria, 0, 1);<br />return (Integer) list.get(0);<br />}<br /><br />// 使用指定的检索标准检索数据,q回指定l计?max,min,avg,sum)<br />public Object getStatValue(DetachedCriteria criteria, String propertyName,<br />String StatName) {<br />if (StatName.toLowerCase().equals("max"))<br />criteria.setProjection(Projections.max(propertyName));<br />else if (StatName.toLowerCase().equals("min"))<br />criteria.setProjection(Projections.min(propertyName));<br />else if (StatName.toLowerCase().equals("avg"))<br />criteria.setProjection(Projections.avg(propertyName));<br />else if (StatName.toLowerCase().equals("sum"))<br />criteria.setProjection(Projections.sum(propertyName));<br />else<br />return null;<br />List list = this.findByCriteria(criteria, 0, 1);<br />return list.get(0);<br />}<br /><br />// -------------------------------- Others --------------------------------<br /><br />// 加锁指定的实?br />public void lock(T entity, LockMode lock) {<br />getHibernateTemplate().lock(entity, lock);<br />}<br /><br />// 强制初始化指定的实体<br />public void initialize(Object proxy) {<br />getHibernateTemplate().initialize(proxy);<br />}<br /><br />// 强制立即更新~冲数据到数据库Q否则仅在事务提交时才更斎ͼ<br />public void flush() {<br />getHibernateTemplate().flush();<br />}<br />}<br />//以上代码来自|上攉<br /><br /><br />以上实C泛型?Hibernate Dao 了,下面的例子就是业务对象对 GenericHibernateDao的?br /><br />业务对象 Article 对应文章表的 aticle ?br /><br />package com.th.huz.model;<br /><br />import java.io.Serializable;<br />import java.util.Date;<br /><br />public class Article implements Serializable {<br /><br />private static final long serialVersionUID = 1072812006693587010L;<br /><br />private long id;<br />private String title;<br />private String author;<br />private Date pubDate;<br />private String content;<br /><br />public long getId() {<br />return id;<br />}<br /><br />public void setId(long id) {<br />this.id = id;<br />}<br /><br />public String getTitle() {<br />return title;<br />}<br /><br />public void setTitle(String title) {<br />this.title = title;<br />}<br /><br />public String getAuthor() {<br />return author;<br />}<br /><br />public void setAuthor(String author) {<br />this.author = author;<br />}<br /><br />public Date getPubDate() {<br />return pubDate;<br />}<br /><br />public void setPubDate(Date pubDate) {<br />this.pubDate = pubDate;<br />}<br /><br />public String getContent() {<br />return content;<br />}<br /><br />public void setContent(String content) {<br />this.content = content;<br />}<br />}<br /><br /><br /><br /><br />定义 Article 业务对象的Dao 接口 IArticleDao Q它l承?GenericDao 接口Q以获得其中的方?br /><br />你可以在 IArticleDao 中添?Article 业务对象Ҏ(gu)的方法,也可以直接?GenericDao 中提供的所有方法IArticleDao接口指定业务对象的类型和主键的类?<Article,Long><br /><br />package com.th.huz.model;<br /><br />import com.th.huz.dao.GenericDao;<br />import com.th.huz.model.Article;<br />public interface IArticleDAO extends GenericDao <Article,Long> {<br />// public void findById(Long id);<br />}<br />然后可以定?ArticleHibernateDao cMQ它只要实现 IArticleDao 接口q?GenericHibernateDao c?可以用所有的 Generic 接口?IArticleDao 接口中的定义的方法。如果你?IArticleDao 接口里指定了Article业务对象Ҏ(gu)的方法,在ArticleHibernateDao实现q些Ҏ(gu)。而Generic 接口中的Ҏ(gu)Q在ArticleHibernateDao 的父c?GenericHibernateDao 中已l全部实CQ直接调用就可以方便的访问数据库?br /><br />package com.th.huz.model;<br /><br />import com.th.huz.dao.GenericHibernateDao;<br /><br />public class ArticleHibernateDao extends GenericHibernateDao<Article,Long> implements<br />IArticleDAO {<br /><br />}<br />其他的业务对象也可以参照 Article ?ArticleHibernateDao cL定义 Q?GenericDao 接口中有的通用Ҏ(gu)q接调用,不的以后补充,其他业务对象Ҏ(gu)的方法就 在其他业务对象的 Dao接口(l承GenericDao接口) 中定义ƈ通过 GenericHibernateDao 子类来实现?节省很多重复代码Q简单几步就可以使用GenericDao接口的实现类 GenericHibernateDao 方便地访问数据库?br /><br />最后提供一?Article 业务对象?Hibernate 映射文g ?SQL脚本 ?一?ArticleHibernateDao cȝ试c?br /><br />Article的映文?br /><br /><?xml version="1.0"?><br /><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><br /><!-- Article.hbm.xml --><br /><hibernate-mapping><br /><class name="com.th.huz.model.Article" table="article"><br /><id name="id" type="java.lang.Long"><br /><column name="id" /><br /><generator class="native" /><br /></id><br /><property name="title" type="java.lang.String"><br /><column name="title" length="100" /><br /></property><br /><property name="author"><br /><column name="author" length="32" /><br /></property><br /><property name="pubDate" type="java.util.Date"><br /><column name="pubDate" /><br /></property><br /><property name="content" type="java.lang.String"><br /><column name="content" /><br /></property><br /></class><br /></hibernate-mapping><br />Article对应的article表的脚本<br /><br />if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[article]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)<br />drop table [dbo].[article]<br />GO<br /><br />CREATE TABLE [dbo].[article] (<br />[id] [int] IDENTITY (1, 1) NOT NULL ,<br />[title] [varchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL ,<br />[author] [varchar] (32) COLLATE Chinese_PRC_CI_AS NULL ,<br />[pubDate] [datetime] NULL ,<br />[content] [text] COLLATE Chinese_PRC_CI_AS NULL<br />) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]<br />GO<br />ArticleHibernateDao的测试类Q只提供了seve(article) Ҏ(gu)的测试代?br /><br />package com.th.huz.test;<br /><br />import junit.framework.TestCase;<br /><br />import org.springframework.context.ApplicationContext;<br />import org.springframework.context.support.ClassPathXmlApplicationC<wbr>ontext;<br /><br />import com.th.huz.model.Article;<br />import com.th.huz.model.ArticleHibernateDao;<br /><br />public class ArticleHibernateDaoTest extends TestCase {<br /><br />ApplicationContext ctx = new ClassPathXmlApplicationC<wbr>ontext(<br />"applicationContext.xml");<br />ArticleHibernateDao adh = (ArticleHibernateDao) ctx<br />.getBean("articleHibernateDao");<br /><br />public void testSave() {<br />Article art = (Article) ctx.getBean("article");<br />art.setId(1);<br />art.setTitle("标题1");<br />art.setAuthor("作?");<br />adh.save(art);<br />}<br />}</span><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/372320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2012-03-20 22:20 <a href="http://www.aygfsteel.com/stevenjohn/archive/2012/03/20/372320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate一U缓存和二~存的区?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371691.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sun, 11 Mar 2012 14:25:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371691.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/371691.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371691.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/371691.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/371691.html</trackback:ping><description><![CDATA[<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">   ~存是介于应用程序和物理数据源之_其作用是Z降低应用E序对物理数据源讉K的频ơ,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复Ӟ应用E序在运行时从缓存读写数据,在特定的时刻或事件会同步~存和物理数据源的数据?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  ~存的介质一般是内存Q所以读写速度很快。但如果~存中存攄数据量非常大Ӟ也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,q要考虑到管理缓存的q发讉K和缓存数据的生命周期?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分ؓ两类Q内|缓存和外置~存。Session的缓存是内置的,不能被卸载,也被UCؓHibernate的第一U缓存。SessionFactory的内|缓存和Session的缓存在实现方式上比较相|前者是SessionFactory对象的一些集合属性包含的数据Q后者是指Session的一些集合属性包含的数据。SessionFactory的内|缓存中存放了映元数据和预定义SQL语句Q映元数据是映文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶D|据映元数据推导出来QSessionFactory的内|缓存是只读的,应用E序不能修改~存中的映射元数据和预定义SQL语句Q因此SessionFactory不需要进行内|缓存与映射文g的同步。SessionFactory的外|缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用q个插g。外|缓存的数据是数据库数据的拷贝,外置~存的介质可以是内存或者硬盘。SessionFactory的外|缓存也被称为Hibernate的第二~存?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  Hibernate的这两~存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢Qؓ了理解二者的区别Q需要深入理解持久化层的~存的两个特性:~存的范围和~存的ƈ发访问策略?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  持久化层的缓存的范围</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  ~存的范围决定了~存的生命周期以及可以被谁访问。缓存的范围分ؓ三类?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  1 事务范围Q缓存只能被当前事务讉K。缓存的生命周期依赖于事务的生命周期Q当事务l束Ӟ~存也就l束生命周期。在此范围下Q缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,~存内的数据通常采用怺兌的的对象形式?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  2 q程范围Q缓存被q程内的所有事务共享。这些事务有可能是ƈ发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进E的生命周期Q进E结束时Q缓存也q束了生命周期。进E范围的~存可能会存攑֤量的数据Q所以存攄介质可以是内存或盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据Ş式。松散的对象数据形式有点cM于对象的序列化数据,但是对象分解为松散的法比对象序列化的算法要求更快?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  3 集群范围Q在集群环境中,~存被一个机器或者多个机器的q程׃n。缓存中的数据被复制到集环境中的每个进E节点,q程间通过q程通信来保证缓存中的数据的一致性,~存中的数据通常采用对象的松散数据Ş式?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  对大多数应用来说Q应该慎重地考虑是否需要用集范围的~存Q因问的速度不一定会比直接访问数据库数据的速度快多?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,q可以到q程范围或集范围的~存内查询,如果q是没有查到Q那么只有到数据库中查询。事务范围的~存是持久化层的W一U缓存,通常它是必需的;q程范围或集范围的~存是持久化层的W二U缓存,通常是可选的?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  持久化层的缓存的q发讉K{略</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  当多个ƈ发的事务同时讉K持久化层的缓存的相同数据Ӟ会引起ƈ发问题,必须采用必要的事务隔L施?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  在进E范围或集群范围的缓存,即第二~存Q会出现q发问题。因此可以设定以下四U类型的q发讉K{略Q每一U策略对应一U事务隔ȝ别?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  事务型:仅仅在受理环境中适用。它提供了Repeatable Read事务隔离U别。对于经常被M很少修改的数据,可以采用q种隔离cdQ因为它可以防止脏读和不可重复读q类的ƈ发问题?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  d型:提供了Read Committed事务隔离U别。仅仅在非集的环境中适用。对于经常被M很少修改的数据,可以采用q种隔离cdQ因为它可以防止脏读q类的ƈ发问题?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  非严D写型Q不保证~存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须数据配置一个很短的数据q期旉Q从而尽量避免脏诅R对于极被修改Qƈ且允许偶脏ȝ数据Q可以采用这Uƈ发访问策略?  只读型:对于从来不会修改的数据,如参考数据,可以使用q种q发讉K{略?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  事务型ƈ发访问策略是事务隔离U别最高,只读型的隔离U别最低。事务隔ȝ别越高,q发性能p低?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  什么样的数据适合存放到第二~存中?</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  1、很被修改的数?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  2、不是很重要的数据,允许出现偶尔q发的数?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  3、不会被q发讉K的数?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  4、参考数?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  不适合存放到第二~存的数据?</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  1、经常被修改的数?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  2、胦务数据,l对不允许出现ƈ?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  3、与其他应用׃n的数据?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  Hibernate的二U缓?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  如前所qͼHibernate提供了两U缓存,W一U是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的~存是事务范围的~存。第一U缓存是必需的,不允许而且事实上也无法比卸除。在W一U缓存中Q持久化cȝ每个实例都具有唯一的OID?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  W二U缓存是一个可插拔的的~存插gQ它是由SessionFactory负责理。由于SessionFactory对象的生命周期和应用E序的整个过E对应,因此W二U缓存是q程范围或者集范围的~存。这个缓存中存放的对象的松散数据。第二对象有可能出现ƈ发问题,因此需要采用适当的ƈ发访问策略,该策略ؓ被缓存的数据提供了事务隔ȝ别。缓存适配器用于把具体的缓存实现Y件与Hibernate集成。第二~存是可选的Q可以在每个cL每个集合的粒度上配置W二U缓存?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  Hibernate的二U缓存策略的一般过E如下:</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  1) 条g查询的时候,L发出一条select * from table_name where …. Q选择所有字D)q样的SQL语句查询数据库,一ơ获得所有的数据对象?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  2) 把获得的所有数据对象根据ID攑օ到第二~存中?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  3) 当HibernateҎ(gu)ID讉K数据对象的时候,首先从Session一U缓存中查;查不刎ͼ如果配置了二U缓存,那么从二U缓存中查;查不刎ͼ再查询数据库Q把l果按照ID攑օ到缓存?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  4) 删除、更新、增加数据的时候,同时更新~存?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  Hibernate的二U缓存策略,是针对于ID查询的缓存策略,对于条g查询则毫无作用。ؓ此,Hibernate提供了针Ҏ(gu)件查询的Query~存?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  Hibernate的Query~存{略的过E如下:</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  1) Hibernate首先Ҏ(gu)q些信息l成一个Query KeyQQuery Key包括条g查询的请求一般信息:SQL, SQL需要的参数Q记录范_起始位置rowStartQ最大记录个数maxRows)Q等?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  2) HibernateҎ(gu)q个Query Key到Query~存中查扑֯应的l果列表。如果存在,那么q回q个l果列表Q如果不存在Q查询数据库Q获取结果列表,把整个结果列表根据Query Key攑օ到Query~存中?/p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">  3) Query Key中的SQL涉及C些表名,如果q些表的M数据发生修改、删除、增加等操作Q这些相关的Query Key都要从缓存中清空?/p></span><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/371691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2012-03-11 22:25 <a href="http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HibernateU联保存和更?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371677.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sun, 11 Mar 2012 08:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371677.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/371677.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371677.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/371677.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/371677.html</trackback:ping><description><![CDATA[来源Qhttp://www.tianxiaboke.com/u/lyeerwy<br /> <p><strong><font color="#ff0000">U联保存和更?/font></strong><br />当Hibernate持久化一个时对象时Q在默认情下Q他不会自动持久化所兌的其他时对象,如果希望当持久化对象时把他所兌的所有时对象进行持久化的话Q可以把 <many-to-one></many-to-one>的cascade属性设|ؓ"save-update" ,cascade的默认属性gؓnone?br />cascade:讄操作对象时的U联操作Q即层之间的连锁操?br />?nbsp;save-update Q表C当保存和更新当前对?即insert和update语句?Q会U联保存和更C他关联的对象<br />?nbsp;all Q表CZQ何情况下都会q行U联操作Q即对一个对象进行操作,也会对和他关联的其他对象q行同样的操?br />?nbsp;delete Q表C在执行deleteӞq行U联操作Q删除和他关联的对象<br />?nbsp;none Q表CZQ何情况下Q都不会q行U联操作<br /><strong><font color="#0000ff"><set>元素的inverse属?/font></strong></p> <p>在运行上面的E序Ӟ如果hibernate?show-sql"讄为trueӞ׃看到Hibernate会生成很多sql语句Q其实很多sql语句都是重复?br />egQ?nbsp;<br />insert into  test.order(o_name,c_id)values(?,?)<br />insert into  test.order(o_name,c_id)values(?,?)<br />insert into  test order   set c_id=? where id=?<br />insert into  test order   set c_id=? where id=?</p> <p>Z解决q个问题Q我们可以利用在<set>标签中加上inverse属性。术语:inverse是指反{的意思,?Hibernate中,表示兌关系中的方向兌关系中,inverse="false"的主控方Q由d方负责维护对象关pL?nbsp;在customer对象的对象配|文件中加上</p> <p><set name="orders"  cascade="save-update" inverse="true"><br /><key  column="c_id" > </key><br /><one-to-many class="net.mbs.mypack.Order " /><br /></set></p> <p>声明在Customer和Order的双向关联关pMQCustomer端的兌只是Order端关联的镜象Q即Order端是ȝ端,负责l护 Customer和order对象之间的关联关p)Q当hibernate探测到持久化对象Customer或Order的状态发生变化时(主要是关联关pȝ改变),仅按照Order对象的状态的变化来同步更新数据库?br />按次配置Q如果在E序中,我们仅仅使用Customer.getOrder().add(order)Q涉及了和Order的关联关pȝ改变Q,是不能让数据库跟对象的变化来q行数据库同步更新的Q只有利用Order对象的方法改变的Order对象状?(egQorder.setCustomer(customer)----涉及C和Customer的关联关pȝ改变)Ӟ数据库才会根据变化来同步更新数据库,卛_有主控方的状态(涉及C和另一斚w的关联关pȝ改变Q发生了变化后,才会触发对象和数据库的同步更新?/p> <p><strong><font color="#0000ff">映射一对多双向兌关系<br /></font></strong>当类与类之间建立了关联,可以方便的从一个对象导航到另一个对象或一l与他关联的对象当中Q根据上面的E序Q对于一个给定的Order对象Q如果想获取与他兌的Customer对象Q我们只需要调用入下方法:<br />Customer c=order.geCustomer(); 那么当我们得C个Customer对象后,x出和q个Customer对象兌的所有Order对象Ӟ应该怎么办呢Q由于在Customer中没有徏立对Order对象的关联,所以,不能通过加蝲Customer对象来自动加载和他关联的所有Order对象Q唯一的方法只能通过JDBC或SQL语言人工写出代码来查询数据库Order表来q回所需要的信息<br />上面的问题虽然解冻I但不能算是最好,因ؓq样性能会有所下降Q对象位于内存中Q在内存中从一个对象导航到另一个对象显然比到数据库中查询数据要快得?br /></p> <p>具体实现<br><br />1Q由于Customer和Order是一对多Q即一个Customer要对应多个OrderQ所以在Customer中应该徏立一个Set对象Q用于存攑֒本Customer对象兌的所有Order对象?br />2Q在customer.hbm.xml通过<one-to-many>建立对Order表的兌关系<br />注意Q?lt;one-to-many>应该攄?lt;set>标签?nbsp;<br />我们先来看看Customercȝ设计和customer.hbm.xml文g的内?br /><br><br><br>------------------------------------------------------<br /><font color="#0000ff">Customer Order 双向一对多</font><br />1QCustomercM建立一个容器对象,包含兌的所有Order对象<br />2QOrdercM建立一个Customer对象Q关联Customer<br />inverse="true"表示维护关联的权利交给引vHibernate语句的生?/p> <p>customer.getOrders().add(order);<br />customer.setName("dddddd");<br /><br />inverse="true"Q设|此属性的一?---是被控方Q?br />当主控方修改对象之间的关联关pLQ让Hibernate生成sql语句</p><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/371677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2012-03-11 16:36 <a href="http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>5个最帔R的几个Hibernate面试问题http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371676.htmlabinabinSun, 11 Mar 2012 07:34:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371676.htmlhttp://www.aygfsteel.com/stevenjohn/comments/371676.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371676.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/371676.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/371676.html
1.实体对象在Hibernate中如何进行状态迁U?
2.何谓Hibernate的N+1问题Q如何解冻I
3.Hibernate延迟加蝲的机制是什么,如何工作Q?
4.HibernateU联保存要如何做Q?
5.Hibernate的二U缓存和一U缓存有什么区别?


abin 2012-03-11 15:34 发表评论
]]>
Hibernate延迟加蝲机制http://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371675.htmlabinabinSun, 11 Mar 2012 07:32:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371675.htmlhttp://www.aygfsteel.com/stevenjohn/comments/371675.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/03/11/371675.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/371675.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/371675.html

延迟加蝲Q?/p>

   延迟加蝲机制是ؓ了避免一些无谓的性能开销而提出来的,所谓gq加载就是当在真正需要数据的时候,才真正执行数据加载操作。在Hibernate中提供了对实体对象的延迟加蝲以及寚w合的延迟加蝲Q另外在Hibernate3中还提供了对属性的延迟加蝲。下面我们就分别介绍q些U类的gq加载的l节?/p>

A、实体对象的延迟加蝲Q?/p>

如果惛_实体对象使用延迟加蝲Q必要在实体的映射配置文g中进行相应的配置Q如下所C:

<hibernate-mapping>

<class name=”com.neusoft.entity.User” table=”user” lazy=”true”>

    ……

</class>

</hibernate-mapping>

通过class的lazy属性设|ؓtrueQ来开启实体的延迟加蝲Ҏ(gu)。如果我们运行下面的代码Q?/p>

User user=(User)session.load(User.class,”1”);Q?Q?/p>

System.out.println(user.getName());Q?Q?/p>

当运行到(1)处时QHibernateq没有发起对数据的查询,如果我们此时通过一些调试工?比如JBuilder2005的Debug工具)Q观察此时user对象的内存快照,我们会惊奇的发现Q此时返回的可能是User$EnhancerByCGLIB$$bede8986cd的对象,而且其属性ؓ null,q是怎么回事Q还记得前面我曾讲过session.load()Ҏ(gu)Q会q回实体对象的代理类对象Q这里所q回的对象类型就是User对象的代理类对象。在Hibernate中通过使用CGLIB,来实现动态构造一个目标对象的代理cd象,q且在代理类对象中包含目标对象的所有属性和Ҏ(gu)Q而且所有属性均被赋gؓnull。通过调试器显C的内存快照Q我们可以看出此时真正的User对象Q是包含在代理对象的 CGLIB$CALBACK_0.target属性中Q当代码q行刎ͼ2Q处Ӟ此时调用user.getName()Ҏ(gu)Q这旉过CGLIB赋予的回调机Ӟ实际上调用CGLIB$CALBACK_0.getName()Ҏ(gu)Q当调用该方法时QHibernate会首先检?CGLIB$CALBACK_0.target属性是否ؓnullQ如果不为空Q则调用目标对象的getNameҎ(gu)Q如果ؓI,则会发v数据库查询,生成cMq样的SQL语句Qselect * from user where id=’1’;来查询数据,q构造目标对象,q且它赋值到CGLIB$CALBACK_0.target属性中?/p>

    q样Q通过一个中间代理对象,Hibernate实现了实体的延迟加蝲Q只有当用户真正发v获得实体对象属性的动作Ӟ才真正会发v数据库查询操作。所以实体的延迟加蝲是用通过中间代理cd成的Q所以只有session.load()Ҏ(gu)才会利用实体延迟加蝲Q因为只有session.load()Ҏ(gu)才会q回实体cȝ代理cd象?/p>

B?nbsp;       集合cd的gq加载:

在Hibernate的gq加载机制中Q针寚w合类型的应用Q意义是最为重大的Q因有可能性能得到大幅度的提高Qؓ此Hibernateq行了大量的努力Q其中包括对JDK Collection的独立实玎ͼ我们在一对多兌中,定义的用来容U_联对象的Set集合Qƈ不是java.util.Setcd或其子类型,而是 net.sf.hibernate.collection.SetcdQ通过使用自定义集合类的实玎ͼHibernate实现了集合类型的延迟加蝲。ؓ了对集合cd使用延迟加蝲Q我们必d下配|我们的实体cȝ关于兌的部分:

<hibernate-mapping>

    <class name=”com.neusoft.entity.User” table=”user”>

…..

<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

<key column=”user_id”/>

<one-to-many class=”com.neusoft.entity.Arrderss”/>

</set>

    </class>

</hibernate-mapping>

通过?lt;set>元素的lazy属性设|ؓtrue来开启集合类型的延迟加蝲Ҏ(gu)。我们看下面的代码:

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();       (1)

Iterator it=addset.iterator();                (2)

while(it.hasNext()){

Address address=(Address)it.next();

System.out.println(address.getAddress());

}

当程序执行到(1)处时Q这时ƈ不会发v对关联数据的查询来加载关联数据,只有q行?2)处时Q真正的数据d操作才会开始,q时Hibernate会根据缓存中W合条g的数据烦引,来查扄合条件的实体对象?/p>

q里我们引入了一个全新的概念——数据索引Q下面我们首先将接一下什么是数据索引。在Hibernate中对集合cdq行~存Ӟ是分两部分进行缓存的Q首先缓存集合中所有实体的id列表Q然后缓存实体对象,q些实体对象的id列表Q就是所谓的数据索引。当查找数据索引Ӟ如果没有扑ֈ对应的数据烦引,q时׃一条select SQL的执行,获得W合条g的数据,q构造实体对象集合和数据索引Q然后返回实体对象的集合Qƈ且将实体对象和数据烦引纳入Hibernate的缓存之中。另一斚wQ如果找到对应的数据索引Q则从数据烦引中取出id列表Q然后根据id在缓存中查找对应的实体,如果扑ֈ׃~存中返回,如果没有扑ֈQ在发vselect SQL查询。在q里我们看出了另外一个问题,q个问题可能会对性能产生影响Q这是集合cd的缓存策略。如果我们如下配|集合类型:

<hibernate-mapping>

    <class name=”com.neusoft.entity.User” table=”user”>

…..

<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

<cache usage=”read-only”/>

<key column=”user_id”/>

<one-to-many class=”com.neusoft.entity.Arrderss”/>

</set>

    </class>

</hibernate-mapping>

q里我们应用?lt;cache usage=”read-only”/>配置Q如果采用这U策略来配置集合cdQHibernate只会对数据索引q行~存Q而不会对集合中的实体对象q行~存。如上配|我们运行下面的代码Q?/p>

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();      

Iterator it=addset.iterator();               

while(it.hasNext()){

Address address=(Address)it.next();

System.out.println(address.getAddress());

}

System.out.println(“Second query……”);

User user2=(User)session.load(User.class,”1”);

Collection it2=user2.getAddresses();

while(it2.hasNext()){

Address address2=(Address)it2.next();

System.out.println(address2.getAddress());

}

q行q段代码Q会得到cM下面的输出:

Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Select * from address where id=’1’;

Select * from address where id=’2’;

Tianjin

Dalian

我们看到Q当W二ơ执行查询时Q执行了两条对address表的查询操作Qؓ什么会q样Q这是因为当W一ơ加载实体后Q根据集合类型缓存策略的配置Q只寚w合数据烦引进行了~存Q而ƈ没有寚w合中的实体对象进行缓存,所以在W二ơ再ơ加载实体时QHibernate扑ֈ了对应实体的数据索引Q但是根据数据烦引,却无法在~存中找到对应的实体Q所以HibernateҎ(gu)扑ֈ的数据烦引发起了两条select SQL的查询操作,q里造成了对性能的浪费,怎样才能避免q种情况呢?我们必须寚w合类型中的实体也指定~存{略Q所以我们要如下寚w合类型进行配|:

<hibernate-mapping>

    <class name=”com.neusoft.entity.User” table=”user”>

…..

<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

<cache usage=”read-write”/>

<key column=”user_id”/>

<one-to-many class=”com.neusoft.entity.Arrderss”/>

</set>

    </class>

</hibernate-mapping>

此时Hibernate会对集合cd中的实体也进行缓存,如果Ҏ(gu)q个配置再次q行上面的代码,会得到cM如下的输出:

Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Tianjin

Dalian

q时不会再有根据数据烦引进行查询的SQL语句Q因为此时可以直接从~存中获得集合类型中存放的实体对象?/p>

C?nbsp;      属性gq加载:

   在Hibernate3中,引入了一U新的特?#8212;—属性的延迟加蝲Q这个机制又取高性能查询提供了有力的工具。在前面我们讲大数据对象dӞ?User对象中有一个resume字段Q该字段是一个java.sql.ClobcdQ包含了用户的简历信息,当我们加载该对象Ӟ我们不得不每一ơ都要加载这个字D,而不论我们是否真的需要它Q而且q种大数据对象的d本n会带来很大的性能开销。在Hibernate2中,我们只有通过我们前面讲过的面性能的粒度细分,来分解Userc,来解册个问题(请参照那一节的Q,但是在Hibernate3中,我们可以通过属性gq加载机Ӟ来我们获得只有当我们真正需要操作这个字D|Q才去读取这个字D|据的能力Qؓ此我们必d下配|我们的实体c:

<hibernate-mapping>

<class name=”com.neusoft.entity.User” table=”user”>

……

<property name=”resume” type=”java.sql.Clob” column=”resume” lazy=”true”/>

    </class>

</hibernate-mapping>

通过?lt;property>元素的lazy属性设|true来开启属性的延迟加蝲Q在Hibernate3中ؓ了实现属性的延迟加蝲Q用了cd强器来对实体cȝClass文gq行强化处理Q通过增强器的增强Q将CGLIB的回调机刉辑Q加入实体类Q这里我们可以看出属性的延迟加蝲Q还是通过 CGLIB来实现的。CGLIB是Apache的一个开源工E,q个cd可以操纵javacȝ字节码,Ҏ(gu)字节码来动态构造符合要求的cd象。根据上面的配置我们q行下面的代码:

String sql=”from User user where user.name=’zx’ ”;

Query query=session.createQuery(sql);    (1)

List list=query.list();

for(int i=0;i<list.size();i++){

User user=(User)list.get(i);

System.out.println(user.getName());

System.out.println(user.getResume());    (2)

}

当执行到(1)处时Q会生成cM如下的SQL语句Q?/p>

Select id,age,name from user where name=’zx’;

q时Hibernate会检索User实体中所有非延迟加蝲属性对应的字段数据Q当执行?2)处时Q会生成cM如下的SQL语句Q?/p>

Select resume from user where id=’1’;

q时会发起对resume字段数据真正的读取操作?/p>

abin 2012-03-11 15:32 发表评论
]]>
վ֩ģ壺 | ƺ| | ʡ| | ɽ| | ˹| | ʤ| ͨ| ʩ| ʯʨ| ߰| | | ͭ| ־| | | ̫| ͡| Զ| ɳ| | | | ״| | | ƽ| | | | ľ| | | ʡ| | ˫| ̨|