【问题标题】:How to accept input for a list of objects using checkboxes in a form如何使用表单中的复选框接受对象列表的输入
【发布时间】:2021-09-05 00:02:46
【问题描述】:

我有一个包含 2 个实体的场景:

1)学生:

@Entity
@Table(name = "student_registration")
public class Student
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Column
    private String firstName;
    @Column
    private String lastName;
    @OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
    private List<Hobby> hobbies;

//constructors (default, all params), getters and setters
}

2)爱好:

@Entity
@Table(name = "hobby")
public class Hobby
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "hobby_id")
    private Student student;
    @Column
    private String name;

//contructors (default, Hobby(name, student), getters and setters)
}

我想从一组复选框中输入每个复选框选项作为一种爱好,其名称等于复选框的值

这是我上面的 JSP 部分:

<div class="form">
    <form:form action="success" modelAttribute="student" onsubmit="return validate()">
        <div class="row">
            <div class="label">First Name</div>
            <div class="field">
                <form:input path="firstName" />
            </div>
        </div>

        <div class="row">
            <div class="label">Last Name</div>
            <div class="field">
                <form:input path="lastName" />
            </div>
        </div>
        <div class="row">
            <div class="label">Hobbies</div>
            <div class="field">
                <form:checkbox path="hobbies" id="hobby1Checkbox" value="Hobby 1" />
                <label class="sublabel" for="hobby1Checkbox">Hobby 1</label>
                <form:checkbox path="hobbies" id="hobby2Checkbox" value="Hobby 2" />
                <label class="sublabel" for="hobby2Checkbox">Hobby 2</label>
                <form:checkbox path="hobbies" id="hobby3Checkbox" value="Hobby 3" />
                <label class="sublabel" for="hobby3Checkbox">Hobby 3</label>
            </div>
        </div>
</form:form>
</div>

这是我的控制器:

@Controller
public class StudentController {

@Autowired
StudentService stuServ;
@RequestMapping("/")
public String index() {
  return "index";
}

@GetMapping("/registration")
public String registrationRedirect(ModelMap studentModel)
{
   studentModel.addAttribute("student", new Student());   
   studentModel.addAttribute("hobby", new Hobby());
   return "registration";
}
@PostMapping("/success")
public String sayHello(@ModelAttribute("registeredStudent") Student student) {
   
   stuServ.addStudent(student);
  return "success";
}
}

我知道我所做的不正确,因为我无法将复选框中的字符串值映射到对象列表 (List) 但是我无法找到实现相同目标的方法。我正在寻找使用 Converter 或 PropertyEditor 的可能解决方案,但我是 Spring MVC 的新手,我很困惑。

*更新:

我观察到,在仅将名称作为参数的 Hobby 类中添加参数化构造函数后,我可以使用复选框直接将值传递给 Hobby 对象,因为复选框的 String 值已初始化为通过上述构造函数的爱好名称。

如果我只是将爱好名称用于注册成功视图,则此方法有效,但是另一个明显的问题是爱好类的学生字段永远不会被初始化,因为只有构造函数 爱好(名称) 被调用,因此关系不是双向的。在 Hobby 类中,学生字段保持为空。

请以适当的方式处理这种情况。我想不出可以让 Spring 知道我将复选框选择的爱好分配给哪个学生的方法。

根据我之前提供的答案进行编辑:

如果我为 Hobby 实体创建存储库,则会出现另一个问题:

public interface HobbyRepository extends JpaRepository<Hobby, Integer>
{
    boolean findByName(String hobby);
}

爱好的复选框字符串值初始化不再起作用。早些时候,带有名称参数的 Hobby 实体的构造函数完成了这项工作,但是在添加 Hobby 存储库时,我收到了以下预期错误:

出现意外错误(类型=错误请求,状态=400)。 object='registeredStudent' 的验证失败。错误计数:1 org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 个错误 字段 'hobbies' 上的对象 'registeredStudent' 中的字段错误:拒绝值 [唱歌、素描、游泳];代码 [typeMismatch.registeredStudent.hobbies,typeMismatch.hobbies,typeMismatch.java.util.List,typeMismatch];参数 [org.springframework.context.support.DefaultMessageSourceResolvable:代码 [re​​gisteredStudent.hobbies,hobbies];论据 [];默认消息[爱好]];默认消息[无法将类型“java.lang.String[]”的属性值转换为属性“爱好”所需的类型“java.util.List”;嵌套异常是 org.springframework.core.convert.ConversionFailedException:无法从类型 [java.lang.String] 转换为类型 [java.lang.Integer] 以获取值“Singing”;嵌套异常是 java.lang.NumberFormatException: For input string: "Singing"]

差不多,名称 = 复选框的字符串值的爱好不再能够初始化。我已经尝试删除 Hobby 存储库,它运行良好。 任何进一步的见解将不胜感激,因为目前唯一可能的解决方案似乎是在我的 Student POJO 类中添加一个额外的 List 字段并使用字段中传递的复选框的值来初始化 Student.hobbies

中包含的爱好对象

【问题讨论】:

    标签: forms spring-boot spring-mvc jsp spring-data-jpa


    【解决方案1】:

    在我的控制器中,可以将当前学生对象作为ModelAttribute传递给属于当前学生对象的各个爱好,从而完成双向关系,如下:

       @PostMapping("/success")
       public String sayHello(@ModelAttribute("registeredStudent") Student student) {
           for(Hobby h : student.getHobbies())
           {
               h.setStudent(student);
           }
           stuServ.addStudent(student);
          return "success";
       }
    

    为了防止StackOverFlow 错误由于实体的无限嵌套

    这是一种解决方案,但可能有更好的方法来解决这个问题。

    编辑:

    如果我为 Hobby 实体创建存储库,则会出现另一个问题:

    public interface HobbyRepository extends JpaRepository<Hobby, Integer>
    {
        boolean findByName(String hobby);
    }
    

    爱好的复选框字符串值初始化不再起作用。早些时候,带有名称参数的 Hobby 实体的构造函数完成了这项工作,但是在添加 Hobby 存储库时,我收到了以下预期错误:

    出现意外错误(类型=错误请求,状态=400)。 object='registeredStudent' 的验证失败。错误计数:1 org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 个错误 字段 'hobbies' 上的对象 'registeredStudent' 中的字段错误:拒绝值 [唱歌、素描、游泳];代码 [typeMismatch.registeredStudent.hobbies,typeMismatch.hobbies,typeMismatch.java.util.List,typeMismatch];参数 [org.springframework.context.support.DefaultMessageSourceResolvable:代码 [re​​gisteredStudent.hobbies,hobbies];论据 [];默认消息[爱好]];默认消息[无法将类型“java.lang.String[]”的属性值转换为属性“爱好”所需的类型“java.util.List”;嵌套异常是 org.springframework.core.convert.ConversionFailedException:无法从类型 [java.lang.String] 转换为类型 [java.lang.Integer] 以获取值“Singing”;嵌套异常是 java.lang.NumberFormatException: For input string: "Singing"]

    差不多,名称 = 复选框的字符串值的爱好不再能够初始化。我已经尝试删除 Hobby 存储库,它运行良好。 任何进一步的见解将不胜感激,因为目前唯一可能的解决方案似乎是在我的 Student POJO 类中添加一个额外的 List 字段并使用字段中传递的复选框的值来初始化 Student.hobbies

    中包含的爱好对象

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 2014-03-15
      • 1970-01-01
      • 2019-07-13
      相关资源
      最近更新 更多