Hibernate(27)Hibernate的查询策略是什么?

Hibernate的查询策略

Hibernate的查询策略决定了如何从数据库中检索数据。它包括多种策略,如即时加载(Eager Loading)、延迟加载(Lazy Loading)和批量检索(Batch Fetching)等。这些策略可以显著影响应用程序的性能和内存使用,因此了解和选择合适的查询策略非常重要。

主要查询策略

  1. 即时加载(Eager Loading):在加载实体时,同时加载其关联的实体。
  2. 延迟加载(Lazy Loading):只有在访问关联实体时,才加载该实体。
  3. 批量检索(Batch Fetching):在一次查询中加载多个关联的实体。

配置查询策略的方式

  1. 在映射文件或注解中配置
  2. 在查询中指定(如HQL或Criteria查询)

示例代码

配置文件 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.Person"/>
        <mapping class="com.example.domain.Address"/>
    </session-factory>
</hibernate-configuration>

实体类 PersonAddress

Person类
java 复制代码
package com.example.domain;

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

@Entity
@Table(name = "person")
public class Person {

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

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

    @Column(name = "age")
    private int age;

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<Address> addresses = new HashSet<>();

    public Person() {}

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Set<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(Set<Address> addresses) {
        this.addresses = addresses;
    }
}
Address类
java 复制代码
package com.example.domain;

import javax.persistence.*;

@Entity
@Table(name = "address")
public class Address {

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

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

    @ManyToOne
    @JoinColumn(name = "person_id", nullable = false)
    private Person person;

    public Address() {}

    public Address(String street, Person person) {
        this.street = street;
        this.person = person;
    }

    // Getters 和 Setters
    
    public Long getId() {
        return id;
    }

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

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

即时加载和延迟加载示例

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;
    }
}

即时加载示例

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

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

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

        // 即时加载示例
        eagerLoadingExample(sessionFactory);

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

    private static void insertData(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        try {
            Person person = new Person("John Doe", 30);
            Address address1 = new Address("123 Street", person);
            Address address2 = new Address("456 Avenue", person);
            person.getAddresses().add(address1);
            person.getAddresses().add(address2);

            session.save(person);
            transaction.commit();
            System.out.println("Inserted Person and Addresses");
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    private static void eagerLoadingExample(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            // 获取Person实体,并同时加载其关联的Address实体(即时加载)
            Person person = session.get(Person.class, 1L);
            if (person != null) {
                System.out.println("Person: " + person.getName());
                for (Address address : person.getAddresses()) {
                    System.out.println("Address: " + address.getStreet());
                }
            } else {
                System.out.println("No Person found with ID 1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

延迟加载示例

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

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

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

        // 延迟加载示例
        lazyLoadingExample(sessionFactory);

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

    private static void insertData(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        try {
            Person person = new Person("John Doe", 30);
            Address address1 = new Address("123 Street", person);
            Address address2 = new Address("456 Avenue", person);
            person.getAddresses().add(address1);
            person.getAddresses().add(address2);

            session.save(person);
            transaction.commit();
            System.out.println("Inserted Person and Addresses");
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    private static void lazyLoadingExample(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            // 获取Person实体,此时不会立即加载其关联的Address实体(延迟加载)
            Person person = session.get(Person.class, 1L);
            if (person != null) {
                System.out.println("Person: " + person.getName());
                // 访问关联的Address实体时才会触发加载
                for (Address address : person.getAddresses()) {
                    System.out.println("Address: " + address.getStreet());
                }
            } else {
                System.out.println("No Person found with ID 1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

批量检索示例

批量检索通过在查询中使用@BatchSize注解或Hibernate的配置文件中的相应属性来实现。

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

import org.hibernate.annotations.BatchSize;

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

@Entity
@Table(name = "person")
@BatchSize(size = 10)
public class Person {

 
相关推荐
㳺三才人子5 小时前
初探 Flask
后端·python·flask·html
星栈独行5 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Java爱好狂.5 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
陈随易6 小时前
Redis 8.8发布,一定要更新
前端·后端·程序员
装不满的克莱因瓶6 小时前
SpringBoot 如何将 lib 目录中jar包打包进最终的jar包里面
spring boot·后端·maven·jar·mvn
ltl7 小时前
Transformer 原论文实验结果:为什么 28.4 BLEU 足以改写路线图
后端
excel7 小时前
为什么我推荐使用 Termius:现代 SSH 工具的完整体验
前端·后端
卷毛的技术笔记8 小时前
Java后端硬核实战:用Spring AI Alibaba+Redis给LLM装上“超强记忆中枢”
java·人工智能·redis·后端·spring·ai·系统架构
IT_陈寒9 小时前
Java的Optional差点让我掉坑里,这几个坑你别踩
前端·人工智能·后端
子兮曰9 小时前
Harness 驾驭工程深度教程:从 AGENTS.md 到全链路 AI 编码基础设施
前端·后端·ai编程