Java Hibernate入门:第一个基于注解的ORM应用

#王者杯·14天创作挑战营·第1期#

在这里插入图片描述

引言

Hibernate是Java生态系统中最流行的对象关系映射(ORM)框架之一,它实现了JPA(Java Persistence API)规范,有效地解决了Java对象与关系型数据库之间的阻抗不匹配问题。通过Hibernate,开发者可以使用面向对象的方式操作数据库,而无需编写复杂的SQL语句和JDBC代码。自Hibernate 3.x版本起,注解成为了配置实体映射关系的主流方式,取代了早期的XML配置文件,使得代码更加简洁和直观。

Hibernate基础

ORM概念

对象关系映射是一种技术,它建立了Java对象和关系型数据库表之间的映射关系。ORM的核心目标是消除这两个不同范式之间的障碍,使开发者能够专注于对象模型的设计,而将数据持久化的细节交给框架处理。Hibernate作为一个成熟的ORM框架,提供了完整的对象生命周期管理、缓存机制、事务支持和查询功能,成为企业级应用开发的重要工具。

Hibernate优势

与传统的JDBC相比,Hibernate提供了诸多优势。首先,它减少了数据访问代码的开发量,显著提高了生产力。其次,Hibernate是数据库无关的,支持各种主流关系型数据库,提高了应用的可移植性。第三,Hibernate的缓存机制可以提升应用性能,减少数据库访问次数。最后,Hibernate支持懒加载、批处理和各种查询优化技术,使得应用能够高效地处理大量数据。

环境准备

项目依赖

要开始使用Hibernate,首先需要在项目中添加必要的依赖。对于Maven项目,可以在pom.xml文件中添加以下依赖:

<dependencies>
    <!-- Hibernate Core -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.6.5.Final</version>
    </dependency>
    
    <!-- 数据库驱动 (以MySQL为例) -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>
    
    <!-- 其他可能需要的依赖 -->
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
</dependencies>

数据库设置

为了示例的简单性,我们将使用MySQL数据库。创建一个名为hibernate_demo的数据库和一个用户表:

CREATE DATABASE hibernate_demo;
USE hibernate_demo;

CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    birth_date DATE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

基于注解的实体模型

Hibernate使用注解来定义Java类与数据库表之间的映射关系。让我们创建一个简单的User实体类:

package com.example.entity;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "users")
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "username", nullable = false, length = 50)
    private String username;
    
    @Column(name = "email", unique = true)
    private String email;
    
    @Temporal(TemporalType.DATE)
    @Column(name = "birth_date")
    private Date birthDate;
    
    @Column(name = "created_at", updatable = false)
    private Date createdAt;
    
    // 默认构造函数(JPA规范要求)
    public User() {
    }
    
    // 带参数的构造函数
    public User(String username, String email, Date birthDate) {
        this.username = username;
        this.email = email;
        this.birthDate = birthDate;
        this.createdAt = new Date();
    }
    
    // Getter和Setter方法
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getEmail() {
        return email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    
    public Date getBirthDate() {
        return birthDate;
    }
    
    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
    
    public Date getCreatedAt() {
        return createdAt;
    }
    
    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                ", birthDate=" + birthDate +
                ", createdAt=" + createdAt +
                '}';
    }
}

在这个实体类中,我们使用了以下JPA注解:

  • @Entity:标记这个类为JPA实体
  • @Table:指定映射的数据库表名
  • @Id:标记主键字段
  • @GeneratedValue:指定主键生成策略
  • @Column:定义字段映射,包括列名、约束等
  • @Temporal:指定日期类型的映射方式

Hibernate配置

配置文件

Hibernate需要一个配置文件来指定数据库连接信息和其他设置。创建一个名为hibernate.cfg.xml的文件,放在src/main/resources目录下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/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/hibernate_demo?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password</property>
        
        <!-- SQL方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
        
        <!-- 打印SQL -->
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        
        <!-- 自动创建/更新表结构 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        
        <!-- 命名策略 -->
        <property name="hibernate.physical_naming_strategy">org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl</property>
        
        <!-- 映射实体类 -->
        <mapping class="com.example.entity.User"/>
    </session-factory>
</hibernate-configuration>

这个配置文件指定了数据库连接信息、SQL方言、日志设置和自动表生成策略。hibernate.hbm2ddl.auto属性设置为update,表示Hibernate会在必要时自动更新表结构,但不会删除现有数据。

Hibernate工具类

为了简化Hibernate的使用,我们创建一个工具类来管理SessionFactory:

package com.example.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class HibernateUtil {
    private static StandardServiceRegistry registry;
    private static SessionFactory sessionFactory;
    
    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                // 创建标准服务注册表
                registry = new StandardServiceRegistryBuilder()
                        .configure() // 默认加载hibernate.cfg.xml
                        .build();
                
                // 创建元数据
                MetadataSources sources = new MetadataSources(registry);
                Metadata metadata = sources.getMetadataBuilder().build();
                
                // 创建会话工厂
                sessionFactory = metadata.getSessionFactoryBuilder().build();
            } catch (Exception e) {
                if (registry != null) {
                    StandardServiceRegistryBuilder.destroy(registry);
                }
                e.printStackTrace();
            }
        }
        return sessionFactory;
    }
    
    public static void shutdown() {
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(registry);
        }
    }
}

这个工具类负责创建和管理全局唯一的SessionFactory实例,SessionFactory是Hibernate的核心接口,用于创建Session对象。

使用Hibernate进行CRUD操作

现在我们可以使用Hibernate进行基本的CRUD(创建、读取、更新、删除)操作了。让我们创建一个简单的示例程序:

package com.example;

import com.example.entity.User;
import com.example.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class HibernateDemo {
    
    public static void main(String[] args) {
        // 创建用户
        User user1 = createUser("张三", "zhangsan@example.com", "1990-05-15");
        User user2 = createUser("李四", "lisi@example.com", "1985-12-20");
        
        // 查询所有用户
        List<User> users = getAllUsers();
        System.out.println("所有用户: ");
        for (User user : users) {
            System.out.println(user);
        }
        
        // 更新用户
        if (users.size() > 0) {
            User userToUpdate = users.get(0);
            updateUser(userToUpdate.getId(), "张三丰", userToUpdate.getEmail());
        }
        
        // 根据ID查询用户
        if (user1 != null) {
            User retrievedUser = getUserById(user1.getId());
            System.out.println("查询到的用户: " + retrievedUser);
        }
        
        // 删除用户
        if (user2 != null) {
            deleteUser(user2.getId());
        }
        
        // 再次查询所有用户
        users = getAllUsers();
        System.out.println("删除后的所有用户: ");
        for (User user : users) {
            System.out.println(user);
        }
        
        // 关闭SessionFactory
        HibernateUtil.shutdown();
    }
    
    // 创建用户
    private static User createUser(String username, String email, String birthDate) {
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            user.setBirthDate(dateFormat.parse(birthDate));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setCreatedAt(new Date());
        
        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            session.save(user);
            transaction.commit();
            return user;
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }
        return null;
    }
    
    // 获取所有用户
    private static List<User> getAllUsers() {
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            return session.createQuery("from User", User.class).list();
        }
    }
    
    // 根据ID查询用户
    private static User getUserById(Long id) {
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            return session.get(User.class, id);
        }
    }
    
    // 更新用户
    private static void updateUser(Long id, String newUsername, String newEmail) {
        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            
            User user = session.get(User.class, id);
            if (user != null) {
                user.setUsername(newUsername);
                user.setEmail(newEmail);
                session.update(user);
            }
            
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }
    }
    
    // 删除用户
    private static void deleteUser(Long id) {
        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            
            User user = session.get(User.class, id);
            if (user != null) {
                session.delete(user);
            }
            
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }
    }
}

这个示例程序演示了使用Hibernate进行基本的CRUD操作。通过Session接口,我们可以保存、获取、更新和删除实体对象,而无需编写SQL语句。Hibernate会自动生成并执行相应的SQL语句。

Hibernate查询

除了基本的CRUD操作外,Hibernate还提供了多种查询方式:

HQL (Hibernate Query Language)

HQL是Hibernate的面向对象查询语言,类似于SQL但操作的是对象而非表:

// 使用HQL查询
String hql = "FROM User u WHERE u.username LIKE :name ORDER BY u.id";
List<User> users = session.createQuery(hql, User.class)
        .setParameter("name", "张%")
        .list();

Criteria API

Criteria API提供了类型安全的、面向对象的查询方式:

// 使用Criteria API查询
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = builder.createQuery(User.class);
Root<User> root = criteriaQuery.from(User.class);
criteriaQuery.select(root)
        .where(builder.like(root.get("username"), "张%"))
        .orderBy(builder.asc(root.get("id")));
List<User> users = session.createQuery(criteriaQuery).list();

原生SQL

对于复杂查询,Hibernate也支持使用原生SQL:

// 使用原生SQL查询
String sql = "SELECT * FROM users WHERE username LIKE ?";
List<User> users = session.createNativeQuery(sql, User.class)
        .setParameter(1, "张%")
        .list();

总结

本文介绍了如何使用Hibernate创建基于注解的ORM应用程序。我们学习了Hibernate的基本概念、环境配置、实体映射以及基本的CRUD操作。与传统的JDBC相比,Hibernate大大简化了数据访问代码,提高了开发效率和代码可维护性。Hibernate的注解方式比早期的XML配置更加简洁和直观,将映射信息直接放在实体类中,使代码更加内聚。通过Session接口和各种查询API,Hibernate为开发者提供了丰富而灵活的数据访问方式,适应各种复杂的业务需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值