Hibernate 框架超详细说明

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 依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

3.2 application.yml 配置

yaml 复制代码
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 基础实体类

java 复制代码
@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<Order> 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<Order> getOrders() { return orders; }
    public void setOrders(List<Order> orders) { this.orders = orders; }
}

4.2 关联实体类

java 复制代码
@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

java 复制代码
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
    List<User> findByEmailContaining(String email);
    
    @Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id = :id")
    Optional<User> findUserWithOrders(@Param("id") Long id);
    
    @Query("SELECT u FROM User u WHERE u.username LIKE %:keyword% OR u.email LIKE %:keyword%")
    List<User> searchUsers(@Param("keyword") String keyword);
}

5.2 Order Repository

java 复制代码
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByUser(User user);
    List<Order> findByUserAndTotalAmountGreaterThan(User user, BigDecimal amount);
    
    @Query("SELECT o FROM Order o WHERE o.orderDate BETWEEN :startDate AND :endDate")
    List<Order> findOrdersByDateRange(@Param("startDate") LocalDateTime startDate, 
                                     @Param("endDate") LocalDateTime endDate);
}

6. Service 层实现

6.1 UserService

java 复制代码
@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<User> 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<User> 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<User> 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

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {
        User user = userService.createUser(request.getUsername(), request.getEmail());
        return ResponseEntity.ok(user);
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        try {
            User user = userService.findUserWithOrders(id);
            return ResponseEntity.ok(user);
        } catch (EntityNotFoundException e) {
            return ResponseEntity.notFound().build();
        }
    }
    
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        List<User> users = userService.findAllUsers();
        return ResponseEntity.ok(users);
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<User> 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<Void> deleteUser(@PathVariable Long id) {
        try {
            userService.deleteUser(id);
            return ResponseEntity.noContent().build();
        } catch (EntityNotFoundException e) {
            return ResponseEntity.notFound().build();
        }
    }
    
    @GetMapping("/search")
    public ResponseEntity<List<User>> searchUsers(@RequestParam String keyword) {
        List<User> users = userService.searchUsers(keyword);
        return ResponseEntity.ok(users);
    }
    
    @PostMapping("/{userId}/orders")
    public ResponseEntity<Order> 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 事务管理

java 复制代码
@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 缓存配置

java 复制代码
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "users")
public class User {
    // 实体定义
}

8.3 分页和排序

java 复制代码
@Service
public class UserService {
    
    public Page<User> 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 优化

java 复制代码
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id = :id")
Optional<User> findUserWithOrders(@Param("id") Long id);

9.2 批量处理

java 复制代码
@Service
public class BatchService {
    
    @PersistenceContext
    private EntityManager entityManager;
    
    @Transactional
    public void batchInsertUsers(List<User> 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 自定义异常

java 复制代码
public class EntityNotFoundException extends RuntimeException {
    public EntityNotFoundException(String message) {
        super(message);
    }
}

public class DataIntegrityException extends RuntimeException {
    public DataIntegrityException(String message) {
        super(message);
    }
}

10.2 全局异常处理

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ErrorResponse> 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<ErrorResponse> 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 的集合代理
  • 代理对象继承自 PersistentBagPersistentList

2. SQL 执行时机

java 复制代码
User user = userRepository.findById(1L).get();  // 执行: SELECT * FROM users WHERE id = 1
// 此时 orders 集合为空的代理对象,未执行查询

List<Order> orders = user.getOrders();  // 此时才执行: SELECT * FROM orders WHERE user_id = ?
// 仅当真正访问 orders 时才触发 SQL 查询

3. 持久层调用方式

初始化时
  • userRepository.findById(1L).get() → 调用 JpaRepository 的方法
  • 执行对 users 表的查询
访问懒加载属性时
  • user.getOrders() → 代理对象拦截调用
  • Hibernate 内部触发额外的 SQL 查询
  • 通过 SessionEntityManager 执行查询

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 会自动管理事务的开启、提交和回滚

代码示例

java 复制代码
@Service
public class TransactionalService {
    
    @Transactional  // 开启事务
    public void performComplexOperation(Long userId) {
        // 事务范围内的操作
    }
}

2. 事务开启的其他方式

编程式事务管理

java 复制代码
@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 代理实现事务管理
  • 在方法执行前开启事务
  • 方法执行成功后提交事务
  • 发生异常时回滚事务

事务传播行为

java 复制代码
@Transactional(propagation = Propagation.REQUIRED)  // 默认传播行为
public void methodA() {
    methodB();  // 如果存在事务则加入,否则新建
}

@Transactional(propagation = Propagation.REQUIRES_NEW)  // 新建事务
public void methodB() {
    // 独立的事务
}

4. 事务配置参数

常用配置

  • rollbackFor: 指定哪些异常触发回滚
  • noRollbackFor: 指定哪些异常不触发回滚
  • isolation: 事务隔离级别
  • propagation: 事务传播行为
  • timeout: 事务超时时间

示例配置

java 复制代码
@Transactional(
    rollbackFor = Exception.class,     // 所有异常都回滚
    timeout = 30,                      // 30秒超时
    isolation = Isolation.READ_COMMITTED  // 隔离级别
)
public void customTransaction() {
    // 自定义事务配置
}
相关推荐
wuk9982 小时前
基于MATLAB/Simulink实现交流异步电动机矢量控制的仿真
开发语言·matlab
零度@2 小时前
30条Java性能优化清单
java·开发语言
期待のcode2 小时前
Java的包装类
java·开发语言
aloha_7892 小时前
python基础面经八股
开发语言·python
李少兄2 小时前
从一篇IDEA笔记开始,我走出了自己的技术创作路
java·笔记·intellij-idea
鹿角片ljp2 小时前
力扣26.有序数组去重:HashSet vs 双指针法
java·算法
雾岛听蓝2 小时前
C++:模拟实现string类
开发语言·c++
SweetCode2 小时前
汉诺塔问题
android·java·数据库
superman超哥2 小时前
Rust Cargo Run 与 Cargo Test 命令:开发工作流的双引擎
开发语言·后端·rust·cargo run·cargo test·开发工作流·双引擎