2016-06-04 11 views
2

Ich habe viele Beispiele im Internet gesehen und sieht aus wie die Lösung sollte gut funktionieren. Trotzdem konnte ich meinen Code nicht funktionieren lassen.Spring Boot, Thymeleaf, ManyToMany Kontrollkästchen Auswertung

Benutzer:

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

Usertype:

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

Benutzer Controller:

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

    }); 
} 

Userform:

<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> 

Der initBinder wird beim Senden nicht aufgerufen. Nur beim Laden der Seite. So kann mein Controller die userTypes-Objekte nicht abrufen. Was fehlt? Vielen Dank!

+0

Beitrag: 'id = 1 & version = 77 & contact.id = 14 & contact.version = 0 & userTypes = 1 & _userTypes = on & userTypes = 2 & _userTypes = on & _csrf = dfffa09b-be52-4d1a-9725-f623aeba81c2' – user3841429

Antwort

0

Ich fand eine einfache und schnelle Lösung. Wahrscheinlich nicht die beste, aber es funktioniert wie erwartet. Hoffe, es wird jemandem helfen.

Benutzer Entity:

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

Im Controller, habe ich einen Helfer, der eine neue Liste für den aktuellen Benutzer die Indizes auf dem Formular übereinstimmen erstellt:

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

Vorlage:

<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> 

Auch ich habe die InitBinder-Methode los. Ich weiß nicht warum, aber es ist absolut nutzlos.