@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 的集合代理
代理对象继承自 PersistentBag、PersistentList 等
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 查询