Hibernate學習

1        Hibernate核心技術

1.1        理論基礎

操作數據庫的3個階段

1、  操作JDBC階段

2、  封裝JDBC

3、  ORM階段

ORM對象關係映射

持久層概念

 

1.2        Hibernate開發流程

步驟

1、  創建Hibernate的配置文件:該文件負責初始化Hibernate配置,包括數據庫配置和映射文件配置

2、  創建Hibernate映射文件:每一個數據表對應一個映射文件,該文件描述了數據庫中表的信息,也描述了對應的持久化類的信息

3、  創建持久化類

以上三步是開發Hibernate要實現的關鍵內容,接下來就要面向Web應用層進行編碼

1、  編寫DAO層:通過HibernateAPI編寫訪問數據庫的代碼

2、  編寫Service層:編寫業務層實現,調用DAO層類代碼

 

下載並安裝Hibernate

必需的包:

Hibernate3.jar

cglib-2.1.jarasm-attrs.jarasm.jarCGLIB庫,用來實現PO字節碼的動態生成

dom4j-1.5.2.jarjavaXMLAPI,類似於jdom,用來讀寫XML文件的

commons-collections-2.1.1.jar

commons-logging-1.0.4.jarlog4j-1.2.9.jar:包含了日誌功能

將以上文件複製到lib目錄下

 

1.3        Hibernate配置文件詳解

有兩種形式:一種是XML(hibernate.cfg.xml),一種是properties屬性文件(hibernate.properties),一般使用XML

Etc子目錄下提供了默認的Hibernate配置文件hibernate.cfg.xml,複製到src目錄下,修改後如下

<hibernate-configuration>

     <session-factory name="foo">

         <property name="myeclipse.connection.profile">JDBC for MySQL</property>

         <!-- 顯示執行的SQL語句 -->

         <property name="show_sql">true</property>

         <property name="connection.url">jdbc:mysql://localhost:3306/demo</property>

         <property name="connection.username">root</property>

         <property name="connection.password"></property>

         <property name="connection.drive_class">org.gjt.mm.mysql.Driver</property>

         <!-- 選擇使用的方言 -->

         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

         <!-- 映射文件 -->

         <mapping resource="com/demo/hibernate/beans/User.hbm.xml"/>

     </session-factory>

</hibernate-configuration>

 

1.4        編寫映射文件User.hbm.xml

Hibernate映射文件包含了對象/關係映射(O/R Mapping)所需的元數據。建立一個映射文件User.hbm.xml來映射到數據庫表User,映射的類名爲User,所在的包爲com.demo.hibernate.beans。如下

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC

     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="com.demo.hibernate.beans">

     <class name="User" table="user">

         <id name="id" column="ID" type="integer">

              <generator class="native"/>               //設置主鍵生成方式

         </id>

         <property name="username" column="username" type="string"/>

         <property name="password" column="password" type="string"/>

         <property name="email" column="email" type="string"/>  

     </class>

</hibernate-mapping>

 

1.4.1       根元素<hibernate-mapping>

每一個hbm.xml文件都有唯一的一個根元素。Package屬性指定一個包前綴。<hibernate-mapping>元素允許嵌套多個<class>映射。但是最好的做法是一個持久化類對應一個映射文件,並以持久化的超類名稱命名

 

1.4.2       使用<class>定義類

<class name="User" table="user">

Class也可以是一個接口,之後可以用<subclass>來指定該接口的實際實現類。

 

1.4.3       使用<id>定義主鍵

如果表使用聯合主鍵,你可以映射多個屬性爲標識符屬性。下面定義了兩個字段作爲聯合主鍵。此時持久化類必須重載equals()hashCode()方法,來實現組合標識符的相等判斷。

<composite-id>

    <key-property name="username"/>

    <key-property name="password"/>

</composite-id>

 

1.4.4       <generator>設置主鍵生成方式

<generator class="native"/>

 

1.4.5       Hibernate映射類型

 

1.4.6       使用<property>定義屬性

<property name="username" column="username" type="string"/>

 

1.4.7       <many-to-one>配置多對一映射

1.4.8       <one-to-one>配置一對一映射

1.4.9       Hibernate映射文件自動生成工具

 

 

1.5        編寫持久化類User.java

持久化類是指其實例需要被Hibernate持久化到數據庫中的類。Hibernate使用簡單的Java對象(Plain Old Java Objects,就是POJOs,有時也稱作Plain Ordinary Java Objects)這種編程模型來進行持久化

package com.demo.hibernate.beans;

public class User {

     private java.lang.Integer id;

     private String username;

     private String password;

     private String email;

     public String getEmail() {

         return email;

     }

     public void setEmail(String email) {

         this.email = email;

     }

     ……

}

getXXX()setXXX()方法必須符合特定的命名規則,“get”和“set”後面緊跟屬性的名字,並且屬性名的首字母爲大寫。

如果持久化類的屬性爲boolean類型,那麼它的get方法即可以用get爲前綴,也可以用“is”爲前綴。

 

1.6        編寫輔助類HibernateSessionFactory.java

Session是一個持久化管理器,我們通過它來從數據加中存取User。首先,我們要從SessionFactory中獲取一個Session。通過對configure()調用來裝載hibernate.cfg.xml配置文件,並初始化成一個Configuration實例。

通常SessionFactory只是被初始化一次,例如通過一個load-on-startup servlet來初始化。這意味着你不應該在servlet中把它作爲一個實例變量來持有,而應該放在其他地方。進一步說,我們需要使用單例(Singleton)模式,才能更容易地在程序中訪問SessionFactory。下面的方法就同時解決了這兩個問題

 

package com.demo.hibernate.util;

import org.hibernate.cfg.Configuration;

import org.hibernate.HibernateException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

 

public class HibernateSessionFactory {

     private static String CONFIG_FILE_LOCATION="/hibernate.cfg.xml";

     private static final ThreadLocal threadLocal=new ThreadLocal();

     private static final Configuration cfg=new Configuration();

     private static SessionFactory sessionFactory;

     //取得session

     public static Session currentSession() throws HibernateException{

         Session session=(Session)threadLocal.get();

         if(session==null){

              if(sessionFactory==null){

                   try{

                       cfg.configure(CONFIG_FILE_LOCATION);

                       sessionFactory=cfg.buildSessionFactory();

                   }catch(Exception e){

                       System.err.println("%%%%Error Creating SessionFactory%%%%");

                       e.printStackTrace();

                   }

              }

              session=sessionFactory.openSession();

              threadLocal.set(session);

         }

         return session;

     }

     //關閉Session對象

     public static void closeSession() throws HibernateException{

         Session session=(Session)threadLocal.get();

         threadLocal.set(null);

         if(session==null){

              session.close();

         }

     }

}

這個類不但在它的靜態初始器中使用了SessionFactory,還使用了一個ThreadLocal變量來保存Session作爲當前工作線程。

 

1.7        編寫DAOUserDAO.java

所謂的DAO(Data Access Object)層,就是數據訪問接口,爲了基於Hibernate的開發中,通常將業務層與數據層分開,DAO層只負責調用Hibernate API實現CRUD操作,Service層面向用戶負責調用DAO層的代碼。這樣做的好處是,數據層的代碼不用關心業務,可以更好地實現移植

    下面編寫一個DAOUserDAO.java,該類實現一個getUser()函數,根據用戶名username查詢一個用戶對象。

public class UserDAO {

     public User getUser(String username)throws HibernateException{

         Session session=null;

         Transaction tx=null;

         User user=null;

         try{

              session=HibernateSessionFactory.currentSession();

              tx=session.beginTransaction();

              Query query=session.createQuery("from User where username=?");

              query.setString(0, username.trim());

              user=(User)query.uniqueResult();

              query=null;

              tx.commit();

             

         }catch(HibernateException e){

              throw e;

         }finally{

              if(tx!=null){

                   tx.rollback();

              }

              HibernateSessionFactory.closeSession();

         }

         return user;

     }

}

 

1.8        編寫Service類並運行

即服務層,就是面向用戶服務,它定義的方法都是與實際的業務相關的。

下面定義一個ServiceUserService,它有一個函數valid(),根據用戶名和密碼來判斷用戶是否存在。

 

運行出錯

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial

      at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)

      at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:247)

      at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:284)

      at javax.naming.InitialContext.getNameParser(InitialContext.java:439)

      at org.hibernate.util.NamingHelper.bind(NamingHelper.java:52)

      at org.hibernate.impl.SessionFactoryObjectFactory.addInstance(SessionFactoryObjectFactory.java:90)

      at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:306)

      at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)

      at com.demo.hibernate.util.HibernateSessionFactory.currentSession(HibernateSessionFactory.java:19)

      at com.demo.hibernate.dao.UserDAO.getUser(UserDAO.java:16)

      at com.demo.hibernate.service.UserService.valid(UserService.java:8)

      at com.demo.hibernate.service.UserService.main(UserService.java:19)

原因:配置文件在存在<session-factory name="foo">,將name="foo"去掉即可

 

1.9        Hibernate核心類用法

1.9.1       使用Configuration裝載配置

使用hibernate.cfg.xml,該文件中設置了數據庫連接的屬性和hbm.xml映射文件配置,Hibernate會自動加載該配置屬性,並自動找到POJO類。

Configuration cfg=new Configuration();

Cfg.configure("hibernate.cfg.xml");

 

1.9.2       sessionFatcory

sessionFaction=cfg.buildSessionFactory();

 

1.9.3       Session

主要功能是提供對映射的實體類實例的創建、讀取和刪除操作。實例可能以下面3種狀態存在。

自由狀態(transient):不曾進行持久化,未與任何Session相關聯

持久化狀態(persistent):僅與一個Session相關聯

遊離狀態(detached):已經進行過持久化,但當前未與任何Session相關聯

 

1、  Save()保存對象

用於將一個新實例化的對象持久化,保存到數據庫中

如:session.save(user);

 

2、  Load()裝載對象

如果你知道某個實例的持久化標識,就可以使用Sessionload()方法來獲取它。

如:User user=(User)session.load(User.class,new Integer("1"));

表示加載標識符爲1User,並賦給一個新的實例變量user

此外,你可以把數據加載到指定的對象實例上(覆蓋該實例原來的數據)

Session.load(user,new Integer("1"));(如果沒有匹配的數據庫記錄,load方法可能拋出無法恢復的異常unrecoverable exception

 

3、  Get()裝載對象

如果你不確定是否有匹配的行記錄存在,應該使用get()方法,它會立刻訪問數據庫,如果沒有,會返回null

 

4、  Flush()強制提交刷新

如果一個實例被更改了,則可以使用flush()將更改後的實例對象強制保存到數據庫中。

 

5、  Update()提交遊離狀態的對象

 

6、  Delete()移除持久化對象

該函數用於從數據庫中刪除對象對應的記錄

 

7、  Refresh()強制裝載對象

任何時候都可以使用refresh()方法強迫裝載對象和它的集合。如果你使用數據庫觸發器功能來處理對象的某些屬性,這個方法就很有用了。

 

1.9.4       使用Transaction管理事務

Transaction tx=session.begionTransaction();

Tx.commit();

 

1.9.5       使用Query進行HQL查詢

1、  不帶參數的查詢

Query query=session.createQuery(“from user”);

 

2、  帶參數的查詢

接口Query提供了對命名參數、JDBC風格的問號(?)參數兩種參數綁定方法。

如:

Query query=session.createQuery("from User where username=:username");

query.setString("username","admin")

也可以使用集合型參數。如下所示,在SQL語句中使用in關鍵字指向一個命名參數列表

List names=new ArrayList();

names.add(admin);

names.add(test);

Query query=session.createQuery("from user where username in (:nameList)");

query.setParameterList("nameList",names);

 

3、  使用問號參數

Query query=session.createQuery("from user where username=?");

query.setString(0,"admin");

 

4、  取得List結果集

List list=query.list();

 

5、  取得迭代列表結果集

Iterate()

 

6、  取得一個對象

如果你知道當前查詢只會返回一個對象,則可使用list()的快捷方式uniqueResult()來取得一個對象

User user=(User)query.uniqueResult()

 

7、  標量查詢

查詢可以在select從句中指定類的屬性,甚至可以調用SQL統計函數

Iterator results=session.createQuery(

    "Select user.username,count(user.email) from user group by username")

    .list().iterator;

 

8、  分頁查詢

query.setFirstResult(10);//設置起始範圍

query.setMaxResults(20);//設置結束範圍

List list=query.list();

 

9、  創建SQL查詢

可以使用createSQLQuery()方法,用普通的SQL來描述查詢並由Hibernate處理將結果貪集轉換成對象的工作。

List users=session.createSQLQuery(SELECT {user}.* FROM User {user}).list();

其中SQL別名需要用大括號包圍起來。和Hibernate查詢一樣,SQL查詢也可以包含命名參數和佔位參數

 

1.9.6       使用Criteria進行條件查詢

Criteria接口與Query接口非常類似,它允許你創建並執行面向對象的標準化查詢。動態地使用面向對象API創建查詢,而非在Java代碼中嵌入字符串

創建Criteria實例

Cirteria criteria=session.createCriteria(User.class);

Criteria.setMaxResults(50);

List users=criteria.list();

 

1、  添加查詢條件

查詢條件是通過org.hibernate.criterion.Restrictions類來實現的,用來模擬SQL語句中的條件關鍵字,例如likebetweenandor

Criteria criteria=session.createCriteria(User.class);

criteria.add(Restrictions.like("username","admin%"));

criteria.add(Restrictions.between("ID",1,10));

List users=criteria.list();

 

2、  添加排序條件

可以使用org.hibernate.criterion.Order來爲查詢結果排序,它共包含兩個方法,asc()desc(),分別實現SQL語句中的ascdesc關鍵字。通過調用CriteriaaddOrder()來添加多個Order實例,如下

List users=session.createCriteria(User.class)

.add(Restrictions.like("username","admin%"))

.addOrder(Order.asc("username"))

.addOrder(Order.asc("password"))

.list();

 

3、  示例查詢

Org.hibernate.criterion.Example類允許通過一個給定實例來構建一個條件查詢。

User user=new User();

User.setUsername();

List results=session.createCriteria(User.class)

    .add(Example.create(user)).list();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章