本文目录导读:

在Java中实现一对多查询(一个用户对应多个订单,一个班级对应多个学生)主要有以下几种方式,我按照从简单到复杂的顺序为你介绍:
SQL层实现(最基础)
表结构设计
-- 用户表
CREATE TABLE user (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 订单表(外键关联用户)
CREATE TABLE order (
id INT PRIMARY KEY,
user_id INT,
order_no VARCHAR(50),
FOREIGN KEY (user_id) REFERENCES user(id)
);
查询方式
两次查询(简单明了)
// 1. 先查询用户 User user = userMapper.getUserById(1); // 2. 再查询该用户的订单 List<Order> orders = orderMapper.getOrdersByUserId(user.getId()); user.setOrders(orders);
一次查询(JOIN + 手动处理)
// SQL: SELECT u.*, o.* FROM user u LEFT JOIN order o ON u.id = o.user_id WHERE u.id = 1
// 结果集需要手动处理重复数据
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
// 手动组装
User user = null;
List<Order> orders = new ArrayList<>();
for (Map<String, Object> row : result) {
if (user == null) {
user = new User();
user.setId((int) row.get("u.id"));
user.setName((String) row.get("u.name"));
}
Order order = new Order();
order.setId((int) row.get("o.id"));
order.setOrderNo((String) row.get("o.order_no"));
orders.add(order);
}
user.setOrders(orders);
ORM框架实现(MyBatis示例)
MyBatis XML配置
<!-- UserMapper.xml -->
<resultMap id="UserOrderMap" type="com.example.User">
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
<!-- 一对多映射 -->
<collection property="orders" ofType="com.example.Order">
<id property="id" column="order_id"/>
<result property="orderNo" column="order_no"/>
</collection>
</resultMap>
<!-- 查询方法 -->
<select id="getUserWithOrders" resultMap="UserOrderMap">
SELECT
u.id as user_id,
u.name as user_name,
o.id as order_id,
o.order_no
FROM user u
LEFT JOIN order o ON u.id = o.user_id
WHERE u.id = #{userId}
</select>
Java实体类
public class User {
private Integer id;
private String name;
private List<Order> orders; // 一对多关系
// getter/setter
}
public class Order {
private Integer id;
private String orderNo;
// getter/setter
}
完整案例:用户-订单查询
数据库层
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
// 方式1:使用MyBatis(推荐)
public User getUserWithOrders(Integer userId) {
// 实际使用MyBatis的Mapper
return userMapper.selectUserWithOrders(userId);
}
// 方式2:JDBC手动实现
public User getUserWithOrdersJdbc(Integer userId) {
String sql = "SELECT u.*, o.* FROM user u " +
"LEFT JOIN `order` o ON u.id = o.user_id " +
"WHERE u.id = ?";
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, userId);
if (rows.isEmpty()) {
return null;
}
User user = new User();
List<Order> orders = new ArrayList<>();
for (Map<String, Object> row : rows) {
// 用户信息(只设置一次)
if (user.getId() == null) {
user.setId((Integer) row.get("id"));
user.setName((String) row.get("name"));
}
// 订单信息
if (row.get("o.id") != null) {
Order order = new Order();
order.setId((Integer) row.get("o.id"));
order.setOrderNo((String) row.get("order_no"));
order.setUserId((Integer) row.get("user_id"));
orders.add(order);
}
}
user.setOrders(orders);
return user;
}
}
Service层
@Service
public class UserService {
@Autowired
private UserDao userDao;
public User getUserInfo(Integer userId) {
User user = userDao.getUserWithOrders(userId);
// 业务逻辑处理
if (user != null && user.getOrders() != null) {
System.out.println("用户 " + user.getName() + " 有 " +
user.getOrders().size() + " 个订单");
}
return user;
}
}
Controller层
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public Result getUser(@PathVariable Integer id) {
User user = userService.getUserInfo(id);
return Result.success(user);
}
}
性能优化建议
延迟加载
<!-- MyBatis延迟加载 -->
<resultMap id="UserOrderMap" type="User">
<collection property="orders"
ofType="Order"
select="com.example.OrderMapper.getOrdersByUserId"
column="id"
fetchType="lazy"> <!-- lazy: 使用时才加载 -->
</collection>
</resultMap>
分批查询(N+1问题优化)
<!-- 使用IN查询减少查询次数 -->
<select id="getUsersWithOrders" resultMap="UserOrderMap">
SELECT u.*, o.*
FROM user u
LEFT JOIN order o ON u.id = o.user_id
WHERE u.id IN
<foreach collection="userIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 两次查询 | 简单易懂,避免笛卡尔积 | 需要多次查询 | 数据量小 |
| JOIN查询 | 一次查询获取全部数据 | 数据量大时效率低 | 数据量适中 |
| MyBatis resultMap | 自动映射,代码简洁 | 配置相对复杂 | 复杂业务场景 |
| 延迟加载 | 按需加载,节省资源 | 可能产生N+1问题 | 关联数据不一定需要 |
推荐方案:对于大多数业务场景,使用MyBatis的resultMap + collection配置,配合延迟加载或分批查询策略,既能保持代码简洁,又能获得较好的性能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播