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 {

 
相关推荐
Victor3563 小时前
Hibernate(29)什么是Hibernate的连接池?
后端
Victor3563 小时前
Hibernate(30)Hibernate的Named Query是什么?
后端
源代码•宸3 小时前
GoLang八股(Go语言基础)
开发语言·后端·golang·map·defer·recover·panic
czlczl200209253 小时前
OAuth 2.0 解析:后端开发者视角的原理与流程讲解
java·spring boot·后端
颜淡慕潇3 小时前
Spring Boot 3.3.x、3.4.x、3.5.x 深度对比与演进分析
java·后端·架构
布列瑟农的星空3 小时前
WebAssembly入门(一)——Emscripten
前端·后端
小突突突5 小时前
Spring框架中的单例bean是线程安全的吗?
java·后端·spring
iso少年5 小时前
Go 语言并发编程核心与用法
开发语言·后端·golang
掘金码甲哥5 小时前
云原生算力平台的架构解读
后端
码事漫谈5 小时前
智谱AI从清华实验室到“全球大模型第一股”的六年征程
后端