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:自动更新数据库表结构(可选项包括none、validate、update、create、create-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 特性
- @Column:用于自定义列属性。
- @OneToOne、@OneToMany、@ManyToOne、@ManyToMany:用于定义实体间关系。
- @JoinColumn:指定关联表的外键字段。
- @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.properties 或 application.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 关系映射(级联操作)
假设 User 与 Address 有一对一关系,在创建实体时可以用注解来指定级联操作。
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();
}
}


![表情[baoquan]-拾光赋](https://blogs.ink/wp-content/themes/zibll/img/smilies/baoquan.gif)


暂无评论内容