Hibernate(31)Hibernate的原生SQL查询是什么?

Hibernate的原生SQL查询

在某些情况下,HQL(Hibernate Query Language)或Criteria API可能无法满足复杂查询的需要,这时可以使用原生SQL查询(Native SQL Query)。原生SQL查询允许开发者直接编写SQL语句,并通过Hibernate执行这些语句,将结果映射为实体类或自定义结果集。

使用原生SQL查询

原生SQL查询主要分为两种:

  1. 实体查询:返回实体对象。
  2. 非实体查询:返回自定义对象或投影结果。

示例代码

实体类定义

我们将定义两个实体类:PersonAddress

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

import javax.persistence.*;

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

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

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.Person"/>
        <mapping class="com.example.domain.Address"/>
    </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;
    }
}

使用原生SQL查询示例

插入示例数据

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 {
            Person person1 = new Person("John Doe", 30);
            Person person2 = new Person("Jane Doe", 28);

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

使用原生SQL查询

查询所有Person记录
java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.NativeQuery;

import java.util.List;

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

        // 使用原生SQL查询所有Person记录
        queryAllPersons(sessionFactory);

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

    private static void queryAllPersons(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            String sql = "SELECT * FROM person";
            NativeQuery<Person> query = session.createNativeQuery(sql, Person.class);
            List<Person> persons = query.getResultList();
            System.out.println("Query all persons:");
            for (Person person : persons) {
                System.out.println(person.getName() + " - " + person.getAge());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}
使用投影查询返回自定义结果

假设我们只想查询Person的姓名和年龄,而不是整个实体,这时可以使用投影查询(Projection Query)。

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

import java.util.List;

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

        // 使用原生SQL投影查询
        queryPersonNameAndAge(sessionFactory);

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

    private static void queryPersonNameAndAge(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            String sql = "SELECT name, age FROM person";
            NativeQuery<Object[]> query = session.createNativeQuery(sql);
            List<Object[]> results = query.getResultList();
            System.out.println("Query person name and age:");
            for (Object[] row : results) {
                String name = (String) row[0];
                Integer age = (Integer) row[1];
                System.out.println(name + " - " + age);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

原生SQL查询详细解释

  1. 插入示例数据 :向数据库中插入两个Person对象供查询使用。

    java 复制代码
    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 {
                Person person1 = new Person("John Doe", 30);
                Person person2 = new Person("Jane Doe", 28);
    
                session.save(person1);
                session.save(person2);
                transaction.commit();
                System.out.println("Inserted sample data");
            } catch (Exception e) {
                if (transaction != null) {
                    transaction.rollback();
                }
                e.printStackTrace();
            } finally {
                if (session != null) {
                    session.close();
                }
            }
        }
    }
  2. 查询所有Person记录 :使用原生SQL查询所有Person记录并映射为Person实体。

    java 复制代码
    public class HibernateNativeQueryExample {
        public static void main(String[] args) {
            // 获取SessionFactory
            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    
            // 使用原生SQL查询所有Person记录
            queryAllPersons(sessionFactory);
    
            // 关闭SessionFactory
            sessionFactory.close();
相关推荐
_UMR_14 小时前
springboot集成Jasypt实现配置文件启动时自动解密-ENC
java·spring boot·后端
程序员小假14 小时前
我们来说说 Cookie、Session、Token、JWT
java·后端
短剑重铸之日14 小时前
《SpringBoot4.0初识》第一篇:前瞻与思想
java·开发语言·后端·spring·springboot4.0
it_czz15 小时前
LangSmith vs LangFlow vs LangGraph Studio 可视化配置方案对比
后端
蓝色王者15 小时前
springboot 2.6.13 整合flowable6.8.1
java·spring boot·后端
花哥码天下16 小时前
apifox登录后设置token到环境变量
java·后端
hashiqimiya17 小时前
springboot事务触发滚动与不滚蛋
java·spring boot·后端
TeamDev17 小时前
基于 Angular UI 的 C# 桌面应用
前端·后端·angular.js