天天看點

【架構】[Hibernate]構架知識點常見操作

配置檔案、JavaBean、HibernateSessionFactory等代碼,請看上一篇:

【架構】[Hibernate]構架知識點詳解入門與測試執行個體

Hibernate常見操作

如果利用Hibernate修改資料庫時,需要使用事務處理,一個事務送出時才真正将修改過的記錄更新到資料庫中。

1、增加記錄

@Test
    public void addStudent(){
        Session session = HibernateSessionFactory.getSession();
        /*需要增加的記錄的對象*/
        Student student = new Student();
        student.setsId("S100");
        student.setsName("王五");
        student.setsAge(26);
        /*定義事務開始*/
        Transaction tran = session.beginTransaction();
        session.save(student);
        /*送出事務,真正儲存到資料庫中*/
        tran.commit();
    }      

根據映射檔案,Hibernate會把我們的增加對象的語句轉換為對應的SQL語句。

Hibernate: insert into hib.students (sName, sAge, sId) values (?, ?, ?)      

2、 删除記錄

@Test
    public void delStudent(){
        Session session = HibernateSessionFactory.getSession();
        /*首先查找待删除的記錄--這裡通過ID*/
        Student student = new Student();
        student.setsId("S100");

        /*定義事務開始*/
        Transaction tran = session.beginTransaction();
        session.delete(student);
        /*送出事務,真正儲存到資料庫中*/
        tran.commit();
    }      

根據映射檔案,Hibernate會把我們的删除對象的語句轉換為對應的SQL語句。

delete from hib.students where sId=?      

3、修改/增加記錄

隻修改還可以用:Update

@Test
    public void addOrUpdata(){
        Session session = HibernateSessionFactory.getSession();
        /*首先查找待修改的記錄--通過ID*/
        //Student s = session.get(Student.class, "S100");//用這種查找出來的隻能修改
        Student s = new Student();
        s.setsId("S101");
        s.setsName("Babo");
        s.setsAge(15);
        /*定義事務開始*/
        Transaction tran = session.beginTransaction();
        session.saveOrUpdate(s);
        /*送出事務,真正儲存到資料庫中*/
        tran.commit();
    }      

hibernate提供了saveOrUpdate的方法來進行資料庫的操作。

hibernate會根據對象的狀态決定是insert還是update,

其根本是通過xml檔案中unsaved-value來确定的。

如果設定null,系統會根據傳入的對象的id的值判斷,

如果是null,則表示對象不存在,那麼insert;

如果不是null,則表示已經存在,那麼update.

Hibernate主鍵ID生成方式

資料庫中表有主鍵、主鍵的唯一性決定了資料庫表中記錄唯一。緩存在Session中的資料即執行個體都有一個唯一的ID,ID映射了資料庫中主鍵。

1、assigned:

主鍵由外部程式負責生成,無需Hibernate參與。即當增加一個實體時,由程式設定它的ID值(手工配置設定值)

<hibernate-mapping package="cn.hncu.domain">
    <class name="Student" table="students" catalog="hib">
        <id name="sId" type="java.lang.String">
            <column name="sId" length="8"></column>
            <generator class="assigned"></generator>            
        </id>
        ...
    </class>
</hibernate-mapping>      

2、identity:

在DB2、SQL Server、MySQL等資料庫産品中表中主鍵列可以設定是自動增長列,則增加一條記錄時主鍵的值可以不指派。用資料庫提供的主鍵生成機制。

(1) 表結構:

create table students(sId int not null  primary key auto_increment,name char(40));      

(2) 映射檔案

<hibernate-mapping package="cn.hncu.domain">
    <class name="Student" table="students" catalog="hib">
        <id name="sId" type="java.lang.String">
            <column name="sId" length="8"></column>
            <generator class="identity"></generator>            
        </id>
        ...
    </class>
</hibernate-mapping>      

3、increment:

主鍵按數值順序遞增。

此方式的實作機制為在目前應用執行個體中維持一個變量,以儲存着目前的最大值,之後每次需要生成主鍵的時候将此值加1作為主鍵。

這種方式可能産生的問題是:如果目前有多個執行個體通路同一個資料庫,那麼由于各個執行個體各自維護主鍵狀态,不同執行個體可能生成同樣的主鍵,進而造成主鍵重複異常。

是以,如果同一資料庫有多個執行個體通路,此方式必須避免使用。

<hibernate-mapping package="cn.hncu.domain">
    <class name="Student" table="students" catalog="hib">
        <id name="sId" type="java.lang.String">
            <column name="sId" length="8"></column>
            <generator class="increment"></generator>           
        </id>
        ...
    </class>
</hibernate-mapping>      

4、sequence:

采用資料庫提供的sequence 機制生成主鍵。

如Oralce 中的Sequence,在Oracle中建立序列:

create sequence hibernate_sequence;

當需要儲存執行個體時,Hibernate自動查詢Oracle中序列”hibernate_sequence”的下一個值;該值作為主鍵值。可以改變預設的序列名稱。

<id name="sId" type="java.lang.String">
    <column name="sId" length="8"></column>
    <generator class="sequence"></generator>            
</id>      

5、native:

由Hibernate根據底層資料庫自行判斷采用identity、hilo、sequence其中一種作為主鍵生成方式。

<id name="sId" type="java.lang.String">
    <column name="sId" length="8"></column>
    <generator class="native"></generator>          
</id>      

6、uuid.hex:

由Hibernate為ID列指派,依據目前用戶端機器的IP、JVM啟動時間、目前時間、一個計數器生成串,以該串為ID值。

<id name="sId" type="java.lang.String">
    <column name="sId" length="8"></column>
    <generator class="uuid.hex"></generator>            
</id>      

Hibernate 查詢方式

Hibernate配備了一種非常強大的查詢語言,這種語言看上去很像SQL。但是不要被文法結構上的相似所迷惑,HQL(Hibernate query lauguage) 被設計為完全面向對象的查詢。

HQL對關鍵字的大寫小并不區分,但是對查詢的對象就要區分大小寫,因為它是面向對象的查詢,是以查詢的是一個對象,而不是資料庫的表,在sql中如果要加條件的話就是列,而在HQL裡面條件就是對象的屬性,而且還要給對象起别名。      

1、Hibernate查詢 HQL語句

限制查詢結果記錄數與起始記錄

@Test
    public void query1(){
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery("from Student");
        query.setFirstResult(10); //設定查詢記錄開始位置,索引從0開始。
        query.setMaxResults(10);//設定查詢傳回的最大記錄個數。
        List<Student> lists = query.list();
        for(Student s:lists){
            System.out.println(s);
        }
    }      

條件查詢

查詢名字中帶有’1’的所有Student

@Test
    public void query2(){
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery("from Student s where s.sName like '%1%'");
        List<Student> lists = query.list();
        for(Student s:lists){
            System.out.println(s);
        }
    }      

2、取表中部分列時

(1) 單一屬性查詢。

還是傳回一個集合,隻不過集合中存儲的不是表的執行個體而是對象。

@Test
    public void query3(){
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery("select sName from Student s");
        List<String> lists = query.list();
        for(String s:lists){
            System.out.println(s);
        }
    }      

(2) 多個屬性的查詢,使用對象數組。

查詢多個屬性,其集合元素是對象數組

數組元素的類型,跟實體類的屬性的類型相關

@Test
    public void query4(){
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery("select sName,sAge from Student s");
        List<Object[]> lists = query.list();
        for(Object[] s:lists){
            System.out.println(s[0]+","+s[1]);
        }
    }      

(3) 多個屬性的查詢,使用List集合裝部分列

@Test
    public void query5(){
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery("select new list(s.sId,s.sName,s.sAge) from Student s");
        List<List> lists = query.list();
        for(List s:lists){
            System.out.println(s.get(0)+" "+s.get(1)+" "+s.get(2));//0,1,2是索引

        }
    }      

(4) 使用Map集合裝部分列

@Test
    public void query6(){
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery("select new Map(s.sId,s.sName,s.sAge) from Student s");
        List<Map> lists = query.list();
        for(Map s:lists){
            System.out.println(s.get("0")+" "+s.get("1")+" "+s.get("2"));//"0","1","2"是key

        }
    }      

3、内連接配接

Query query=session.createQuery("select c.name, s.name from Student s join s.classes c ").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
    Object[] obj = (Object[])iter.next();
    System.out.println(obj[0] + ", " + obj[1]);
}      

4、外連接配接

select c.name, s.name from Classes c left join c.students s 
select c.name, s.name from Classes c right join c.students s      

5、帶參數的查詢

(1) ?作為參數

如” from Customer cus where cus.name=?”;

Session session = HibernateSessionFactory.getSession();
    Query query = session.createQuery("from Customer cus where cus.name=?");
     query.setParameter(0, "zhou");
     List list = query.list();      

(2) 參數名稱 :name

Session session = HibernateSessionFactory.getSession();
       Query query = session.createQuery("from Customer cus where cus.name=:name ");
       query.setParameter("name", "zhou");
       List list = query.list();      

(3) 條件查詢,使用 ?的方式傳遞參數

Query query = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE ?");

Query query = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE :myname");

query.setParameter("myname", "張三");//傳遞參數因為setParameter方法傳回Query接口,是以可用省略方式來查詢

List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE :myname and s.id = :myid").
setParameter("myname", "%周%").setParameter("myid", 15).list();      

6、嵌入原生sql測試

SQLQuery sqlQuery = session.createSQLQuery("select * from t_student");
    List students = sqlQuery.list();
    for (Iterator iter = students.iterator();iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
    }