Hibernate——HQL語句

HQL(Hibernate Query Language) – 官方推薦

前面的入門示例中,我們通過session.load(Employee.class, 1),也就是通過load()方法或者get()方法,可以通過主鍵屬性來查詢一條記錄。當然這種方法很有侷限性,爲了更多的查詢需求,我們需要使用HQL語句。

HQL即Hibernate查詢語言,它是面向對象的查詢語言,與SQL不同,HQL中的對象名是區分大小寫的(除了JAVA類和屬性的其他部分不區分大小寫);HQL中查的是對象而不是表,並且支持多態;HQL主要通過Query來操作,Query的創建方式:

Query q = session.createQuery(hql);
 hql = from Person
 hql = from User user where user.name = :name
 hql = from User user where user.name = :name and user.birthday < :birthday

下面我們通過示例來學習HQL的相關語法。

建立三張表

這裏我們建立三張表,通過示例來學習HQL語法。

CREATE TABLE student (
    sid INT PRIMARY KEY,
    sname VARCHAR (45) NOT NULL,
    ssex CHAR (2) NOT NULL,
    sdept VARCHAR (10) NOT NULL,
    sage INT,
    saddress VARCHAR (45)
);

-- 學生表中的數據
INSERT INTO student
VALUES
    (
        20040001,
        '林青霞',
        'F',
        '計算機系',
        22,
        '上海'
    );

INSERT INTO student
VALUES
    (
        20040002,
        '劉德華',
        'M',
        '外語系',
        23,
        '南京'
    );

INSERT INTO student
VALUES
    (
        20050003,
        '成龍',
        'M',
        '化學系',
        21,
        '山東'
    );

INSERT INTO student
VALUES
    (
        20050004,
        '林可欣',
        'F',
        '計算機系',
        22,
        '北京'
    );

INSERT INTO student
VALUES
    (
        20050005,
        '周華健',
        'M',
        '生物系',
        24,
        '山東'
    );

INSERT INTO student
VALUES
    (
        20050006,
        '周潤發',
        'M',
        '數學系',
        20,
        '湖北'
    );

-- 建立課程表
CREATE TABLE course (
    cid INT PRIMARY KEY,
    -- 這是課程號
    cname VARCHAR (50) NOT NULL,
    -- 課程名
    ccredit INT -- 課程學分
);

INSERT INTO course
VALUES
    (11, 'java編程', 6);

INSERT INTO course
VALUES
    (21, 'c++課程', 4);

INSERT INTO course
VALUES
    (31, 'oracle', 3);

INSERT INTO course
VALUES
    (41, 'javaEE', 100);

INSERT INTO course
VALUES
    (51, 'linux', 1);

-- 建立選課表
CREATE TABLE studCourse (
    stuCourseId INT AUTO_INCREMENT PRIMARY KEY,
    -- 這是一個自增的,表示一次選課
    sid INT REFERENCES student (sid),
    -- 學生號
    cid INT REFERENCES course (cid),
    -- 課程號
    grade INT NOT NULL -- 成績
);

-- 初始化數據
INSERT INTO studCourse (sid, cid, grade)
VALUES
    (20040001, 11, 90);

INSERT INTO studCourse (sid, cid, grade)
VALUES
    (20040001, 21, 19);

INSERT INTO studCourse (sid, cid, grade)
VALUES
    (20050003, 21, 45);

INSERT INTO studCourse (sid, cid, grade)
VALUES
    (20050004, 41, 99);

INSERT INTO studCourse (sid, cid, grade)
VALUES
    (20050006, 11, 39);

此時數據庫中的數據如下:

這裏寫圖片描述

建立項目HibernateHQL

我們使用Hibernate自動生成domain對象和映射文件,如果我們的表有主外鍵的關係,應該先映射主表,再映射從表。

另外,在IntelliJ IDEA中,需要手動配置一對多,或者多對一、多對多的關係。

當然,首先我們需要先配置好數據源,建好domain對象存放的包。建數據源的步驟可以參考Hibernate——入門

(1) 使用Hibernate Persistence 工具,選中我們要映射的表及其字段

這裏寫圖片描述

這裏最重要的一點是,我們不能勾選studCourse表中的sid字段和cid字段,因爲在生成的StudCoursedomain對象中,這兩個字段會對應生成Student對象和Course對象。這在接下來配置一對多關係的時候就會看到。

(2) 配置一對多和多對一的關係,也就是我們的表所對應的外鍵關係

首先,studentstudCourse是一對多的關係,一個student可以對應多個studCourse;反過來,studCoursestudent是多對一的關係,即多個studCourse可以對應一個student

在Hibernate中,這樣的關係在domain對象中表現爲,StudCourse對象有一個Student屬性,即一個StudCourse對象對應一個Student對象,這個Student對象根據studCourse表的外鍵字段sid生成。Student對象【可以】有一個Set<StudCourse>集合,表示一個Student對象對應多個StudCourse對象。這裏用了【可以】一詞,其實是爲了說,不一定是Set<StudCourse>,也可以是List<StudCourse>

還是在剛纔的界面,我們選中studCourse表,然後點擊表格上方的加號。

這裏寫圖片描述

在彈出來的界面中配置StudentStudCourse的關係。

這裏寫圖片描述

同樣的,與StudentStudCourse類似,我們配置CourseStudCourse的關係。

這裏寫圖片描述

最後,在我們的配置界面,我們可以看到剛纔配置的關係,這裏可以檢查一下是否有錯誤。

這裏寫圖片描述

確認無誤後,我們點擊確定就可以了。此時,IDEA會幫我們自動在com.gavin.domain包下生成3個domain對象和3個映射文件。

如下圖:

這裏寫圖片描述

此時我們的3個domain對象分別如下:

public class Student {
    private int sid;
    private String sname;
    private String ssex;
    private String sdept;
    private Integer sage;
    private String saddress;
    private Set<StudCourse> studcourse;

    // ... 省略其他方法
}

public class Course {
    private int cid;
    private String cname;
    private Integer ccredit;
    private Set<StudCourse> studcourse;

    // ... 省略其他方法
}

public class StudCourse {
    private int stuCourseId;
    private int grade;
    private Student student;
    private Course course;

    // ... 省略其他方法
}

可以看到,Student類和Course類都包含一個Set集合,集合裏保存着StudCourse對象。而StudCourse對象中包含一個Student對象和一個Course對象。這正好對應我們上面所講述的一對多和多對一的關係。

此時hibernate.cfg.xml文件如下,記得要配置數據庫的用戶名和密碼,以及數據庫方言。

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">gavin</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <mapping resource="com/gavin/domain/Course.hbm.xml"/>
        <mapping resource="com/gavin/domain/StudCourse.hbm.xml"/>
        <mapping resource="com/gavin/domain/Student.hbm.xml"/>

        <!-- DB schema will be updated if needed -->
        <!-- <property name="hbm2ddl.auto">update</property> -->
    </session-factory>
</hibernate-configuration>

HQL語法

一個工具類:HibernateSessionFactory

HibernateSessionFactory類設計成單例的,並且將Session與線程綁定。

package com.gavin.util;

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

public class HibernateSessionFactory {
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<>();
    private static org.hibernate.SessionFactory sessionFactory;

    static {
        sessionFactory = new Configuration().configure().buildSessionFactory();
    }

    /**
     * 單例
     */
    private HibernateSessionFactory() {
    }

    public static Session getSession() throws HibernateException {
        Session session = threadLocal.get();

        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession()
                    : null;
            threadLocal.set(session);
        }

        return session;
    }

    public static void rebuildSessionFactory() {
        try {
            sessionFactory = new Configuration().configure().buildSessionFactory();
        } catch (Exception e) {
            System.err.println("%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }

    public static void closeSession() throws HibernateException {
        Session session = threadLocal.get();
        threadLocal.set(null);

        if (session != null) {
            session.close();
        }
    }

    public static org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

測試

  • 1. 查詢所有學生信息,並輸出其選課信息。
package com.gavin.view;

import com.gavin.domain.Course;
import com.gavin.domain.StudCourse;
import com.gavin.domain.Student;
import com.gavin.util.HibernateSessionFactory;
import org.hibernate.Session;
import org.hibernate.Transaction;

import java.util.List;

public class TestMain {

    public static void main(String[] args) {
        queryAll();
    }

    public static void queryAll() {
        Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateSessionFactory.getSession();
            transaction = session.beginTransaction();
            // 1.檢索所有學生
            List<Student> list = session.createQuery("from Student").list();
            transaction.commit();

            for (Student student : list) {
                int size = student.getStudcourse().size();
                if (size == 0) {
                    System.out.println(student.getSname() + "沒有選課");
                }else{
                    System.out.println(student.getSname() + "選了" + size + "門課");
                    for (StudCourse studCourse : student.getStudcourse()) {
                        Course course = studCourse.getCourse();
                        System.out.println(course.getCname()+ " ");
                    }
                    System.out.println();
                }
            }
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            throw new RuntimeException(e);
        }finally {
            HibernateSessionFactory.closeSession();
        }
    }
}

如上述代碼所示,我們使用HQL語句from Student就可以查詢所有的學生信息,並不需要select *。並且將查詢結果直接封裝成對象,通過list()方法返回查詢結果列表。不過要注意的是,這裏的Student指的是Student對象,而不是數據庫中的表名,數據庫中的表名是小寫。

我們查詢出來的不止學生基本信息,還包括其選課信息,因爲Student對象中有Set<StudCourse>對象,所以我們連帶着將選課信息也可以查出來。下面是運行結果:

林青霞選了2門課
c++課程 
java編程 

劉德華沒有選課
成龍選了1門課
c++課程 

林可欣選了1門課
javaEE 

周華健沒有選課
周潤發選了1門課
java編程 

從這個示例中我們可以看到Hibernate極大地簡化了我們的查詢過程,在配置好Hibernate之後,我們可以直接對對象進行查詢,並直接返回查詢出來的對象。

  • 2. 查詢部分屬性
public static void querySome(){
    Session session = null;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        // 1.檢索學生的名字和所在系
        // JDBC是要查詢什麼字段就查詢什麼字段,而不要select * from 表
        // 但Hibernate建議我們把對象的所有屬性都查詢出來,這樣才能封裝成一個完整的對象
        // 這裏進行演示查詢部分屬性
        List<Object[]> list = session.createQuery("select sname, sdept from Student").list();
        for (Object[] objects: list) {
            System.out.println(objects[0] + " " + objects[1]);
        }
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

Hibernate不建議我們查詢部分屬性,而是建議我們把對象的所有屬性都查詢出來,這樣才能封裝成一個完整的對象。

要注意的是,select sname, sdept from Student這句話中的snamesdept都是Student對象的屬性名,而不是數據庫表的字段。

林青霞 計算機系
劉德華 外語系
成龍 化學系
林可欣 計算機系
周華健 生物系
周潤發 數學系
  • 3. 根據條件查詢一個單獨的對象
public static void queryOne() {
    Session session = null;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();

        Student student = (Student) session.createQuery("from Student where sid = " + 20050003).uniqueResult();
        System.out.println("student = " + student);
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

HQL也支持where條件查詢,上述示例,我們查詢sid爲20050003的學生,並通過uniqueResult()方法直接返回一個單獨的結果。輸出如下:

student = Student{sid=20050003, sname='成龍', ssex='M', sdept='化學系', sage=21, saddress='山東'}
  • 4. 結果去重
public static void queryDistinct() {
    Session session = null;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();

        List<String> list = session.createQuery("select distinct ssex from Student").list();
        for (String str : list) {
            System.out.println(str);
        }
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

HQL也可以通過distinct關鍵字對結果去重。

F
M
  • 5. between關鍵字
public static void queryBetween() {
    Session session = null;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        List<Student> list = session.createQuery("from Student where sage between 20 and 22").list();
        for (Student student : list) {
            System.out.println(student);
        }
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

HQL語句也可以在where條件中使用between關鍵字。上例查出所有年齡在20和22之間的學生。

Student{sid=20040001, sname='林青霞', ssex='F', sdept='計算機系', sage=22, saddress='上海'}
Student{sid=20050003, sname='成龍', ssex='M', sdept='化學系', sage=21, saddress='山東'}
Student{sid=20050004, sname='林可欣', ssex='F', sdept='計算機系', sage=22, saddress='北京'}
Student{sid=20050006, sname='周潤發', ssex='M', sdept='數學系', sage=20, saddress='湖北'}
  • 6. in關鍵字
public static void queryIn(){
    Session session;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        List<Student> list = session.createQuery("from Student where sage not in (22, 23)").list();
        list.forEach(student -> System.out.println("student = " + student));
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

HQL語句的where條件中也可以使用in關鍵字,上例查出年齡不是22和23歲的學生。

student = Student{sid=20050003, sname='成龍', ssex='M', sdept='化學系', sage=21, saddress='山東'}
student = Student{sid=20050005, sname='周華健', ssex='M', sdept='生物系', sage=24, saddress='山東'}
student = Student{sid=20050006, sname='周潤發', ssex='M', sdept='數學系', sage=20, saddress='湖北'}
  • 6. group by分組查詢
public static void queryGroupBy(){
    Session session;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        List<Object[]> list = session.createQuery("select avg(sage), sdept from Student group by sdept").list();
        list.forEach(objects -> System.out.println("Arrays.toString(objects) = " + Arrays.toString(objects)));
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

HQL也可以進行group by分組,上例通過分組查出了每個系的平均年齡。

Arrays.toString(objects) = [21.0, 化學系]
Arrays.toString(objects) = [23.0, 外語系]
Arrays.toString(objects) = [20.0, 數學系]
Arrays.toString(objects) = [24.0, 生物系]
Arrays.toString(objects) = [22.0, 計算機系]
  • 7. group by having 分組查詢並過濾
public static void queryGroupByHaving(){
    Session session;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        // 查詢平均年齡不小於22歲的系
        List<Object[]> list = session.createQuery("select avg(sage), sdept" +
                " from Student group by sdept having avg(sage) >= 22 ").list();
        list.forEach(objects -> System.out.println("Arrays.toString(objects) = " + Arrays.toString(objects)));

        // 查詢各個系的女生人數,並過濾出女生人數大於1個的系
        list = session.createQuery("select count(ssex), sdept" +
                " from Student where ssex='F' group by sdept having count(ssex) >1").list();
        list.forEach(objects -> System.out.println("Arrays.toString(objects) = " + Arrays.toString(objects)));

        // 查詢計算機系的人數
        List<Long> list1 = session.createQuery("select count(*)" +
                " from Student where sdept='計算機系'").list();
        list1.forEach(objects -> System.out.println("Arrays.toString(objects) = " + (objects)));

        // 查詢11號課程的最高分和最低分
        list = session.createQuery("select 11, max(grade), min(grade) from StudCourse where course.cid=11").list();
        list.forEach(objects -> System.out.println("Arrays.toString(objects) = " + Arrays.toString(objects)));

        // 查詢各科考試不及格學生的姓名,科目與成績
        // 在這裏,HQL語句比SQL簡單多了
        list = session.createQuery("select student.sname, course.cname, grade from StudCourse where grade >= 60").list();
        list.forEach(objects -> System.out.println("Arrays.toString(objects) = " + Arrays.toString(objects)));

        // 查詢各個系不及格的學生人數
        list = session.createQuery("select count(*), student.sdept from StudCourse where grade < 60 group by student.sdept").list();
        list.forEach(objects -> System.out.println("Arrays.toString(objects) = " + Arrays.toString(objects)));

        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

上例示範了使用group by having語法進行分組查詢並過濾。輸出如下:

Arrays.toString(objects) = [23.0, 外語系]
Arrays.toString(objects) = [24.0, 生物系]
Arrays.toString(objects) = [22.0, 計算機系]
Arrays.toString(objects) = [2, 計算機系]
Arrays.toString(objects) = 0
Arrays.toString(objects) = [11, 90, 39]
Arrays.toString(objects) = [林青霞, java編程, 90]
Arrays.toString(objects) = [林可欣, javaEE, 99]
Arrays.toString(objects) = [1, 化學系]
Arrays.toString(objects) = [1, 數學系]
Arrays.toString(objects) = [1, 計算機系]
  • 8. order by 對結果進行排序
public static void queryOrderBy(){
    Session session;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        List<Student> list = session.createQuery("from Student order by sage").list();
        list.forEach(student -> System.out.println("student = " + student));
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

HQL支持通過order by對結果進行排序。上例將學生按照年齡進行排序。

student = Student{sid=20050006, sname='周潤發', ssex='M', sdept='數學系', sage=20, saddress='湖北'}
student = Student{sid=20050003, sname='成龍', ssex='M', sdept='化學系', sage=21, saddress='山東'}
student = Student{sid=20040001, sname='林青霞', ssex='F', sdept='計算機系', sage=22, saddress='上海'}
student = Student{sid=20050004, sname='林可欣', ssex='F', sdept='計算機系', sage=22, saddress='北京'}
student = Student{sid=20040002, sname='劉德華', ssex='M', sdept='外語系', sage=23, saddress='南京'}
student = Student{sid=20050005, sname='周華健', ssex='M', sdept='生物系', sage=24, saddress='山東'}
  • 9. 分頁查詢
public static void queryByPage(int pageSize){
    // 按照學生年齡從小到大取出第1個到到第3個學生
    Session session;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        long size = (Long) session.createQuery("select count(*) from Student").uniqueResult();
        long pageCount = (size -1) / pageSize + 1;
        for (int i = 0; i < pageCount; i++) {
            System.out.println("**********第 " + i + " 頁*************");
            List<Student> list = session.createQuery("from Student order by sage").setFirstResult(pageSize * i)
                    .setMaxResults(pageSize).list();
            list.forEach(student -> System.out.println("student = " + student));
        }
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

分頁查詢在日常開發中需求很廣泛,上例示範了通過HQL進行分頁查詢。輸入pageSize等於2,輸出如下:

**********第 0 頁*************
student = Student{sid=20050006, sname='周潤發', ssex='M', sdept='數學系', sage=20, saddress='湖北'}
student = Student{sid=20050003, sname='成龍', ssex='M', sdept='化學系', sage=21, saddress='山東'}
**********第 1 頁*************
student = Student{sid=20040001, sname='林青霞', ssex='F', sdept='計算機系', sage=22, saddress='上海'}
student = Student{sid=20050004, sname='林可欣', ssex='F', sdept='計算機系', sage=22, saddress='北京'}
**********第 2 頁*************
student = Student{sid=20040002, sname='劉德華', ssex='M', sdept='外語系', sage=23, saddress='南京'}
student = Student{sid=20050005, sname='周華健', ssex='M', sdept='生物系', sage=24, saddress='山東'}
  • 10. 給查詢語句設置參數

下例演示了給HQL語句傳遞參數的兩種方式。

public static void querySetParameter(){
    Session session;
    Transaction transaction = null;
    try {
        session = HibernateSessionFactory.getSession();
        transaction = session.beginTransaction();
        // 第一種傳遞參數的方法
        // Query query = session.createQuery("from Student where sdept =:sdept and sage > :sage");
        // query.setParameter("sdept","計算機系");
        // query.setParameter("sage", 20);

        // 第二種傳遞參數的方法
        Query query = session.createQuery("from Student where sdept = ? and sage > ?");
        query.setParameter(0,"計算機系");
        query.setParameter(1, 20);
        List<Student> list = query.list();
        list.forEach(student -> System.out.println("student = " + student));
        transaction.commit();
    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        throw new RuntimeException(e);
    }finally {
        HibernateSessionFactory.closeSession();
    }
}

到此,我們已經發現了上述代碼存在很多冗餘,所以我們可以把相同的代碼抽取出來,寫一個專門的工具類來負責統一的查詢、更新等。

下面是一個完整的工具類HibernateUtil

package com.gavin.util;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;

import java.util.List;

public class HibernateUtil {
    /**
     * 提供一個統一的查詢方法
     * @param hql hql語句
     * @param parameters 參數數組
     * @return List結果列表
     */
    public static List executeQuery(String hql, Object[] parameters) {
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery(hql);
        if (parameters != null) {
            for (int i = 0; i < parameters.length; i++) {
                query.setParameter(i, parameters[i]);
            }
        }
        return query.list();
    }

    /**
     * 提供一個統一的帶分頁的查詢方法
     * @param hql hql語句
     * @param parameters 參數數組
     * @param pageSize 每一頁的大小
     * @param pageNow 當前的頁數
     * @return 結果列表
     */
    public static List executeQueryByPage(String hql, Object[] parameters, int pageSize, int pageNow) {
        Session session = HibernateSessionFactory.getSession();
        Query query = session.createQuery(hql);
        if (parameters != null) {
            for (int i = 0; i < parameters.length; i++) {
                query.setParameter(i, parameters[i]);
            }
        }
        query.setFirstResult((pageNow - 1) * pageSize).setMaxResults(pageSize);
        return query.list();
    }

    /**
     * 提供一個統一的保存對象方法
     * @param object 對象
     */
    public static void save(Object object) {
        Session session = HibernateSessionFactory.getSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            session.save(object);
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * 一個統一的更新方法
     * @param hql hql語句
     * @param parameters 參數列表
     */
    public static void executeUpdate(String hql, Object[] parameters) {
        Session session = HibernateSessionFactory.getSession();
        Transaction transaction = null;
        Query query;
        try {
            transaction = session.beginTransaction();
            query = session.createQuery(hql);
            if (parameters != null) {
                for (int i = 0; i < parameters.length; i++) {
                    query.setParameter(i, parameters[i]);
                }
            }
            query.executeUpdate();
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            throw new RuntimeException(e);
        }
    }
}

現在的項目結構圖如下:

這裏寫圖片描述


接下來,是我們通過工具類進行查詢的一些示例:

public static void query(){
    String hql = "select student.sname, student.sdept from StudCourse where course.cid=?";
    Object[] objects = new Object[]{21};
    List<Object[]> list = HibernateUtil.executeQuery(hql, objects);
    list.forEach(obj -> System.out.println(Arrays.toString(obj)));

    hql = "from StudCourse where course.cid = 21";
    List<StudCourse> l = HibernateUtil.executeQuery(hql, null);
    for (StudCourse studcourse : l) {
        System.out.println("studCourse.getGrade() = " + studcourse.getGrade());
        Student s = studcourse.getStudent();
        System.out.println("s = " + s);
    }
}

public static void update(){
    String hql = "update Course set cid = cid - 1";
    HibernateUtil.executeUpdate(hql, null);
}

public static void add() {
    Course course = new Course();
    course.setCid(111);
    course.setCname("MySQL");
    course.setCcredit(4);
    HibernateUtil.save(course);
}

public static void queryByPageByUtil(){
    String hql = "from Student";
    List<Student> list = HibernateUtil.executeQueryByPage(hql, null, 2, 2);
    list.forEach(student -> System.out.println("student = " + student));
}

public static void queryByUtil() {
    String hql = "from Student where sdept = ? and sage > ?";
    Object[] parameters = new Object[]{"計算機系", 20};
    List<Student> list = HibernateUtil.executeQuery(hql, parameters);
    list.forEach(student -> System.out.println("student = " + student));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章