복붙노트

[SPRING] 리스트와 체크 박스를 사용한 Spring MVC 데이터 바인딩

SPRING

리스트와 체크 박스를 사용한 Spring MVC 데이터 바인딩

나는이 문제에 대한 질문이 이미 제기되었지만 내 문제를 해결 한 답을 찾지 못했습니다.

내 데이터베이스에는 다 대다 관계가 있습니다. 나는 테이블을 만들고 변경하기 위해 JPA와 Hibernate를 사용하고있다. 내 모델 클래스는 다음과 같습니다.

Book.java

@Entity
@Table(name="tb_books")
public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false, insertable = false)
    private Integer id;

    @Column(name = "title", nullable = false, length = 255)
    private String title;

    @Column(name = "author", nullable = false, length = 255)
    private String author;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.EAGER)
    @JoinTable(name = "book_tag",
               joinColumns = { @JoinColumn(name = "fk_book") },
               inverseJoinColumns = { @JoinColumn(name = "fk_tag") })
    private List<Tag> tags;

    //getters, setters, equals and hash methods...

}

Tag.java

@Entity
@Table(name="tb_tags")
public class Tag implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false)
    private Integer id;

    @Column(name = "description", nullable = false, length = 255)
    private String description;

    //getters, setters, equals and hash methods...
}

Spring MVC를 사용하여 JSP에서 오는 데이터로 내 책 태그 테이블에 삽입 및 업데이트를하려고합니다. 다음은 내 컨트롤러 및 삽입 페이지입니다.

BookController.java

@Controller
@RequestMapping(value = "/book")
public class BookController {

    @Autowired
    private BookService bookService;

    /*
        Controller method that gets us to the adding book page. 
    */    
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView addBookPage() {

        List<Tag> tags = tagService.getTags(); //all tags from the database

        ModelAndView modelAndView = new ModelAndView("form-book");
        modelAndView.addObject("book", new Book());
        modelAndView.addObject("tags", tags);

        return modelAndView;
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public ModelAndView addBookProcess(@ModelAttribute Book book) {

        bookService.addBook(book);
        return new ModelAndView("redirect:/book/add");
    }

    //...

}

form-book.jsp

<form:form method="POST" modelAttribute="book" action="${pageContext.request.contextPath}/book/add.html">
<table>
    <tbody>
        <tr>
            <td>Title:</td>
            <td><form:input path="title" autocomplete="off" /></td>
        </tr>
        <tr>
            <td>Author:</td>
            <td><form:input path="author" autocomplete="off" /></td>
        </tr>
        <tr>
            <td colspan="2">

                <form:checkboxes path="tags" 
                items="${tags}" 
                itemLabel="description"
                itemValue="id"/>

            </td>
        </tr>
        <tr>
            <td><input type="submit" value="Add" /></td>
            <td><input type="button" onclick="location.href = '${pageContext.request.contextPath}/index'" value="Cancel"/></td>
        </tr>
    </tbody>
</table>

</form:form>

하나 이상의 체크 박스가 선택된 책을 업데이트하거나 삽입하려고 시도 할 때를 제외하고는 모든 것이 잘 작동합니다. 내가 그렇게하려고 할 때, 나는 단지 "잘못된 요청"페이지를 얻습니다, 나는 데이터 바인딩과 관련하여 뭔가 잘못하고 있기 때문에 상상합니다.

이게 내가이 상황을 다루는 방식인가? 더 좋은 방법이 있습니까? 내가 뭘 잘못하고 있죠?

해결법

  1. ==============================

    1.분명히 체크 박스에서 나오는 List는 사실 모델 클래스로 정의 된대로 List of Tags로 변환 할 수없는 String 배열이었습니다.

    분명히 체크 박스에서 나오는 List는 사실 모델 클래스로 정의 된대로 List of Tags로 변환 할 수없는 String 배열이었습니다.

    나는 사용자 정의 PropertyEditor를 작성하여 문제를 해결했다. 그러면 체크 박스를 태그 목록과 바인딩 할 수있다.

    public class TagPropertyEditor extends PropertyEditorSupport {
    
        private TagService tagService;
    
        public TagPropertyEditor(TagService tagService){
            this.tagService = tagService;
        }
    
        @Override
        public String getAsText() {
            return ((Tag) getValue()).getId().toString();
        }
    
        @Override
        public void setAsText(String incomingId) throws IllegalArgumentException {
            Tag tag = tagService.getTag(Integer.valueOf(incomingId));
            setValue(tag);
        }
    }
    

    그리고 내 BookController에 등록하십시오 :

    //...
    @InitBinder
    public void initBinder(WebDataBinder binder){
        binder.registerCustomEditor(Tag.class, new TagPropertyEditor(tagService));
    }
    

    그리고 이것은 내 JSP의 checkboxes 태그입니다.

     <form:checkboxes path="tags" 
                      items="${tags}"
                      itemLabel="description"
                      itemValue="id"/>
    
  2. from https://stackoverflow.com/questions/46123767/spring-mvc-databinding-using-lists-and-checkboxes by cc-by-sa and MIT license