Spring Boot,Thymeleaf,ManyToMany复选框评估

时间:2016-06-04 04:51:06

标签: spring-boot thymeleaf

我在互联网上看过很多例子,看起来解决方案应该可以正常工作。但仍然无法使我的代码工作。

用户:

@Entity
@Table(name = "users")
public class User implements Serializable{

private static final long serialVersionUID = 1L;    
...

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "user_usertypes", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "usertype_id", referencedColumnName = "id"))
private Set<UserType> userTypes;
}

的用户类型:

@Entity
@Table(name = "usertypes")
public class UserType implements Serializable{

private static final long serialVersionUID = 1L;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Version
@Column(name = "version")
private Integer version;

@Column(name = "name")
private String name;

@ManyToMany(mappedBy = "userTypes")
private Set<User> users;

@Override
public int hashCode() {
    int hash = 5;
    hash = 83 * hash + Objects.hashCode(this.id);
    return hash;
}

@Override
public boolean equals(Object obj) {
    System.out.println("comparing objects");
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()){
        return false;
    }
    final UserType other = (UserType) obj;
    return Objects.equals(this.id, other.id);
}
}

用户控制器:

@Controller
public class UserController {
    @RequestMapping(value = "/user", method = RequestMethod.POST)
public String saveUser(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return "users/userform";
    }
    System.out.println(user.getUserTypes());
    userService.saveUser(user);
    return "redirect:/user/" + user.getId();
}

@InitBinder
private void initBinder(ServletRequestDataBinder binder) {

    binder.registerCustomEditor(Set.class, "userTypes", new CustomCollectionEditor(Set.class) {
        protected Object convertElement(Object element) {
            if (element != null) {
                System.out.println("From Controller: " + element.toString());
                return userTypeService.findOne(Integer.parseInt(element.toString()));
            }
            return null;
        }

    });
}

用户窗体:

<form th:object="${user}" th:action="@{/user}" method="post">
<input type="hidden" th:field="*{id}"/>
<ul>
   <li th:each="type : ${types}">
     <input type="checkbox"  th:id="${type.id}" th:field="*{userTypes}" th:value="${type.id}"/>
     <label th:for="${type.id}" th:text="${type.name}">name</label>
   </li>
 </ul>
<form>

initBinder不会在提交时调用。仅在页面加载时。 所以,我的控制器无法获取userTypes对象。缺什么?谢谢!

1 个答案:

答案 0 :(得分:0)

我找到了一个简单快捷的解决方案。可能不是最好的,但它按预期工作。希望,它会帮助别人。

用户实体:

private List<UserType> userTypes = new ArrayList<>();

控制器中,我创建了一个帮助程序,为当前用户创建一个新的List以匹配表单上的索引:

public String edit(@PathVariable Integer id, Model model) {
    model.addAttribute("user", updatedTypes(userService.getUserById(id)));
    model.addAttribute("types", userTypeService.getAllUserTypes());
    return "users/userform";
}

private User updatedTypes(User user) {
    List<UserType> userTypes = new ArrayList<>();
    for (long i = 0; i < userTypeService.count(); i++) {
        userTypes.add(new UserType());
    }
    for (UserType type : user.getUserTypes()) {
        userTypes.add(type.getId() - 1, type);
    }
    user.setTypes(userTypes);
    return user;
}

<强>模板:

 <li th:each="type, stat : ${types}">
     <input type="checkbox" th:field="*{userTypes[__${stat.index}__]}"
           th:value="${type.id}"/>
     <label th:for="|userTypes${stat.index}|+1" th:text="${type.name}">
           name
     </label>
 </li>

另外,我摆脱了initBinder方法。我不知道为什么,但它绝对没用。