JPA —-( java persistent api) java持久化接口规范


1. 什么是 JPA?

JPA(Java Persistence API)是 Java 官方的 ORM 规范,提供了一套用于对象关系映射(Object-Relational Mapping)的标准。JPA 定义了如何将 Java 对象(实体)持久化到关系数据库中,但它本身没有具体的实现,常见的实现包括 Hibernate、EclipseLink 等。

1.1 JPA 的核心概念

  • Entity(实体):Java 类与数据库表的映射关系,通过 @Entity 注解声明。
  • EntityManager:负责实体的生命周期管理(如新增、查询、更新、删除),相当于数据库的操作接口。
  • Entity Transaction:用于控制事务。JPA 使用 @Transactional 注解来管理事务。
  • JPQL(Java Persistence Query Language):JPA 提供的一种类似 SQL 的查询语言,用于查询实体数据。

2. 常见的 JPA 实现框架

虽然 JPA 提供了一套标准接口,但并没有实现。市场上有几种常见的 JPA 实现框架,其中 Hibernate 是最常用的。

2.1 Hibernate

Hibernate 是一种 Java ORM 框架,是 JPA 的一种流行实现。它不仅支持 JPA 标准,还提供了一些 JPA 规范中没有的高级特性,如缓存、延迟加载等。

Hibernate 特点
  • 透明持久化:自动管理对象到数据库之间的转换。
  • 缓存支持:分为一级缓存(session 缓存)和二级缓存(session 工厂级缓存),提高了性能。
  • 级联操作:支持级联操作管理(如 @Cascade),可以控制关联对象的保存或删除。

3. JPA 与 Spring Boot 的整合

Spring Boot 提供了 spring-boot-starter-data-jpa 依赖,可以简化与 JPA(特别是 Hibernate)之间的整合。Spring Data JPA 框架基于 JPA 提供了一套 Repository 模型,可以自动生成常用的数据库操作代码。

3.1 添加依赖

pom.xml 中添加 JPA 和数据库驱动依赖:

<dependencies>
    <!-- Spring Data JPA Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- 数据库驱动(以 MySQL 为例) -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

3.2 配置数据库连接

application.properties 中配置数据库相关属性:

spring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC
spring.datasource.username=your_username
spring.datasource.password=your_password

# Hibernate 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
  • spring.jpa.hibernate.ddl-auto:自动更新数据库表结构(可选项包括 nonevalidateupdatecreatecreate-drop)。
  • spring.jpa.show-sql:显示 SQL 语句。

3.3 创建实体类(Entity)

实体类是 Java 类和数据库表的映射,Spring Data JPA 使用 @Entity 注解标记为数据库表,并通过 @Id 标记主键。

示例:User 实体类

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

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

    private String name;
    private String email;

    // Getters and Setters
}

3.4 创建 Repository 接口

Spring Data JPA 通过 Repository 接口提供 CRUD 操作。只需继承 JpaRepository 接口即可使用。

示例:UserRepository

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
   
    User findByName(String name);
}
  • JpaRepository:Spring Data JPA 提供的基础接口,包含 CRUD 方法。
  • findByName:JPA 支持根据字段命名规则生成查询方法。这里通过 name 字段查找用户。

3.5 编写 Service 层

Service 层负责业务逻辑,通过 @Autowired 注入 Repository。

示例:UserService

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserService {
   
    @Autowired
    private UserRepository userRepository;

    public User saveUser(User user) {
   
        return userRepository.save(user);
    }

    public List<User> getAllUsers() {
   
        return userRepository.findAll();
    }

    public User getUserByName(String name) {
   
        return userRepository.findByName(name);
    }
}

3.6 创建 Controller 层

Controller 层接收客户端请求并调用 Service 层,生成 RESTful API。

示例:UserController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
   
    @Autowired
    private UserService userService;

    @PostMapping
    public User createUser(@RequestBody User user) {
   
        return userService.saveUser(user);
    }

    @GetMapping
    public List<User> getAllUsers() {
   
        return userService.getAllUsers();
    }

    @GetMapping("/{name}")
    public User getUserByName(@PathVariable String name) {
   
        return userService.getUserByName(name);
    }
}

3.7 测试应用

可以通过 Postman 或其他工具来发送请求,例如:

  • POST /users:新增用户
  • GET /users:查询所有用户
  • GET /users/{name}:按用户名查询

4. 事务管理(Transaction Management)

Spring Boot 默认开启事务管理,可以使用 @Transactional 注解管理事务,控制数据的一致性和回滚。

示例:UserService 添加事务管理

import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
   
    @Transactional
    public void updateUserEmail(Long id, String newEmail) {
   
        User user = userRepository.findById(id).orElseThrow();
        user.setEmail(newEmail);
        userRepository.save(user);
    }
}
  • @Transactional:声明方法是事务性的,如果发生异常会自动回滚。

5. 常用注解与 JPA 特性

  1. @Column:用于自定义列属性。
  2. @OneToOne@OneToMany@ManyToOne@ManyToMany:用于定义实体间关系。
  3. @JoinColumn:指定关联表的外键字段。
  4. @Query:自定义查询,支持 JPQL 和原生 SQL。
  • JPA 是规范,Hibernate 是其常见实现。
  • Spring Data JPA 通过 Repository 接口简化了 CRUD 操作。
  • 配置数据库和实体映射后,可以轻松实现数据的持久化操作。
  • 事务管理通过 @Transactional 注解轻松实现。
和mybatis的区别

jpa规范的框架是实现了统一接口的框架,规范性强无需过多在于sql的编写,只需要关注业务层级的开发,而mybatis的灵魂在于动态sql,编写xml语句搭配动态sql更好的扩展颗粒度

但是mybatis-plus又往jpa的方向扩展了,可以使用继承的规范iservice也可以实现jpa,mybatis-plus也是选择了实现jpa的方式,接口规范向jpa靠拢

但是虽然现在国内的项目以及教学项目都很少使用hibernate 但是还是可以了解

Springboot整合hibernate

1. 使用 Hibernate 的 Spring Boot 项目初始化

首先,在 Spring Boot 项目中直接集成 Hibernate 实现 JPA 规范。Spring Boot 提供了自动配置来简化这个过程。

1.1 添加依赖

pom.xml 文件中添加 Hibernate、Spring Data JPA 及数据库驱动依赖:

<dependencies>
    <!-- Spring Boot JPA 支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
    </dependency>
</dependencies>

1.2 配置数据库连接

application.propertiesapplication.yml 中配置数据库连接信息:

spring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

1.3 创建实体类

使用 Hibernate 的注解创建实体类(如 @Entity@Id@GeneratedValue 等),这些注解均符合 JPA 规范:

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {
   
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
}

1.4 创建 JPA Repository 接口

使用 JpaRepository 提供基本的 CRUD 方法,省去繁琐的数据访问代码:

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
   
    // 可以自定义查询方法,如根据名字查找用户
    List<User> findByName(String name);
}

2. 基础 CRUD 操作

Spring Data JPA 提供了 save()findById()findAll()delete() 等方法,我们可以直接使用这些方法完成 CRUD 操作。

2.1 保存数据

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
   
    @Autowired
    private UserRepository userRepository;

    public User saveUser(User user) {
   
        return userRepository.save(user);
    }
}

2.2 查询数据

public Optional<User> getUserById(Long id) {
   
    return userRepository.findById(id);
}

public List<User> getAllUsers() {
   
    return userRepository.findAll();
}

2.3 更新数据

可以通过 save() 方法自动判断是否是更新:

public User updateUser(Long id, User user) {
   
    if (userRepository.existsById(id)) {
   
        user.setId(id); // 设置 ID 以更新指定用户
        return userRepository.save(user);
    }
    return null;
}

2.4 删除数据

public void deleteUser(Long id) {
   
    userRepository.deleteById(id);
}

3. 进阶功能

3.1 关系映射(级联操作)

假设 UserAddress 有一对一关系,在创建实体时可以用注解来指定级联操作。

import jakarta.persistence.*;

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

    @OneToOne(mappedBy = "address")
    private User user;
}

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

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "address_id")
    private Address address;
}

在使用 UserService 保存 User 时,Address 会被自动保存,这就是级联操作的作用。

3.2 缓存配置

Spring Boot 中可以通过二级缓存提高性能。在 application.properties 中添加如下配置:

spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.jcache.JCacheRegionFactory
spring.cache.jcache.provider=org.ehcache.jsr107.EhcacheCachingProvider

3.3 事务管理

Spring Boot 默认开启事务,可以用 @Transactional 注解在需要的业务方法上开启事务:

import org.springframework.transaction.annotation.Transactional;

@Transactional
public User updateUserWithTransaction(User user) {
   
    user.setName("Updated Name");
    userRepository.save(user);
    return user;
}

3.4 复杂查询:JPQL 和 Criteria API

JPQL 查询示例
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface UserRepository extends JpaRepository<User, Long> {
   
    @Query("SELECT u FROM User u WHERE u.email = :email")
    User findUserByEmail(@Param("email") String email);
}
Criteria 查询示例

Criteria API 允许动态构建查询条件,适合多条件查询场景:

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;

public List<User> getUsersByCriteria(String name) {
   
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<User> cq = cb.createQuery(User.class);
    Root<User> root = cq.from(User.class);
    cq.select(root).where(cb.equal(root.get("name"), name));
    return entityManager.createQuery(cq).getResultList();
}

4. 测试和验证

创建测试类来验证上述功能。使用 Spring Boot 提供的测试框架编写 CRUD 测试。

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserServiceTest {
   
    @Autowired
    private UserService userService;

    @Test
    public void testSaveUser() {
   
        User user = new User();
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");
        User savedUser = userService.saveUser(user);
        assertThat(savedUser.getId()).isNotNull();
    }
}

原文链接:JPA —-( java persistent api) java持久化接口规范

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容