You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot单向一对多关联:Rest接口同时保存用户与借阅书籍

Spring Boot 单向一对多关联的Rest接口数据保存实现

1. 确认实体类关联配置

确保你的User和BorrowedBooks实体类的单向一对多关联配置正确,核心是通过级联操作实现用户与书籍数据的同步保存:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // 单向一对多关联,级联所有操作,orphanRemoval确保删除用户时自动清理关联书籍
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "user_id") // 指定BorrowedBooks表中的外键字段
    private List<BorrowedBooks> borrowedBooks = new ArrayList<>();

    // 省略getter、setter、构造方法
}

@Entity
public class BorrowedBooks {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String bookName;
    private String genre;

    // 单向关联无需添加User字段
    // 省略getter、setter、构造方法
}

2. 创建请求DTO

定义DTO接收Postman传递的组合参数,避免直接暴露实体类结构:

// 接收用户+借阅书籍的请求DTO
public class UserBorrowRequest {
    private Long userId; // 可选:存在则更新用户,不存在则创建新用户
    private String userName;
    private List<BorrowedBookDTO> borrowedBooks;

    // 省略getter、setter
}

// 书籍信息DTO
public class BorrowedBookDTO {
    private String bookName;
    private String genre;

    // 省略getter、setter
}

3. 编写业务逻辑(Service层)

复刻Hibernate的对象创建逻辑,处理用户的创建/更新,以及书籍实体的转换与关联:

@Service
public class UserService {
    private final UserRepository userRepository;

    // 构造注入替代@Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User saveUserWithBorrows(UserBorrowRequest request) {
        User user;
        // 处理用户逻辑:存在则查询并更新,不存在则创建新用户
        if (request.getUserId() != null) {
            user = userRepository.findById(request.getUserId())
                    .orElseThrow(() -> new IllegalArgumentException("指定用户不存在"));
            user.setName(request.getUserName());
        } else {
            user = new User();
            user.setName(request.getUserName());
        }

        // 将DTO转换为BorrowedBooks实体
        List<BorrowedBooks> bookEntities = request.getBorrowedBooks().stream()
                .map(dto -> {
                    BorrowedBooks book = new BorrowedBooks();
                    book.setBookName(dto.getBookName());
                    book.setGenre(dto.getGenre());
                    return book;
                })
                .collect(Collectors.toList());

        // 若需替换用户现有借阅记录,先清空集合再添加;若需追加则直接调用addAll
        user.getBorrowedBooks().clear();
        user.getBorrowedBooks().addAll(bookEntities);

        // 保存用户,通过级联操作自动保存关联书籍
        return userRepository.save(user);
    }
}

4. 编写Rest Controller

提供接口接收Postman的请求:

@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping("/borrow")
    public ResponseEntity<User> handleUserBorrow(@RequestBody UserBorrowRequest request) {
        User savedUser = userService.saveUserWithBorrows(request);
        return ResponseEntity.ok(savedUser);
    }
}

5. Postman请求示例

发送POST请求到http://localhost:8080/api/users/borrow,请求体为JSON格式:

{
    "userId": 1, // 可选,不传则创建新用户
    "userName": "张三",
    "borrowedBooks": [
        {
            "bookName": "Spring Boot实战",
            "genre": "计算机技术"
        },
        {
            "bookName": "百年孤独",
            "genre": "文学"
        }
    ]
}

关键注意事项

  • 必须确保User类的@OneToMany注解设置了cascade = CascadeType.ALL,否则保存用户时不会自动同步书籍数据
  • 若需要更新用户的借阅记录,记得先清空现有集合再添加新数据,避免重复追加
  • 异常处理可根据业务需求扩展,比如通过全局异常处理器返回统一格式的错误响应

内容的提问来源于stack exchange,提问作者Mathew Pius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:50:44