Hibernate(37)Hibernate的多表联合查询如何实现?

Hibernate的多表联合查询

在Hibernate中,多表联合查询(Join Query)用于从多个相关表中提取数据。通过使用HQL(Hibernate Query Language)或Criteria API,可以实现不同表之间的联接查询。

使用HQL进行多表联合查询的示例代码

首先,假设我们有两个实体类:StudentCourse,并且它们之间存在多对多的关系。

实体类定义

Student
java 复制代码
package com.example.domain;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "student_course", 
        joinColumns = { @JoinColumn(name = "student_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "course_id") }
    )
    private Set<Course> courses = new HashSet<>();

    public Student() {}

    public Student(String name) {
        this.name = name;
    }

    // Getters 和 Setters

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Course> getCourses() {
        return courses;
    }

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }
}
Course
java 复制代码
package com.example.domain;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "course")
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(mappedBy = "courses")
    private Set<Student> students = new HashSet<>();

    public Course() {}

    public Course(String name) {
        this.name = name;
    }

    // Getters 和 Setters

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

Hibernate配置文件 hibernate.cfg.xml

xml 复制代码
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
        <property name="hibernate.connection.username">your_username</property>
        <property name="hibernate.connection.password">your_password</property>

        <!-- Hibernate 属性配置 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- 映射类 -->
        <mapping class="com.example.domain.Student"/>
        <mapping class="com.example.domain.Course"/>
    </session-factory>
</hibernate-configuration>

HibernateUtil类

java 复制代码
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            // 从配置文件创建SessionFactory
            sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        } catch (Throwable ex) {
            // 记录启动失败的错误
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

使用HQL进行多表联合查询

插入示例数据

java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class HibernateInsertData {
    public static void main(String[] args) {
        // 获取SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        // 插入示例数据
        insertSampleData(sessionFactory);

        // 关闭SessionFactory
        sessionFactory.close();
    }

    private static void insertSampleData(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        try {
            // 创建学生
            Student student1 = new Student("John Doe");
            Student student2 = new Student("Jane Doe");

            // 创建课程
            Course course1 = new Course("Mathematics");
            Course course2 = new Course("History");

            // 建立多对多关系
            student1.getCourses().add(course1);
            student1.getCourses().add(course2);

            student2.getCourses().add(course1);
            student2.getCourses().add(course2);

            course1.getStudents().add(student1);
            course1.getStudents().add(student2);

            course2.getStudents().add(student1);
            course2.getStudents().add(student2);

            // 保存数据
            session.save(student1);
            session.save(student2);

            transaction.commit();
            System.out.println("Inserted sample data");
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

HQL联合查询示例

查询所有学生及其选修的课程
java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;

import java.util.List;

public class HibernateHQLJoinQueryExample {
    public static void main(String[] args) {
        // 获取SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        // 使用HQL进行联合查询
        queryStudentCourses(sessionFactory);

        // 关闭SessionFactory
        sessionFactory.close();
    }

    private static void queryStudentCourses(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            String hql = "SELECT s.name, c.name FROM Student s JOIN s.courses c";
            Query<Object[]> query = session.createQuery(hql, Object[].class);

            List<Object[]> results = query.list();
            System.out.println("Student and their Courses:");
            for (Object[] row : results) {
                String studentName = (String) row[0];
                String courseName = (String) row[1];
                System.out.println("Student: " + studentName + ", Course: " + courseName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

使用Criteria API进行多表联合查询

Criteria API联合查询示例

查询所有学生及其选修的课程
java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import java.util.List;

public class HibernateCriteriaJoinQueryExample {
    public static void main(String[] args) {
        // 获取SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        // 使用Criteria API进行联合查询
        queryStudentCourses(sessionFactory);

        // 关闭SessionFactory
        sessionFactory.close();
    }

    private static void queryStudentCourses(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
            CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class);
            Root<Student> studentRoot = criteriaQuery.from(Student.class);
            Join<Student, Course> courseJoin = studentRoot.join("courses");

            criteriaQuery.multiselect(studentRoot.get("name"), courseJoin.get("name"));

            List<Object[]> results = session.createQuery(criteriaQuery).getResultList();
            System.out.println("Student and their Courses:");
            for (Object[] row : results) {
                String studentName = (String) row[0];
                String courseName = (String) row[1];
                System.out.println("Student: " + studentName + ", Course: " + courseName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

详细解释

  1. 实体类定义
    • Student 类和 Course 类通过 @ManyToMany 注解来定义多对多的关系。Student 类使用 @JoinTable 注解来定义中间表,指定了关联的学生和课程的外键。
相关推荐
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于Springboot的酒店住宿信息管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
咖啡啡不加糖2 小时前
Grafana 监控服务指标使用指南:打造可视化监控体系
java·后端·grafana
gAlAxy...3 小时前
SpringBoot Servlet 容器全解析:嵌入式配置与外置容器部署
spring boot·后端·servlet
BYSJMG3 小时前
计算机毕业设计选题推荐:基于Hadoop的城市交通数据可视化系统
大数据·vue.js·hadoop·分布式·后端·信息可视化·课程设计
BYSJMG3 小时前
Python毕业设计选题推荐:基于大数据的美食数据分析与可视化系统实战
大数据·vue.js·后端·python·数据分析·课程设计·美食
东东5163 小时前
OA自动化居家办公管理系统 ssm+vue
java·前端·vue.js·后端·毕业设计·毕设
程序员鱼皮4 小时前
前特斯拉 AI 总监:AI 编程最大的谎言,是 “提效”
前端·后端·ai·程序员·开发
好好研究4 小时前
SpringBoot使用外置Tomcat
spring boot·后端·tomcat
索荣荣5 小时前
Spring Boot 实现DOCX转PDF(基于docx4j的轻量级开源方案)
spring boot·后端·pdf
mit6.8245 小时前
[todo]10个常见的后端框架
后端