Hibernate 框架超详细说明 1. Hibernate 框架概述 ORM 框架 :对象关系映射(Object-Relational Mapping) JPA 实现 :Java Persistence API 的具体实现 数据库抽象 :屏蔽底层数据库差异 自动 SQL 生成 :减少手动 SQL 编写工作 2. 核心概念 2.1 持久化生命周期 瞬时态(Transient) :未与 Session 关联的对象 持久态(Persistent) :与 Session 关联的对象 脱管态(Detached) :与 Session 断开连接的对象 2.2 Session 机制 Session 接口 :Hibernate 的核心接口 事务管理 :提供 ACID 事务支持 缓存机制 :一级缓存(Session 级别) 3. 项目配置 3.1 Maven 依赖
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
3.2 application.yml 配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/hibernate_demo
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
hbm2ddl.auto: update
4. 实体类定义 4.1 基础实体类
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false, length = 50)
private String username;
@Column(name = "email", unique = true)
private String email;
@Column(name = "created_at")
private LocalDateTime createdAt;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List orders = new ArrayList<>();
// 构造函数
public User() {}
public User(String username, String email) {
this.username = username;
this.email = email;
this.createdAt = LocalDateTime.now();
}
// Getter 和 Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public LocalDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
public List getOrders() { return orders; }
public void setOrders(List orders) { this.orders = orders; }
}
4.2 关联实体类
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "order_number", unique = true)
private String orderNumber;
@Column(name = "total_amount")
private BigDecimal totalAmount;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Column(name = "order_date")
private LocalDateTime orderDate;
// 构造函数
public Order() {}
public Order(String orderNumber, BigDecimal totalAmount, User user) {
this.orderNumber = orderNumber;
this.totalAmount = totalAmount;
this.user = user;
this.orderDate = LocalDateTime.now();
}
// Getter 和 Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getOrderNumber() { return orderNumber; }
public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; }
public BigDecimal getTotalAmount() { return totalAmount; }
public void setTotalAmount(BigDecimal totalAmount) { this.totalAmount = totalAmount; }
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
public LocalDateTime getOrderDate() { return orderDate; }
public void setOrderDate(LocalDateTime orderDate) { this.orderDate = orderDate; }
}
5. Repository 接口 5.1 基础 Repository
@Repository
public interface UserRepository extends JpaRepository {
Optional findByUsername(String username);
List findByEmailContaining(String email);
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id = :id")
Optional findUserWithOrders(@Param("id") Long id);
@Query("SELECT u FROM User u WHERE u.username LIKE %:keyword% OR u.email LIKE %:keyword%")
List searchUsers(@Param("keyword") String keyword);
}
5.2 Order Repository
@Repository
public interface OrderRepository extends JpaRepository {
List findByUser(User user);
List findByUserAndTotalAmountGreaterThan(User user, BigDecimal amount);
@Query("SELECT o FROM Order o WHERE o.orderDate BETWEEN :startDate AND :endDate")
List findOrdersByDateRange(@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate);
}
6. Service 层实现 6.1 UserService
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private OrderRepository orderRepository;
public User createUser(String username, String email) {
User user = new User(username, email);
return userRepository.save(user);
}
public Optional findUserById(Long id) {
return userRepository.findById(id);
}
public User findUserWithOrders(Long id) {
return userRepository.findUserWithOrders(id)
.orElseThrow(() -> new EntityNotFoundException("User not found: " + id));
}
public List findAllUsers() {
return userRepository.findAll();
}
public User updateUser(Long id, String username, String email) {
User user = userRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("User not found: " + id));
user.setUsername(username);
user.setEmail(email);
return userRepository.save(user);
}
public void deleteUser(Long id) {
if (!userRepository.existsById(id)) {
throw new EntityNotFoundException("User not found: " + id);
}
userRepository.deleteById(id);
}
public List searchUsers(String keyword) {
return userRepository.searchUsers(keyword);
}
public Order createOrderForUser(Long userId, String orderNumber, BigDecimal amount) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException("User not found: " + userId));
Order order = new Order(orderNumber, amount, user);
return orderRepository.save(order);
}
}
7. 控制器层 7.1 UserController
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity createUser(@RequestBody CreateUserRequest request) {
User user = userService.createUser(request.getUsername(), request.getEmail());
return ResponseEntity.ok(user);
}
@GetMapping("/{id}")
public ResponseEntity getUser(@PathVariable Long id) {
try {
User user = userService.findUserWithOrders(id);
return ResponseEntity.ok(user);
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
@GetMapping
public ResponseEntity> getAllUsers() {
List users = userService.findAllUsers();
return ResponseEntity.ok(users);
}
@PutMapping("/{id}")
public ResponseEntity updateUser(@PathVariable Long id,
@RequestBody UpdateUserRequest request) {
try {
User updatedUser = userService.updateUser(id, request.getUsername(), request.getEmail());
return ResponseEntity.ok(updatedUser);
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
@DeleteMapping("/{id}")
public ResponseEntity deleteUser(@PathVariable Long id) {
try {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
@GetMapping("/search")
public ResponseEntity> searchUsers(@RequestParam String keyword) {
List users = userService.searchUsers(keyword);
return ResponseEntity.ok(users);
}
@PostMapping("/{userId}/orders")
public ResponseEntity createOrder(@PathVariable Long userId,
@RequestBody CreateOrderRequest request) {
try {
Order order = userService.createOrderForUser(userId,
request.getOrderNumber(),
request.getAmount());
return ResponseEntity.ok(order);
} catch (EntityNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
}
8. 高级特性 8.1 事务管理
@Service
public class TransactionalService {
@Autowired
private UserRepository userRepository;
@Autowired
private OrderRepository orderRepository;
@Transactional
public void performComplexOperation(Long userId) {
// 在同一个事务中执行多个操作
User user = userRepository.findById(userId).orElse(null);
// 创建订单
Order order = new Order("ORD-001", new BigDecimal("100.00"), user);
orderRepository.save(order);
// 更新用户信息
user.setUsername("updated_username");
userRepository.save(user);
// 如果发生异常,整个事务回滚
}
@Transactional(rollbackFor = Exception.class)
public void customRollback() throws Exception {
// 自定义回滚条件
}
}
8.2 缓存配置
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "users")
public class User {
// 实体定义
}
8.3 分页和排序
@Service
public class UserService {
public Page getUsersWithPagination(int page, int size, String sortBy, String direction) {
Sort sort = direction.equalsIgnoreCase("desc") ?
Sort.by(sortBy).descending() :
Sort.by(sortBy).ascending();
Pageable pageable = PageRequest.of(page, size, sort);
return userRepository.findAll(pageable);
}
}
9. 查询优化 9.1 Fetch Join 优化
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id = :id")
Optional findUserWithOrders(@Param("id") Long id);
9.2 批量处理
@Service
public class BatchService {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void batchInsertUsers(List users) {
for (int i = 0; i < users.size(); i++) {
entityManager.persist(users.get(i));
if (i % 20 == 0) { // 每20个对象刷新一次
entityManager.flush();
entityManager.clear();
}
}
}
}
10. 异常处理 10.1 自定义异常
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(String message) {
super(message);
}
}
public class DataIntegrityException extends RuntimeException {
public DataIntegrityException(String message) {
super(message);
}
}
10.2 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity handleEntityNotFound(EntityNotFoundException e) {
ErrorResponse error = new ErrorResponse("ENTITY_NOT_FOUND", e.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(DataIntegrityException.class)
public ResponseEntity handleDataIntegrity(DataIntegrityException e) {
ErrorResponse error = new ErrorResponse("DATA_INTEGRITY_ERROR", e.getMessage());
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
}
}
11. 性能优化要点 合理使用懒加载和急加载 避免 N+1 查询问题 使用批量操作 合理配置缓存 使用索引优化查询 及时关闭 Session 和连接 12. 常见问题 LazyInitializationException :在事务外访问懒加载属性 事务边界问题 :确保在事务范围内进行数据库操作 缓存一致性 :在集群环境中注意缓存同步 并发控制 :使用乐观锁或悲观锁处理并发访问 Hibernate 懒加载机制详解 懒加载的工作原理 1. 代理对象机制 当使用
FetchType.LAZY
时,Hibernate 会创建一个 代理对象
user.getOrders()
返回的是 Hibernate 的 集合代理 代理对象继承自
PersistentBag
、
PersistentList
等 2. SQL 执行时机
User user = userRepository.findById(1L).get(); // 执行: SELECT * FROM users WHERE id = 1
// 此时 orders 集合为空的代理对象,未执行查询
List orders = user.getOrders(); // 此时才执行: SELECT * FROM orders WHERE user_id = ?
// 仅当真正访问 orders 时才触发 SQL 查询
3. 持久层调用方式 初始化时
userRepository.findById(1L).get()
→ 调用
JpaRepository
的方法 执行对
users
表的查询 访问懒加载属性时
user.getOrders()
→ 代理对象拦截调用 Hibernate 内部触发 额外的 SQL 查询 通过
Session
或
EntityManager
执行查询 4. 实际执行流程
1. userRepository.findById(1L).get()
→ Spring Data JPA → Hibernate → SQL: SELECT * FROM users WHERE id = 1
2. user.getOrders()
→ Hibernate 代理拦截器 → 触发懒加载
→ 生成 SQL: SELECT * FROM orders WHERE user_id = 1
→ 执行查询并填充集合
5. 关键点 懒加载是在 访问属性时 触发,而非 方法调用时 需要在 事务范围内 访问,否则抛出
LazyInitializationException
Hibernate 通过 字节码增强 实现透明的懒加载机制 Hibernate 事务开启方式详解 1. @Transactional 注解方式 主要开启方式 使用
@Transactional
注解是 Spring 中开启事务的主要方式 可以在 方法级别 或 类级别 使用 Spring 会自动管理事务的开启、提交和回滚 代码示例
@Service
public class TransactionalService {
@Transactional // 开启事务
public void performComplexOperation(Long userId) {
// 事务范围内的操作
}
}
2. 事务开启的其他方式 编程式事务管理
@Service
public class ProgrammaticTransactionService {
@Autowired
private PlatformTransactionManager transactionManager;
public void performWithProgrammaticTransaction() {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 业务逻辑
// ...
transactionManager.commit(status); // 提交事务
} catch (Exception e) {
transactionManager.rollback(status); // 回滚事务
}
}
}
3. @Transactional 工作机制 Spring AOP 代理 Spring 通过 AOP 代理 实现事务管理 在方法执行前开启事务 方法执行成功后提交事务 发生异常时回滚事务 事务传播行为
@Transactional(propagation = Propagation.REQUIRED) // 默认传播行为
public void methodA() {
methodB(); // 如果存在事务则加入,否则新建
}
@Transactional(propagation = Propagation.REQUIRES_NEW) // 新建事务
public void methodB() {
// 独立的事务
}
4. 事务配置参数 常用配置
rollbackFor
: 指定哪些异常触发回滚
noRollbackFor
: 指定哪些异常不触发回滚
isolation
: 事务隔离级别
propagation
: 事务传播行为
timeout
: 事务超时时间 示例配置
@Transactional(
rollbackFor = Exception.class, // 所有异常都回滚
timeout = 30, // 30秒超时
isolation = Isolation.READ_COMMITTED // 隔离级别
)
public void customTransaction() {
// 自定义事务配置
}
