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));
}
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页