SpringData
Spring Data 是 Spring 的数据访问统一抽象:把"各种数据源"(关系库、Redis、MongoDB、ES)的 CRUD 收敛为"接口 + 方法名约定"。开发者只定义 Repository 接口,框架按方法名自动生成实现——findByName 自动变成按 name 字段查询,无需写 SQL/胶水代码。它解决"每种数据源一套 API"的碎片化问题,让业务代码与具体存储解耦。
核心抽象:Repository 体系
| 接口 | 提供能力 |
|---|---|
CrudRepository<T, ID> | save/findById/findAll/delete/count |
PagingAndSortingRepository | findAll(Pageable)/findAll(Sort) |
JpaRepository | 批量保存、flush、带分页查询 |
Spring Data JPA
JPA(Jakarta Persistence API)是 Java 的 ORM 标准,Spring Data JPA 提供开箱即用的 Repository 实现。实体用注解映射表:
@Entity
@Table(name = "t_user")
public class User {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50)
private String name;
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
}// Repository:接口即实现,方法名自动生成查询
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name); // WHERE name = ?
List<User> findByNameContaining(String keyword); // LIKE %keyword%
Optional<User> findFirstByEmailOrderByCreatedAtDesc(String email);
// @Query 自定义 JPQL/原生 SQL
@Query("SELECT u FROM User u WHERE u.name LIKE %:kw%")
List<User> search(@Param("kw") String kw);
}方法名解析规则
findBy + 属性名 + And/Or/Containing/OrderBy 等关键字自动翻译成查询。复杂查询用 @Query(JPQL 面向实体,SQL 面向表);只返回部分列用 Projection 接口。方法名过长时优先 @Query。
分页与排序
Page<User> page = userRepo.findAll(
PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "createdAt")));
page.getTotalElements(); page.getContent(); // 总条数 / 当前页数据JPA 与 MyBatis 选型
| 维度 | Spring Data JPA | MyBatis(见 MyBatis) |
|---|---|---|
| 开发效率 | 高(接口即 CRUD) | 中(手写 SQL/XML) |
| SQL 控制 | 弱(复杂 SQL 靠 @Query) | 强(完全掌控) |
| 复杂查询/动态 SQL | 一般 | 强(<if>/<foreach>) |
| 学习曲线 | 陡(懒加载/缓存坑多) | 平 |
| 适用 | 标准 CRUD、快速迭代 | 复杂报表、动态 SQL、性能敏感 |
Spring Data Redis
对 Redis 的模板化封装,RedisTemplate 提供类型安全的命令操作,@Cacheable 注解与缓存抽象打通:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory f) {
RedisTemplate<String, Object> t = new RedisTemplate<>();
t.setConnectionFactory(f);
// 序列化:key 用 String,value 用 JSON,避免乱码
t.setKeySerializer(new StringRedisSerializer());
t.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return t;
}
}@Service
public class UserService {
@Autowired private RedisTemplate<String, Object> redis;
public void setCache(String key, Object val) {
redis.opsForValue().set(key, val, 10, TimeUnit.MINUTES); // 带过期
}
public Object getCache(String key) { return redis.opsForValue().get(key); }
// 声明式缓存:方法结果自动进缓存(Redis 为默认 CacheManager)
@Cacheable(cacheNames = "user", key = "#id")
public User findById(Long id) { return userRepo.findById(id).orElse(null); }
}Redis 的完整命令、数据结构与使用场景见 Redis 与 使用场景。
Spring Data MongoDB
对 MongoDB 的 Repository 抽象,实体注解映射文档(Document),API 与 JPA 风格一致:
@Document(collection = "orders")
public class Order {
@Id private String id; // Mongo 用 String 主键(_id)
private String userId;
private BigDecimal amount;
private List<OrderItem> items; // 内嵌文档
}public interface OrderRepository extends MongoRepository<Order, String> {
List<Order> findByUserId(String userId);
}MongoDB 的文档模型、索引与聚合见 MongoDB。
事务与多数据源
@Transactional 统一管理各数据源事务——JPA 天然支持;Mongo 多文档事务(4.0+ 副本集)通过 MongoTransactionManager 接入;Redis 比较特殊,默认不参与声明式事务,需显式开启事务支持后 @Transactional 才映射为 MULTI/EXEC 流水线:
// RedisTemplate 开启事务支持(否则 @Transactional 对 Redis 无效)
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory f) {
RedisTemplate<String, Object> t = new RedisTemplate<>();
t.setConnectionFactory(f);
t.setEnableTransactionSupport(true); // 关键:开启后参与 Spring 事务
// ...序列化配置
}@Transactional
public void transfer(Long from, Long to, BigDecimal amt) {
accountRepo.decreaseBalance(from, amt); // JPA 事务
redis.opsForValue().set("op:" + from, amt); // 同一事务内的 Redis 操作(MULTI/EXEC)
}多数据源事务
@Transactional 只保证单数据源事务;跨库(JPA + Redis 同时写)需分布式事务方案,见 seata 与 分布式事务。同一方法里混用多数据源时,事务只作用于"主事务管理器"绑定的源;Redis 即便开启事务支持,与关系库的回滚也是分离的(Redis 没有回滚机制,MULTI 执行前可丢弃)。
Spring Data 与 SpringFramework 的 IoC/事务、SpringBoot 的自动配置(spring-boot-starter-data-jpa 等)紧密集成,是 Spring 生态数据访问的标准入口。