文章目录概述一、 核心特性对比表二、MyBatis 详解1. 设计理念与核心优势2. 基础配置3. 基本 CRUD 与映射(1)注解方式(适合简单 SQL)(2)XML 方式(推荐用于复杂逻辑)4. 动态 SQL:MyBatis 的杀手锏(1)XML 中的动态查询(2)注解中使用 `"
})
List
注意:注解中动态 SQL 可读性差,建议仅用于简单条件。
二、Spring Data JPA 详解:面向对象的持久化1. 核心理念与优势Spring Data JPA 是 JPA(Java Persistence API)规范的增强实现,底层通常使用 Hibernate。它通过接口方法名或 @Query 自动生成 SQL,极大提升了开发效率。
核心优势:
零实现接口,save()、findById() 等方法自动生成派生查询:方法名即 DSL,如 findByUsernameContainingAndAgeGreaterThan与 Spring 生态无缝集成(事务、AOP、Security)支持分页、排序、Specification 动态查询2. 基础配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update # 开发环境可用,生产慎用
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
3. 基本使用(1)实体类定义
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "age")
private Integer age;
// 构造函数、getter、setter
}
(2)Repository 接口
public interface UserRepository extends JpaRepository
// 派生查询
List
List
List
// 排序
List
// 分页
Page
}
(3)自定义查询(JPQL / Native SQL)
@Query("SELECT u FROM User u WHERE u.name LIKE %:name% AND u.age > :age")
List
@Query(value = "SELECT * FROM user u WHERE u.name LIKE CONCAT('%', :name, '%')", nativeQuery = true)
List
4. 复杂动态查询:Specification当查询条件复杂时,可使用 JpaSpecificationExecutor。
public interface UserRepository extends JpaRepository
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List
Specification
List
if (name != null && !name.trim().isEmpty()) {
predicates.add(cb.like(root.get("name"), "%" + name + "%"));
}
if (minAge != null) {
predicates.add(cb.greaterThanOrEqualTo(root.get("age"), minAge));
}
if (maxAge != null) {
predicates.add(cb.lessThanOrEqualTo(root.get("age"), maxAge));
}
return cb.and(predicates.toArray(new Predicate[0]));
};
return userRepository.findAll(spec);
}
}
5. 分页与排序
// 分页
Pageable pageable = PageRequest.of(0, 10);
Page
// 排序
Sort sort = Sort.by(Sort.Direction.DESC, "id");
List
// 分页 + 排序
PageRequest pageRequest = PageRequest.of(0, 10, Sort.by("id").descending());
三、性能对比1. 核心性能差异概览对比维度MyBatisSpring Data JPA(Hibernate)SQL 生成方式手动编写 SQL,可控性强自动生成 SQL,复杂场景可能不优化批量操作性能高,可支持真正的批量 SQL默认 saveAll 逐条插入,性能较差缓存机制一级/二级缓存,需手动配置一级缓存默认开启,二级缓存需配置复杂查询性能高,可针对具体业务优化 SQL较低,复杂 JPQL 或 Criteria SQL 生成可能低效大数据量性能优,支持流式、分页、批处理较差,批量插入/更新需优化或重写N+1 查询问题无,SQL 自由控制可能出现懒加载导致 N+1 问题开发效率中低,需手写 SQL高,CRUD 方法自动生成2. 详细性能对比分析2.1. 批量插入性能MyBatis:支持真正的批量 SQL(如 INSERT INTO ... VALUES (...),(...),...),插入 1K/1W/10W 条数据时,性能可达 JPA 的 10 倍 左右。Spring Data JPA:默认 saveAll 方法实际为循环单条插入,效率极低。批量插入 1W 条数据可能耗时数分钟,且会先查询再插入/更新,导致额外性能开销。实测案例:插入 10 万条数据,MyBatis 真批量仅需 640ms,而 JPA 默认方式可能超过 1 分钟。
2.2. 查询性能MyBatis:SQL 手动控制,可针对索引、JOIN、复杂条件优化,性能更优。Spring Data JPA:自动生成 SQL,复杂查询可能生成冗余语句,性能较差。如分页查询时,会先执行 count 查询,再执行 limit,可能拖慢性能。2.3. 缓存机制MyBatis:一级缓存(Session 级别)默认开启,二级缓存需手动配置,适合分布式环境。Spring Data JPA:一级缓存默认开启,二级缓存需额外配置(如 Ehcache),配置复杂且容易出错。2.4. 大数据量处理MyBatis:支持流式查询、分页插件、批处理,适合大数据量场景。Spring Data JPA:大数据量操作需额外优化,如重写 saveAll、使用原生 SQL,否则性能较差。2.5. N+1 查询问题MyBatis:无此问题,SQL 自由控制。Spring Data JPA:懒加载可能导致 N+1 查询,需手动配置 JOIN FETCH 或 EntityGraph 优化。3. 性能优化建议3.1. MyBatis 优化优化点建议N+1 查询使用 JOIN 一次性查出关联数据,避免循环查库延迟加载配置 fetchType="lazy",按需加载关联对象二级缓存在 mapper.xml 中启用
Spring Data JPA:负责核心领域模型的 CRUD,如用户、订单、商品。MyBatis:负责复杂报表、统计分析、批量操作、高并发查询。配置建议:
使用不同的 @MapperScan 和 @EnableJpaRepositories 指定包路径。统一事务管理(@Transactional),确保跨数据源一致性。五、总结无论选择哪一个,关键是理解其设计哲学,合理使用其优势,规避其短板。技术选型没有绝对的对错,只有是否适合当前团队与业务场景。
框架适合谁不适合谁MyBatisSQL 工程师、复杂系统、高性能场景追求快速开发、不熟悉 SQL 的团队Spring Data JPADDD 实践者、快速开发、标准业务系统需要复杂 SQL 优化、遗留数据库对接最终建议:
新项目、标准业务系统 → 优先考虑 Spring Data JPA,提升开发效率。复杂查询、高并发、报表系统 → 选择 MyBatis,掌握 SQL 主动权。大型项目 → 可混合使用,JPA 处理常规 CRUD,MyBatis 处理复杂逻辑。