Я использую Spring MVC и пытаюсь сохранить базовую анкету с ответами да / нет (истина / ложь) на Map<String, Boolean>
, где клавишей String является "Q1", "Q2" соответственно.
На стороне контроллера он связывается должным образом, устанавливая соответствующие входные значения на карту, но когда объект сущности передается в службу для сохранения, возникает исключение ClassCastException с жалобой на то, что его нельзя сохранить.Тип базы данных (postgres) - логический.
Исключение
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
at org.hibernate.type.descriptor.java.BooleanTypeDescriptor.unwrap(BooleanTypeDescriptor.java:19) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.type.descriptor.sql.BooleanTypeDescriptor$1.doBind(BooleanTypeDescriptor.java:44) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:74) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:280) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:275) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:903) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.persister.collection.BasicCollectionPersister.doUpdateRows(BasicCollectionPersister.java:231) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.updateRows(AbstractCollectionPersister.java:1728) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
Сущность
@Entity
public class Questionnaire {
private static final long serialVersionUID = 1L;
public static final String[] SHORT_QUESTIONS = {"q1", "q2", "q3", "q4", "q5", "q6", "q7"};
@ElementCollection(fetch=FetchType.LAZY)
@MapKeyColumn(name="question")
@Column(name="answer")
private Map<String, Boolean> shortForm = new LinkedHashMap<>();
// constructor, setters and getters here
}
Метод контроллера:
@PostMapping("/questionnaire/save/{id}")
public String save(@ModelAttribute @Valid Questionnaire questionnaire, BindingResult binder, RedirectAttributes redirectAttrs, Model model) {
if (binder.hasErrors()) {
model.addAttribute("messageDanger", messages.getMessage("general.save.failed", null, LocaleContextHolder.getLocale()));
return "questionnaire/full";
}
// these all bind properly and return true or false accordingly
log.debug("q1: " + questionnaire.getShortForm().get("q1"));
log.debug("q2: " + questionnaire.getShortForm().get("q2"));
log.debug("q3: " + questionnaire.getShortForm().get("q3"));
log.debug("q4: " + questionnaire.getShortForm().get("q4"));
log.debug("q5: " + questionnaire.getShortForm().get("q5"));
log.debug("q6: " + questionnaire.getShortForm().get("q6"));
// Exception occurs here during .save()
questionnaireSvc.save(questionnaire);
redirectAttrs.addFlashAttribute("message", messages.getMessage("general.save.success", null, LocaleContextHolder.getLocale()));
return "redirect:/questionnaire/full/" + questionnaire.getId();
}
HTML (Thymeleaf)
<tr th:each="question : ${T(app.model.Questionnaire).SHORT_QUESTIONS}">
<td headers="question-col" th:utext="#{questionnaire.short.__${question}__}"></td>
<td headers="applicant-col">
<div class="custom-control custom-radio">
<input type="radio" th:field="*{shortForm[__${question}__]}" class="custom-control-input" required value="false" />
<label class="custom-control-label" th:text="#{general.no}" th:for="${#ids.prev('shortForm__${question}__')}"></label>
</div>
<div class="custom-control custom-radio">
<input type="radio" th:field="*{shortForm[__${question}__]}" class="custom-control-input" required value="true" />
<label class="custom-control-label" th:text="#{general.yes}" th:for="${#ids.prev('shortForm__${question}__')}"></label>
</div>
</td>