目录
What Is JPA and Why Use Hibernate?
Setting Up JPA with Hibernate
Creating Your First Entity
Performing CRUD Operations
Relationships: One-to-Many Example
Best Practices and Common Pitfalls
Going Further: Spring Boot Integration
首页 Java java教程 Java坚持JPA和Hibernate:一个完整的教程

Java坚持JPA和Hibernate:一个完整的教程

Jul 26, 2025 am 05:13 AM
java

JPA 是 Java Persistence API 的缩写,是一种用于将 Java 对象映射到数据库表的标准规范,而 Hibernate 是其最流行的实现之一,提供了对象关系映射(ORM)功能,能够简化数据库操作。1. JPA 定义了实体映射和 CRUD 操作的标准,使开发者可以使用面向对象的方式操作数据库,避免编写大量 JDBC 代码。2. Hibernate 作为 JPA 的实现,不仅支持 JPA 规范,还提供缓存、懒加载、事务管理等高级特性。3. 使用 Maven 添加 hibernate-core 和数据库驱动(如 H2)依赖,并在 src/main/resources/META-INF/persistence.xml 中配置数据库连接和 Hibernate 属性,如 hbm2ddl.auto 控制表结构的生成策略。4. 通过 @Entity、@Table、@Id、@GeneratedValue、@Column 等注解定义实体类与数据库表的映射关系。5. 使用 EntityManager 进行 CRUD 操作,所有操作需在事务中进行,persist() 保存新实体,merge() 更新已有实体,find() 根据主键查询,remove() 删除实体。6. 支持实体间关系映射,如 @OneToMany 和 @ManyToOne 实现一对多关联,并通过 cascade 配置级联操作,确保关联数据同步保存或删除。7. 最佳实践包括:及时关闭 EntityManager 和 EntityManagerFactory 防止内存泄漏,重写 equals() 和 hashCode() 方法,优先使用 FetchType.LAZY 避免性能问题,使用 DTO 而非实体类暴露 API,避免 LazyInitializationException。8. 在 Spring Boot 项目中,推荐使用 Spring Data JPA,通过继承 JpaRepository 接口自动获得 CRUD 功能,由 Spring 管理配置、事务和依赖注入。9. 可通过 JPQL 查询如 SELECT u FROM User u LEFT JOIN FETCH u.posts 预加载关联数据,避免懒加载异常。10. 实际开发中应从小功能开始,逐步增加实体、关系和查询,结合实践深入掌握 JPA 与 Hibernate 的使用。你现在已经掌握了 JPA 和 Hibernate 的核心知识,能够构建高效的数据持久化 Java 应用。

Java Persistence with JPA and Hibernate: A Complete Tutorial

Java Persistence with JPA and Hibernate is a go-to combination for managing relational data in Java applications. Whether you're building a Spring Boot app or a standalone Java project, understanding how to persist data effectively is essential. This tutorial walks you through the fundamentals of JPA (Java Persistence API) and Hibernate — one of its most popular implementations — with practical examples and best practices.

Java Persistence with JPA and Hibernate: A Complete Tutorial

What Is JPA and Why Use Hibernate?

JPA (Java Persistence API) is a specification, not a concrete implementation. It defines how Java objects can be mapped to database tables, and how to perform CRUD (Create, Read, Update, Delete) operations using object-oriented syntax instead of raw SQL.

Hibernate is a full-featured, open-source ORM (Object-Relational Mapping) framework that implements the JPA specification. It adds extra features beyond JPA and handles the heavy lifting of translating Java objects to database records and vice versa.

Java Persistence with JPA and Hibernate: A Complete Tutorial

✅ Why use them together?

  • Write less boilerplate JDBC code
  • Work with Java objects instead of SQL queries
  • Leverage annotations for easy mapping
  • Support for advanced features like caching, lazy loading, and transactions

Setting Up JPA with Hibernate

To get started, you’ll need the right dependencies. Here’s how to set it up in a Maven project:

Java Persistence with JPA and Hibernate: A Complete Tutorial
<dependencies>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>6.4.4.Final</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>2.2.224</version>
    </dependency>
</dependencies>

We’re using H2 as an in-memory database for simplicity, but Hibernate supports MySQL, PostgreSQL, Oracle, and more.

Next, create a persistence.xml file in src/main/resources/META-INF/:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="3.0">
    <persistence-unit name="my-persistence-unit">
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:testdb"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

Key property:

  • hibernate.hbm2ddl.auto: update automatically creates or updates tables based on your entity classes. Use none, validate, or create-drop in production as needed.

Creating Your First Entity

An entity is a Java class mapped to a database table. Use JPA annotations to define the mapping.

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

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

    @Column(nullable = false)
    private String name;

    @Column(unique = true)
    private String email;

    // Constructors
    public User() {}

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getters and 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 String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    @Override
    public String toString() {
        return "User{"  
                "id="   id  
                ", name='"   name   '\''  
                ", email='"   email   '\''  
                '}';
    }
}

Annotations explained:

  • @Entity: Marks the class as a JPA entity.
  • @Table: Optional; customizes the table name.
  • @Id: Specifies the primary key.
  • @GeneratedValue: Tells Hibernate to auto-generate the ID.
  • @Column: Customize column definition (nullability, uniqueness, etc.).

Performing CRUD Operations

Use EntityManager to interact with the persistence context.

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
        EntityManager em = emf.createEntityManager();

        // Create
        em.getTransaction().begin();
        User user = new User("Alice", "alice@example.com");
        em.persist(user);
        em.getTransaction().commit();

        // Read
        User found = em.find(User.class, 1L);
        System.out.println("Found: "   found);

        // Update
        em.getTransaction().begin();
        found.setName("Alicia");
        em.merge(found);
        em.getTransaction().commit();

        // Delete
        em.getTransaction().begin();
        em.remove(found);
        em.getTransaction().commit();

        em.close();
        emf.close();
    }
}

? Note:

  • Always wrap database operations in transactions.
  • persist() saves a new entity; merge() updates a detached one.
  • find() retrieves an entity by ID.

Relationships: One-to-Many Example

Most real-world apps involve relationships. Let’s add Post entities linked to User.

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    // constructors, getters, setters...
}

Now, a User can have multiple posts:

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Post> posts = new ArrayList<>();

When you save a user with posts (and cascade is enabled), Hibernate saves the posts automatically.

User user = new User("Bob", "bob@example.com");
Post post1 = new Post("First Post");
Post post2 = new Post("Second Post");

post1.setUser(user);
post2.setUser(user);
user.getPosts().add(post1);
user.getPosts().add(post2);

em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();

This creates the user and both posts in a single transaction.


Best Practices and Common Pitfalls

Here are key tips to avoid common issues:

  • Always close EntityManager and EntityManagerFactory to prevent memory leaks.
  • Use equals() and hashCode() in entities — especially when using collections.
  • Avoid FetchType.EAGER by default; prefer FetchType.LAZY to prevent loading unnecessary data.
  • Don’t expose entities directly in APIs — use DTOs (Data Transfer Objects) instead.
  • Be cautious with cascade = CascadeType.ALL — it can accidentally delete related data.
  • Initialize lazy collections inside the transaction (before closing EntityManager), or use JOIN FETCH in queries.

Example of a JPQL query to fetch user with posts:

String jpql = "SELECT u FROM User u LEFT JOIN FETCH u.posts WHERE u.id = :id";
User user = em.createQuery(jpql, User.class)
              .setParameter("id", 1L)
              .getSingleResult();

This avoids the "LazyInitializationException".


Going Further: Spring Boot Integration

In real projects, especially with Spring Boot, you won’t use EntityManagerFactory directly. Instead:

  • Use Spring Data JPA for repository abstraction
  • Annotate your main class with @SpringBootApplication
  • Define repositories like:
public interface UserRepository extends JpaRepository<User, Long> {
}

Spring handles the rest — configuration, transactions, and dependency injection.


That’s it. You now have a solid foundation in JPA and Hibernate. From defining entities and relationships to performing CRUD and managing transactions, you're ready to build robust data-driven Java applications. The key is practice — try adding more entities, queries, and constraints to deepen your understanding.

Basically, just start small, let Hibernate do the work, and learn as you go.

以上是Java坚持JPA和Hibernate:一个完整的教程的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Stock Market GPT

Stock Market GPT

人工智能驱动投资研究,做出更明智的决策

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

如何在Java中的类Path中添加JAR文件? 如何在Java中的类Path中添加JAR文件? Sep 21, 2025 am 05:09 AM

使用-cp参数可将JAR加入类路径,使JVM能加载其内类与资源,如java-cplibrary.jarcom.example.Main,支持多JAR用分号或冒号分隔,也可通过CLASSPATH环境变量或MANIFEST.MF配置。

文件夹在哪里找 文件夹在哪里找 Sep 20, 2025 am 07:57 AM

最直接的方法是回忆保存位置,通常在桌面、文档、下载等文件夹;若找不到,可使用系统搜索功能。文件“失踪”多因保存路径未留意、名称记忆偏差、文件被隐藏或云同步问题。高效管理建议:按项目、时间、类型分类,善用快速访问,定期清理归档,并规范命名。Windows通过文件资源管理器和任务栏搜索查找,macOS则依赖访达和聚焦搜索(Spotlight),后者更智能高效。掌握工具并养成良好习惯是关键。

如何在Java中创建文件 如何在Java中创建文件 Sep 21, 2025 am 03:54 AM

UseFile.createNewFile()tocreateafileonlyifitdoesn’texist,avoidingoverwriting;2.PreferFiles.createFile()fromNIO.2formodern,safefilecreationthatfailsifthefileexists;3.UseFileWriterorPrintWriterwhencreatingandimmediatelywritingcontent,withFileWriterover

了解Java仿制药和通配符 了解Java仿制药和通配符 Sep 20, 2025 am 01:58 AM

Javagenericsprovidecompile-timetypesafetyandeliminatecastingbyallowingtypeparametersonclasses,interfaces,andmethods;wildcards(?,?extendsType,?superType)handleunknowntypeswithflexibility.1.UseunboundedwildcardwhentypeisirrelevantandonlyreadingasObject

Google Chrome无法加载此页面 Google Chrome无法加载此页面 Sep 20, 2025 am 03:51 AM

首先检查网络连接是否正常,若其他网站也无法打开则问题在网络;1.清除浏览器缓存和Cookies,进入Chrome设置选择清除浏览数据;2.关闭扩展程序,可通过无痕模式测试是否因插件冲突导致;3.检查并关闭代理或VPN设置,避免网络连接被拦截;4.重置Chrome网络设置,恢复默认配置;5.更新或重装Chrome至最新版本以解决兼容性问题;6.使用其他浏览器对比测试,确认问题是否仅限Chrome;根据错误提示如ERR_CONNECTION_TIMED_OUT或ERR_SSL_PROTOCOL_ER

UC浏览器如何强制缩放网页_UC浏览器网页强制缩放功能使用技巧 UC浏览器如何强制缩放网页_UC浏览器网页强制缩放功能使用技巧 Sep 24, 2025 pm 04:54 PM

首先启用UC浏览器内置缩放功能,进入设置→浏览设置→字体与排版或页面缩放,选择预设比例或自定义百分比;其次可通过双指张开或捏合手势强制调整页面显示大小;对于限制缩放的网页,可请求桌面版网站以解除限制;高级用户还可通过在地址栏执行JavaScript代码修改viewport属性,实现更灵活的强制缩放效果。

为什么实时系统需要确定性响应保障? 为什么实时系统需要确定性响应保障? Sep 22, 2025 pm 04:03 PM

实时系统需确定性响应,因正确性依赖结果交付时间;硬实时系统要求严格截止期限,错过将致灾难,软实时则允许偶尔延迟;非确定性因素如调度、中断、缓存、内存管理等影响时序;构建方案包括选用RTOS、WCET分析、资源管理、硬件优化及严格测试。

如何在Java中获取通话方法的名称? 如何在Java中获取通话方法的名称? Sep 24, 2025 am 06:41 AM

答案是使用Thread.currentThread().getStackTrace()获取调用方法名,通过索引2得到调用anotherMethod的someMethod名称,因索引0为getStackTrace、1为当前方法、2为调用者,示例输出“Calledbymethod:someMethod”,也可用Throwable实现,但需注意性能、混淆、安全及内联影响。

See all articles