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

Spring Boot中使用JPA批量插入多行数据遇问题求助

问题解决方案

问题根源

  1. 表单提交时,所有选中的code因同名name="code"被Spring MVC拼接为单个字符串,绑定到单个CourseTwo的code字段,导致所有代码存入同一行。
  2. 尝试的批量代码错误:用单个CourseTwo对象初始化ArrayList,违反集合构造参数要求,触发No primary or single unique constructor found for interface java.util.List异常。

1. 修正表单提交逻辑

移除单个CourseTwo绑定,改为提交选中的CourseOne ID列表:

<form th:action="@{/saveCourseTwo}" method="post">
    <div class="overflow-scroll" style="border: 2px dashed; height:300px; width:800px">
        <div class="table-responsive">
            <table class="table table-sm table-striped table-hover" style="width: 100%">
                <thead class="green white-text">
                    <tr>
                        <th>Select</th>
                        <th>Code</th>
                        <th>Title</th>
                        <th>Units</th>
                    </tr>
                </thead>
                <tbody>
                    <tr th:each="course : ${listCourseOne}">                            
                        <td>
                            <input type="checkbox" class="form-check-input" 
                                   name="selectedCourseIds" th:value="${course.courseOneId}" />
                        </td>
                        <td th:text="${course.code}"></td>
                        <td th:text="${course.title}"></td>
                        <td th:text="${course.units}"></td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
    <button type="submit" class="btn btn-success">Save</button>
</form>
  • 去掉th:object="${courseTwo}",无需绑定单个对象
  • 复选框name设为selectedCourseIds,传递选中的CourseOne ID列表

2. 新增CourseOne仓库(若未存在)

用于查询选中的课程信息:

public interface CourseOneRepository extends CrudRepository<CourseOne, Long> {
}

3. 修改服务层批量保存逻辑

接收ID列表,批量创建CourseTwo实例并保存:

@Service
public class CourseTwoService {

    private final CourseTwoRepository courseTwoRepo;
    private final CourseOneRepository courseOneRepo;

    // 构造注入
    public CourseTwoService(CourseTwoRepository courseTwoRepo, CourseOneRepository courseOneRepo) {
        this.courseTwoRepo = courseTwoRepo;
        this.courseOneRepo = courseOneRepo;
    }

    public List<CourseTwo> saveCourseTwo(List<Long> selectedCourseIds) {
        List<CourseTwo> courseTwoList = new ArrayList<>();
        for (Long courseOneId : selectedCourseIds) {
            // 查询对应CourseOne实例
            CourseOne courseOne = courseOneRepo.findById(courseOneId)
                    .orElseThrow(() -> new IllegalArgumentException("CourseOne not found with id: " + courseOneId));
            // 创建CourseTwo并赋值
            CourseTwo courseTwo = new CourseTwo();
            courseTwo.setCode(courseOne.getCode());
            courseTwo.setCourseOne(courseOne);
            courseTwoList.add(courseTwo);
        }
        // 批量插入
        return (List<CourseTwo>) courseTwoRepo.saveAll(courseTwoList);
    }
}

4. 编写控制器处理请求

接收表单提交的ID列表,调用服务层:

@Controller
public class CourseController {

    private final CourseTwoService courseTwoService;
    private final CourseOneRepository courseOneRepo;

    public CourseController(CourseTwoService courseTwoService, CourseOneRepository courseOneRepo) {
        this.courseTwoService = courseTwoService;
        this.courseOneRepo = courseOneRepo;
    }

    // 显示课程选择表单
    @GetMapping("/selectCourses")
    public String showSelectForm(Model model) {
        model.addAttribute("listCourseOne", courseOneRepo.findAll());
        return "course-select"; // 替换为你的视图名称
    }

    // 处理批量保存请求
    @PostMapping("/saveCourseTwo")
    public String saveCourseTwo(@RequestParam("selectedCourseIds") List<Long> selectedCourseIds) {
        courseTwoService.saveCourseTwo(selectedCourseIds);
        return "redirect:/success"; // 替换为保存成功后的跳转页面
    }
}

5. 实体关系优化(可选)

当前一对一关系限制每个CourseOne只能关联一个CourseTwo,若业务允许重复插入同一课程,需改为一对多:

  • 修改CourseOne:
@OneToMany(mappedBy = "courseOne", cascade = CascadeType.ALL)
private List<CourseTwo> courseTwoList = new ArrayList<>();
  • 修改CourseTwo:
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "course_one_id")
private CourseOne courseOne;

内容的提问来源于stack exchange,提问作者Done-Q

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:25:18