在使用JPA(Java Persistence API)时,虽然它主要通过对象而不是SQL语句来操作数据库,但在处理复杂查询时,我们有时仍需要直接使用SQL。这可以通过 @Query 注解在 Repository 接口中实现。以下是一个使用Spring Data JPA和原生SQL来处理复杂数据库查询的实例。
遇见即是缘分,关注🌟、点赞👍、收藏📚,让这份美好延续下去!
🌟 获取技术转管理相关的知识 请搜索关注 【技术管理修行】 号
一、查询用户及其订单信息
假设我们有两个表:users 和 orders,其中 orders 表通过 user_id 字段与 users 表关联。
二、数据库表结构
- users
- id INT
- name VARCHAR
- email VARCHAR
- orders
- id INT
- user_id INT
- order_date DATE
- amount DECIMAL
三、创建JPA实体
1. User 实体类
package com.jsglxx.demo.entity;import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;@Entity
public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; public User() {super();}// getters and setters public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public User(Long id, String name, String email) {super();this.id = id;this.name = name;this.email = email;}}
2. Orders 实体类
注意:order 是 Mysql 排序的保留关键字,不能使用。
package com.jsglxx.demo.entity;import java.math.BigDecimal;
import java.util.Date;import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;@Entity
public class Orders { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Long userId; private Date orderDate; private BigDecimal amount; public Orders() {super();}// getters and setters public Long getId() {return id;}public void setId(Long id) {this.id = id;}public Long getUserId() {return userId;}public void setUserId(Long userId) {this.userId = userId;}public Date getOrderDate() {return orderDate;}public void setOrderDate(Date orderDate) {this.orderDate = orderDate;}public BigDecimal getAmount() {return amount;}public void setAmount(BigDecimal amount) {this.amount = amount;}public Orders(Long id, Long userId, Date orderDate, BigDecimal amount) {super();this.id = id;this.userId = userId;this.orderDate = orderDate;this.amount = amount;}}
四、 创建 Repository 接口
package com.jsglxx.demo.repository;import java.util.List;import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;import com.jsglxx.demo.entity.User;public interface UserRepository extends JpaRepository<User, Long> { @Query(value = "SELECT u.*, o.* FROM user u INNER JOIN orders o ON u.id = o.user_id WHERE u.name = ?1", nativeQuery = true) List<Object[]> findUserWithOrdersByName(String name); }
- 返回类型 List<Object[]> 中的 Object[] 表示每行结果是一个对象数组,其中包含了 users 和 orders 表中对应列的值。
- 对于更复杂的查询,考虑使用 DTO(Data Transfer Object) 来映射查询结果,使代码更加清晰。
五、 Service 调用
package com.jsglxx.demo.service;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.jsglxx.demo.repository.UserRepository;@Service
public class UserService { @Autowired private UserRepository userRepository; public List<Object[]> getUserWithOrdersByName(String name) { return userRepository.findUserWithOrdersByName(name); }
}
六、 Controller 调用
@RestController
@RequestMapping("/users")
public class UserController { @Autowiredprivate UserService userService;//根据用户姓名查询订单信息@GetMapping("/{name}")public List<Object[]> getUserWithOrdersByName(@PathVariable String name){return this.userService.getUserWithOrdersByName(name);}
}
七、测试
1、插入模拟数据
2、使用 postman 测试
八、总结
通过上述示例,可以掌握如何在Spring Data JPA中使用原生SQL来处理复杂的数据库查询。