Как принять ввод для списка объектов с помощью флажков в форме

#forms #spring-boot #spring-mvc #jsp #spring-data-jpa

Вопрос:

У меня есть сценарий с 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>
 

Here is my controller:

 @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";
}
}
 

I understand that what I have done is incorrect, since I cannot map a String value from a checkbox to a list of objects (List)
However I am unable to find a way to achieve the same. I was looking into possible solutions using a Converter or a PropertyEditor but I am new to Spring MVC and I’m confused.

*Update:

I have observed that upon adding a parameterized constructor within the Hobby class with only the name as the argument, I am able to directly pass the value to the Hobby object using the checkboxes, since the String value of the checkboxes is initialized to the Hobby name via the aforementioned contructor.

Это работает, если я должен использовать имя хобби только для представления успеха регистрации, однако другая очевидная проблема заключается в том, что поле учащегося класса хобби никогда не инициализируется, поскольку вызывается только хобби(имя) конструктора, следовательно, связь не является двунаправленной. Поле Студент остается пустым в классе хобби.

Пожалуйста, помогите найти подходящие способы справиться с ситуацией. Я не могу придумать способы, с помощью которых я мог бы сообщить Весне, какому ученику я назначаю хобби, выбранное флажком.

Отредактируйте в отношении моего ранее предоставленного ответа:

Другая проблема возникает, если я создаю репозиторий для объекта Хобби:

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

Инициализация строкового значения флажка для хобби больше не работает. Ранее конструктор с параметром name для объекта Хобби выполнял эту работу, но при добавлении репозитория хобби я получаю следующую ожидаемую ошибку:

Произошла неожиданная ошибка (тип=Неверный запрос, статус=400). Не удалось выполнить проверку для объекта=’registeredStudent’. Количество ошибок: 1 организация.springframework.проверка.Исключение BindException: org.springframework.проверка.Beanpropertybindingрезультат: 1 Ошибка в поле ошибка в объекте «Зарегистрированный студент» в поле «хобби»: отклонено значение [Пение,Рисование,Плавание]; коды [Несоответствие типов.Зарегистрирован студент.хобби,совпадение типов.хобби,совпадение типов.java.util.Список,сопоставление типов]; аргументы [org.springframework.контекст.поддержка.Defaultmessagesourcerразрешимые: коды [зарегистрированныйстудент.хобби,хобби]; аргументы []; сообщение по умолчанию [хобби]]; сообщение по умолчанию [Не удалось преобразовать значение свойства типа ‘java.lang.Строка[]» для требуемого типа «java.util.List» для свойства «хобби»; вложенное исключение-org.каркасная работа.ядро.преобразование.Исключение ConversionFailedException: Не удалось преобразовать из типа [java.lang.Строка] для ввода [java.lang.Целое число] для значения «Пение»; вложенным исключением является исключение java.lang.NumberFormatException: Для входной строки: «Пение»]

В значительной степени Хобби с именем = строковое значение флажков больше не может быть инициализировано. Я попытался удалить хранилище хобби, и оно отлично работает. Любое дальнейшее понимание было бы оценено, поскольку единственным возможным решением на данный момент, по-видимому, является добавление дополнительного поля<Строка> списка<Строка> в моем классе POJO для студентов и использование значений из флажков, переданных в поле, для инициализации объектов хобби, содержащихся в Student.хобби.

Ответ №1:

В моем контроллере текущий объект учащегося, переданный как атрибут ModelAttribute, может быть назначен каждому из увлечений, принадлежащих текущему объекту учащегося, тем самым завершая двунаправленную связь следующим образом:

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

Мне пришлось исключить сопоставленные поля, т. Е. хобби в сущности студента и студент в сущности хобби из хэш-кода и методов equals в соответствующих сущностях, чтобы предотвратить ошибку стекового потока из-за бесконечной вложенности сущностей

Это работает как решение, однако могут быть лучшие способы решения этой проблемы.

Редактировать:

Другая проблема возникает, если я создаю репозиторий для объекта Хобби:

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

Инициализация строкового значения флажка для хобби больше не работает. Ранее конструктор с параметром name для объекта Хобби выполнял эту работу, но при добавлении репозитория хобби я получаю следующую ожидаемую ошибку:

Произошла неожиданная ошибка (тип=Неверный запрос, статус=400). Не удалось выполнить проверку для объекта=’registeredStudent’. Количество ошибок: 1 организация.springframework.проверка.Исключение BindException: org.springframework.проверка.Beanpropertybindingрезультат: 1 Ошибка в поле ошибка в объекте «Зарегистрированный студент» в поле «хобби»: отклонено значение [Пение,Рисование,Плавание]; коды [Несоответствие типов.Зарегистрирован студент.хобби,совпадение типов.хобби,совпадение типов.java.util.Список,сопоставление типов]; аргументы [org.springframework.контекст.поддержка.Defaultmessagesourcerразрешимые: коды [зарегистрированныйстудент.хобби,хобби]; аргументы []; сообщение по умолчанию [хобби]]; сообщение по умолчанию [Не удалось преобразовать значение свойства типа ‘java.lang.Строка[]» для требуемого типа «java.util.List» для свойства «хобби»; вложенное исключение-org.каркасная работа.ядро.преобразование.Исключение ConversionFailedException: Не удалось преобразовать из типа [java.lang.Строка] для ввода [java.lang.Целое число] для значения «Пение»; вложенным исключением является исключение java.lang.NumberFormatException: Для входной строки: «Пение»]

В значительной степени Хобби с именем = строковое значение флажков больше не может быть инициализировано. Я попытался удалить хранилище хобби, и оно отлично работает. Любое дальнейшее понимание было бы оценено, поскольку единственным возможным решением на данный момент, по-видимому, является добавление дополнительного поля<Строка> списка<Строка> в моем классе POJO для студентов и использование значений из флажков, переданных в поле, для инициализации объектов хобби, содержащихся в Student.хобби.