注銷

          注銷

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            112 隨筆 :: 7 文章 :: 18 評論 :: 0 Trackbacks
          <2007年5月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          一、首先學習hibernate.cfg.xml配置文件的具體配置
          <?xml version="1.0" encoding="UTF-8"?>

          <!--指定該文件的官方dtd-->
          <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
          <hibernate-configuration>
            <session-factory>
              <!-- 顯示sql語言 -->
              <property name="show_sql">true</property>
              <!-- sql語言 -->
              <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
              <!-- jdbc驅動程式 -->
              <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
              <!-- jdbc url -->
              <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
              <!-- 數據庫用戶名 -->
              <property name="connection.username">root</property>
              <!-- 數據庫密碼 -->
              <property name="connection.password">wyq</property>
              <!-- C3P0連接池設定 -->
              <!--最小連接數-->
              <property name="c3p0.min_size">5</property>
              <!--最大連接數-->
              <property name="c3p0.max_size">20</property>
             <!--延遲所允許的時間-->
              <property name="c3p0.timeout">1800</property>
             <!--緩存所允許的最大連接數-->
              <property name="c3p0.max_statements">50</property>
              <!-- 每隔100筆資料送入資料庫,清除緩存(定期清除緩存,減小壓力) -->
              <property name="hibernate.jdbc.batch_size">100</property>
              <!-- 設定事務管理的工廠類 -->
              <property name="hibernate.transaction.factiory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
             <mapping resource="com/wyq/hibernate/pojo/User.hbm.xml"/>
             <mapping resource="com/wyq/hibernate/pojo/TUser.hbm.xml"/>
             <mapping resource="com/wyq/hibernate/pojo/Room.hbm.xml"/>
            </session-factory>
          </hibernate-configuration>
          需要的jar包有c3p0.jar,hibernate3.jar,數據庫.jar,log4j.jar


          ------------------------------------------------------------------------------------------------------------------------

          1、讀取配置文件獲得連接
             讀取hibernate.cfg.xml配置文件,hibernate.cfg.xml文件放在Classpath下,使用下面的方式讀入該文件
                //Configuration 負責管理hibernate配置信息
                Configuration config=new Configuration().configure();
                //根據config建立SessionFactory
                //SessionFactory用于建立Session
                SessionFactory sessionFactory=config.buildSessionFactory();
                //開啟session,相當于jdbc的Connection
                session = sessionFactory.openSession();

          2、Criteria 基本資料查詢
          (1)標準查詢:
                //創建查詢標準
                Criteria criteria=session.creteCriteria(User.class);
                //查詢條件
                criteria.add(Expression.eq("name","caterpillar"));
          ************************************************************************************
          Expression.eq(String s1,String s2)---------->相等s1=s2
          Expression.allEq(Map map)    --------------->多個屬性-值對應關系,多個Expression.eq疊加
          Expression.gt(String s1,String s2)----------->大于s1>s2
          Expression.ge(String s1,String s2)----------->大于等于s1>=s2
          Expression.lt(String s1,String s2)------------>小于s1<s2
          Expression.le(String s1,String s2)------------>小于等于s1<=s2
          Expression.between(String s1,int s2,int s3)--->s2<s1<s3
          Expression.like(String s1,String s2)------------>s1 like s2
          比較2個屬性
          Expression.eqProperty(String s1,String s2)--->s1=s2
          Expression.gtProperty(String s1,String s2)---->s1>s2
          Expression.geProperty(String s1,String s2)---->s1>=s2
          Expression.ltProperty(String s1,String s2)----->s1<s2
          Expression.leProperty(String s1,String s2)----->s1<=s2
          Expression.and()----->Expression.and(Expression.eq("String s1,String s2"),Expression.eq(String s3,String s4))
          Expression.or()
          ************************************************************************************
          (2)高級查詢
          一、可以使用Criteria進行查詢,并用order對結果進行排序。
          //設置從第幾條開始取的記錄
          criteria.setFirstResult(100);
          //最多取的幾條記錄
          criteria.setMaxResults(20);
          //對結果進行排序
          criteria.addOrder(Order.asc(String s1));
          criteria.addOrder(Order.desc(String s2));

          二、可以對查詢結果進行統計操作,使用Projections的rowCount(),count(),max(),min(),countDistinct()等方法:
          例如:criteria.setProjection(Projections.max("age"));

          三、還可以用Projections的groupProperty()來對結果進行分組
          例如:criteria.setProjection(Projections.groupProperty("age"));

          (***)四、結合統計與分組的功能,可以用ProjectionList
          例如:ProjectionList projectionList =Projections.projectionList();
                      projectionList.add(Projections.groupProperty("age"));
                      projectionList.add(Projections.rowCount());
                      criteria.setProjection(projectionList);
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                //查詢所有記錄
                List users=criteria.list();
                Iterator iterator=users.iterator();
                while(iterator.hasNext()){
                   User user=(User)iterator.next();
                   System.out.println(user.getId()+"\t"+user.getName()+"/"+user.getAge());
          }
          3、criteria的增、刪、改(還不完善)
          在用到增、刪、改時,必須先聲明事務
          增加:
            Transaction tx = session.beginTransaction();//Transaction表示一組會話操作
            session.save(user);//將事物映射到數據庫進行存儲
            tx.commit();
            session.close();
          刪除:
            Session session=this.getSession();
            User user=(User)session.get(User.class, new Integer(1));
            Transaction tx = session.beginTransaction();//Transaction表示一組會話操作
            session.delete(user);//將事物映射到數據庫進行存儲
            tx.commit();
            session.close();

          修改:
            Session session=this.getSession();
            User user =(User)session.get(User.class,new Integer(2));//創建持久化的事物
            user.setName("wyqqqqqqqqqq");
            user.setAge(new Integer(30));
            Transaction tx = session.beginTransaction();//Transaction表示一組會話操作
            session.update(user);//將事物映射到數據庫進行存儲
            tx.commit();
            session.close();
          ----------------------------------------------------------------------------------------------------------------------
          一、Query查詢可以先設定查詢參數,之后通過set等方法,將指定的參數值添入.還可以使用命名參數
          Session session = sessionFactory.openSession();
          Query query = session.createQuery("select user.name from User as user where user.age>?(
          :minAge )");
          query.setInteger(0,25);
          query.setInteger("minAge",25);
          List names=query.list();
          Iterator iterator = names.iterator();
          while(iterator.hasNext()){
                System.out.println(iterator.next());
          }
          session.close();

          二、如果查詢整個表直接使用from User如果針對某個屬性使用select user.name from User as user
          使用hql可以更接近我們平時的jdbc編程,和把sql語句寫在程序中差不多,另外,也可以將sql語句寫在配置文件中。



          --------------------------------------------------------------------------------------------------------------------------
             多表關聯
          一、多對一進行關聯(多個學生對應同一間宿舍)---學生是主體,宿舍是附體,關聯關系<many-to-one>在主體學生中設置,在學生類中設置宿舍類,由于宿舍類只有一個可以直接用類來設置,在映射學生類(User)中包含宿舍這個類(Room),在映射配置文件(User.hbm.xml)中定義

          <many-to-one name="room" column="room_id" cascade="save-update" class="com.wyq.hibernate2.Room"></many-to-one>

          哪個是主體類就在哪個配置文件定義關聯關系.

          cascade屬性:表示關聯對象的持久化,該屬性也要設置在主體中,作用就是當主控方執行操作時,關聯對象(被動方)是否同步執行同一操作.
          cascade的值:all:表示所有情況下都進行級聯操作.
                                  none:所有情況下都不進行級聯操作
                                  save-update:在執行save-update時進行級聯操作.
                                  delete:在執行delete時進行級聯操作.

          注意:使用cascade自動持久化時,會先檢查被關聯物件的id屬性,未被持久化的物件之id屬性是由unsaved-value決定,預設是null,如果您使用long這樣的原生型態(primitive type)時,則必須自行指定預設值.

          例如:<id name="id" column="ROOM_ID" unsaved-value="0">
                      <generator class="increment"/>
                  </id>

          如果您不想額外設定unsaved-value資訊,則可以將long改為Long,這可以符合預設的unsaved-value為null的設定 .

          二、一對多進行關聯(一間宿舍對應多個學生)---宿舍是主體,學生是附體,關聯關系<one-to-many>在主體宿舍中設置,由于要在宿舍類中設置學生類,一個宿舍包含多個學生,所以在宿舍類中要用Set類來進行設置,用set類(private Set users = new HashSet();)來存儲多個學生類,在映射宿舍類(Room)中要包含<set>這個節點,用來與user相關聯

          例如:<set name="users" table="USER">
                      <key column="ROOM_ID"/>
                      <one-to-many class="onlyfun.caterpillar.User"/>
                  </set>

          name:表示屬性,table:表示關聯的表名,key:表示通過什么字段進行關聯,<one-to-many>:表示關聯類。這里也可以使用cascade屬性。

          三、在表關聯的設計中,不論是一對多還是多對一,都要將關聯字段設置在多的那一方。
          例如:user表格和room表格,要將關聯字段room_id設置在user表格中。

          四、一對一進行關聯(一個人只有一個房間,一個房間也只有一個人)。
          可以通過2中方式進行關聯:

          (1)、通過外鍵進行關聯:在多對一的例子中就是通過外鍵進行關聯的.
          在user-room的設置中(user.hbm.xml):
          <many-to-one name="room"
                               column="ROOM_ID"
                               class="onlyfun.caterpillar.Room"
                               cascade="all"
                               unique="true"/>

          其中unique表示限制一個User有一獨有的 Room,這只是單向的,說明一個user只有一個room.
          在room-user的設置中(room.hbm.xml):
          <one-to-one name="user"
                              class="onlyfun.caterpillar.User"
                              property-ref="room"/>
          這樣就完成了雙向的一對一關聯,property-ref告訴hibernate,查詢出user并將其參考至room。
          (2)、通過主鍵進行關聯:限制兩個資料表的主鍵使用相同的值,如此一個User與Room就是一對一關係
          user.hbm.xml:
          <one-to-one name="room"
                              class="onlyfun.caterpillar.Room"
                              cascade="all"/>
          room.hbm.xml:
          <one-to-one name="user"
                              class="onlyfun.caterpillar.User"
                              constrained="true"/>

          使用constrained="true"告訴Hibernate參考至User的主鍵

          五、雙向關聯,就是將一和二結合起來,如果將關聯的維護交給User的話會比較容易,因為每個User都對應至一個Room,在儲存時並用像Room一樣必須對Set中的每個物件作檢查,為了將關聯的維護交給User,我們可以在Room.hbm.xml中的<set>修改,加上inverse="true",表示將關聯的維護「反過來」交給User作

           例如:<set name="users" table="users" iinverse="true" cascade="all">
                        <key  column="room_id"/>
                        <one-to-many class="onlyfun.caterpillar.User"/>

          在設立雙向關聯時,關聯由多對一中「多」的哪一方維護,會比由「一」的哪一方維護來的方便,在Hibernate可以藉由inverse來設定,不設定inverse基本上也可以運行,但是效能會較差。


          ------------------------------------------------------------------------------------------------------------------------
                在Hibernate中,集合類的映射可以延遲初始(Lazy Initialization),在多對一或者一對多中,都可以使用延遲初始,例如:一個用戶(user對應user表)有多個email地址(address對應address表),也就是在真正索取該物件的資料時,才向資料庫查詢,就上次例子來說,就是我們在讀取User時,先不取得其中的 addrs屬性中之物件資料,由於只需要讀取User的name屬性,此時我們只要執行一次select即可,真正需要addrs的資料時,才向資料庫要求。在含有集合類的user.hbm.xml中要如下設置:

            <set name="addrs" table="ADDRS" lazy="true">
                      <key column="USER_ID"/>
                      <element type="string" column="ADDRESS" not-null="true"/>
                  </set>

          --------------------------------------------------------------------------------------------------------------------------
                session是hibernate運做的核心,是有SessionFactory所創建,sessionFactory是線程安全的,你可以讓多個線程同時存取SessionFactory,而不會有資源共用的問題,然而session不是設計為線程安全的,所以讓多個線程共用一個session,將發生資料共用而發生混亂的問題.下面是一個標準類.

          import java.io.Serializable;
          import net.sf.hibernate.HibernateException;
          import net.sf.hibernate.Session;
          import net.sf.hibernate.SessionFactory;
          import net.sf.hibernate.Transaction;
          public class HibernateSessionUtil implements Serializable
          {
               //創建線程局部變量 tLocalsess 
              public static final ThreadLocal tLocalsess = new ThreadLocal();
             //創建線程局部變量 tLocaltx
          public static final ThreadLocal tLocaltx = new ThreadLocal();
                //取得session
              public static Session currentSession(){
                   //從線程變量tLocalsess中,取得當前session
          Session session = (Session) tLocalsess.get();
          //判斷session是否為空,如果為空,將創建一個session,并付給線程變量tLocalsess
              try{
          if (session == null){
          session = openSession();
          tLocalsess.set(session);
          }
          }catch (HibernateException e){
          throw new InfrastructureException(e);
          }
          return session;
          }
          //關閉當前session
              public static void closeSession(){
          
                   //從線程變量tLocalsess中,取得當前session
          Session session = (Session) tLocalsess.get();
                   //設置線程變量tLocalsess為空
          tLocalsess.set(null);
          try{
                      //關閉session
          if (session != null && session.isOpen()){
          session.close();
          }
          }catch (HibernateException e){
          throw new InfrastructureException(e);
          }
          }
          //事物處理
              public static void beginTransaction(){
                //從線程變量tLocaltx中取得事物管理對象Transaction
                  Transaction tx = (Transaction) tLocaltx.get();
          try{
                      //如果為空就從session中創建一個tx
          if (tx == null){
          tx = currentSession().beginTransaction();
          tLocaltx.set(tx);
          }
          }catch (HibernateException e){
          throw new InfrastructureException(e);
          }
          }
          //提交事物
              public static void commitTransaction(){
                //取得事物
          Transaction tx = (Transaction) tLocaltx.get();
          try{
                      //如果不為空就提交
          if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
          tx.commit();
          tLocaltx.set(null);
          }catch (HibernateException e){
          throw new InfrastructureException(e);
          }
          }
              //事物回滾    
              public static void rollbackTransaction(){
                   //取得tx事物
          Transaction tx = (Transaction) tLocaltx.get();
          try{
                      //將變量清空
          tLocaltx.set(null);
          if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){
                          //事物回滾
          tx.rollback();
          }
          }catch (HibernateException e){
          throw new InfrastructureException(e);
          }
          }
          
             //取得session
          private static Session openSession() throws HibernateException{
          return getSessionFactory().openSession();
          }
          
             //取得sessionFactory
          private static SessionFactory getSessionFactory() throws HibernateException{
          return SingletonSessionFactory.getInstance();
          }
          }
          filter的代碼:
          public class HibernateSessionCloser implements Filter{
          protected FilterConfig filterConfig = null;
          public void init(FilterConfig filterConfig)throws ServletException{
          this.filterConfig = filterConfig;
          }
          public void destroy(){
          this.filterConfig = null;
          }
          public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain chain)
          throws IOException, ServletException {
          try{
          chain.doFilter(request, response);
          }
          finally{
          try{
          HibernateSessionUtil.commitTransaction();
          }catch (InfrastructureException e){
          HibernateSessionUtil.rollbackTransaction();
          }finally{
          HibernateSessionUtil.closeSession();
          }
          }
          }
          }
          ---------------------------------------------------------------------------------------
          
                (1)、悲觀鎖定(Pessimistic Locking)一如其名稱所示,悲觀的認定每次資料存取時,其它的客戶端也會存取同一筆資料,因此對該筆資料進行鎖定,直到自己操作完成後解除鎖定。 

                悲觀鎖定通常透過系統或資料庫本身的功能來實現,依賴系統或資料庫本身提供的鎖定機制,Hibernate即是如此,可以利用Query或 Criteria的setLockMode()方法來設定要鎖定的表或列(Row)及其鎖定模式,可設定的鎖定模式有以下的幾個:
        1. LockMode.WRITE:在insert或update時進行鎖定,Hibernate會在save()方法時自動獲得鎖定。
        2. LockMode.UPGRADE:利用SELECT ... FOR UPDATE進行鎖定。
        3. LockMode.UPGRADE_NOWAIT:利用SELECT ... FOR UPDATE NOWAIT進行鎖定,在Oracle環境下使用。
        4. LockMode.READ:在讀取記錄時Hibernate會自動獲得鎖定。
        5. LockMode.NONE:沒有鎖定。

                (2)、樂觀鎖定(Optimistic locking)則樂觀的認為資料的存取很少發生同時存取的問題,因而不作資料庫層次上的鎖定,為了維護正確的資料,樂觀鎖定使用應用程式上的邏輯實現版本控制的解決。 

                在不實行悲觀鎖定策略的情況下,資料不一致的情況一但發生,有幾個解決的方法,一種是先更新為主,一種是後更新的為主,比較複雜的就是檢查發生變動的資料來實現,或是檢查所有屬性來實現樂觀鎖定。
                要注意的是,由於樂觀鎖定是使用系統中的程式來控制,而不是使用資料庫中的鎖定機制,因而如果有人特意自行更新版本訊息來越過檢查,則鎖定機制就會無效,例如在上例中自行更改userV2的version屬性,使之與資料庫中的版本號相同的話就不會有錯誤,像這樣版本號被更改,或是由於資料是由外部系統而來,因而版本資訊不受控制時,鎖定機制將會有問題,設計時必須注意。

        6. posted on 2007-05-30 14:20 注銷..... 閱讀(420) 評論(0)  編輯  收藏 所屬分類: 閱讀摘要
          主站蜘蛛池模板: 呼图壁县| 南宁市| 休宁县| 双柏县| 库伦旗| 托克逊县| 屏南县| 灵川县| 探索| 涟水县| 炎陵县| 黄梅县| 青海省| 本溪| 新绛县| 阜城县| 甘南县| 台东市| 离岛区| 莎车县| 澄迈县| 晋江市| 海城市| 保定市| 丹阳市| 林甸县| 昭通市| 自治县| 昌邑市| 榆社县| 若尔盖县| 周口市| 耿马| 集安市| 保康县| 奉节县| 康马县| 和田市| 和平区| 南安市| 浦东新区|