Spring Data JPA学习笔记

Spring Data JPA学习

Spring Data JPA 是 Spring 框架中用于简化 JPA (Java Persistence API) 开发的模块,它提供了对 JPA 的抽象和增强,可以大幅减少数据访问层的样板代码。

包名:org.springframework.data.jpa

Persistence:持久化

核心概念

1. 主要组件

  • Repository 接口:Spring Data JPA 的核心接口,提供了基本的 CRUD 操作
  • JpaRepository:继承自 Repository,提供了更多 JPA 相关的方法
  • @Entity:标记一个类为 JPA 实体
  • @Id:标记实体类的主键字段
  • @GeneratedValue:指定主键生成策略

2. 基本使用

定义实体类(属性对应数据库表的字段)

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;
    
    // 构造方法、getter和setter
}

创建 Repository 接口(数据库访问层接口)

public interface UserRepository extends JpaRepository<User, Long> {
    // 可以添加自定义查询方法
}

使用 Repository

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    public User createUser(User user) {
        return userRepository.save(user);
    }
    
    public List<User> findAllUsers() {
        return userRepository.findAll();
    }
}

查询方法

Spring Data JPA 提供了强大的查询方法生成机制:

1. 方法名派生查询

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
    List<User> findByEmailContaining(String emailPart);
    List<User> findByNameAndEmail(String name, String email);
    List<User> findByNameOrderByEmailAsc(String name);
}

2. 使用 @Query 注解

@Query("SELECT u FROM User u WHERE u.email LIKE %?1%")
List<User> findByEmailLike(String email);

// 原生SQL查询
@Query(value = "SELECT * FROM users WHERE email LIKE %?1%", nativeQuery = true)
List<User> findByEmailLikeNative(String email);

3. 分页和排序

Page<User> findByName(String name, Pageable pageable);
List<User> findByName(String name, Sort sort);

使用示例:

Page<User> users = userRepository.findByName(
    "John", 
    PageRequest.of(0, 10, Sort.by("email").ascending())
);

高级特性

1. 规范模式 (Specification)

允许使用编程方式构建查询:

public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}

// 使用示例
Specification<User> spec = (root, query, cb) -> {
    return cb.and(
        cb.like(root.get("name"), "%John%"),
        cb.equal(root.get("active"), true)
    );
};
List<User> users = userRepository.findAll(spec);

2. 投影 (Projection)

可以只查询部分字段:

public interface UserNameOnly {
    String getName();
}

public interface UserRepository extends JpaRepository<User, Long> {
    List<UserNameOnly> findByName(String name);
}

3. 实体图 (EntityGraph)

解决 N+1 查询问题:

@EntityGraph(attributePaths = {"orders"})
List<User> findByName(String name);

事务管理

Spring Data JPA 默认在 Repository 方法上添加了 @Transactional 注解:

@Service
@Transactional
public class UserService {
    // 方法默认都有事务
}

常见配置

application.properties 配置示例

# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=secret

# JPA配置
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

最佳实践

  1. 尽量使用方法名派生查询,保持代码简洁
  2. 复杂查询使用 @Query 注解
  3. 注意事务边界,通常在服务层使用 @Transactional
  4. 对于关联查询,合理使用 FetchType 和 EntityGraph
  5. 考虑使用 DTO 投影来减少数据传输量

常见问题解决

  1. N+1 查询问题:使用 EntityGraph 或 JOIN FETCH 解决
  2. 延迟加载异常:确保在事务范围内访问延迟加载的属性
  3. 性能问题:合理使用批量操作和二级缓存

Spring Data JPA 极大地简化了数据访问层的开发,通过合理使用其特性,可以编写出既简洁又高效的持久层代码。

posted @ 2025-10-12 16:17  hqq的进阶日记  阅读(19)  评论(0)    收藏  举报