2012-01-02 8 views
13

So che ci sono già state le domande intorno a questo argomento, ma non ho capito come risolvere il seguente problema:Spring MVC utilizzo della forma: casella di controllo per associare i dati

ho un/rapporto ruoli utente e io desidera elencare tutti i ruoli disponibili in un JSP come elementi della casella di controllo, in cui sono selezionate le caselle di controllo assegnate agli utenti. Tuttavia, gli elementi corrispondenti non vengono controllati (qui sto usando Spring 3.1).

estratto dall'oggetto Utente:

private Set<RoleEntity> roles = new HashSet<RoleEntity>(); 

estratto dal controller Primavera (aggiungendo oggetto utente e la lista ruolo da modello):

UserEntity userEntity = userEntityService.findById(UserEntity.class, new Long(id)); 
model.addAttribute("userAttribute", userEntity); 

List<RoleEntity> roleList = roleEntityService.findAll(); 
model.addAttribute("roleList", roleList); 

Estratto della JSP:

<form:form modelAttribute="userAttribute" method="POST" action="${saveUrl}"> 
... 

    <table align="center"> 
     <tr> 
      <td>ID</td> 
      <td>Role Name</td> 
     </tr> 
     <c:forEach items="${roleList}" var="role" varStatus="status"> 
      <tr> 
       <td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td> 
       <td><c:out value="${role.name}" /></td> 
      </tr> 
     </c:forEach> 
    </table> 

... 
</form:form> 

La documentazione Spring MVC dice questo: Quando il valore associato è di tipo array o java.util.Collection, l'input (checkbox) è contrassegnato come 'checked' se il valore configurato setValue (Object) è presente nella Collection associata.

Non è questo il caso? Cosa mi manca qui?

Grazie mille.

Paul

risposta

20

La mia ipotesi è vi manca l'implementazione per le equals e hashcode metodi sulla classe RoleEntity.

Quando il valore limite è di tipo array o java.util.Collection, l'ingresso (casella di controllo) è contrassegnato come 'controllato' se il valore configurato setValue (Object) è presente nella Collezione legato.

Questo è corretto, ma per verificare la presenza in un HashSet è necessario equals e hashcode implementato correttamente.

Proprio come un test rapido per vedere se questo è il problema, sostituire questa linea:

model.addAttribute("roleList", roleList); 

con questa linea:

model.addAttribute("roleList", userEntity.getRoles()); 

Non si ottiene tutte le caselle di controllo controllati? Se sì, allora non hai fornito il tuo equals e hashcode e quelli di default sono utilizzati (quelli ereditati da Object).

Il valore predefinito equals confronta l'identità, il che significa che una variabile contiene la stessa istanza di un'altra variabile. Uguaglianza significa che due oggetti diversi contengono lo stesso stato o hanno lo stesso significato, per così dire.

L'utilizzo di model.addAttribute("roleList", userEntity.getRoles()) attiva il metodo predefinito equals per restituire true poiché l'elenco ei valori che si verificano per presenza nell'elenco sono identici (due oggetti identici sono sempre uguali).

Ma nel tuo caso si utilizza userEntityService.findById per uno e roleEntityService.findAll per l'altro che significa diversi oggetti. A questo punto devi usare un test di uguaglianza appropriato invece dell'identità.

Avete implementato equals/hashcode?

Sulla base di codice, ecco un esempio che funziona:

Controller:

import java.util.Arrays; 
import java.util.Collections; 
import java.util.HashSet; 
import java.util.List; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

@Controller 
public class SomeController { 
    @RequestMapping(value = "/something", method = { RequestMethod.GET, RequestMethod.POST }) 
    public String handle(Model model) { 

     UserEntity userEntity = new UserEntity(); 
     userEntity.setRoles(new HashSet<RoleEntity>()); 
     Collections.addAll(userEntity.getRoles(), 
           new RoleEntity(1, "one"), 
           new RoleEntity(3, "three")); 
     model.addAttribute("userAttribute", userEntity);   

     List<RoleEntity> roleList = Arrays.asList(
             new RoleEntity(1, "one"), 
             new RoleEntity(2, "two"), 
             new RoleEntity(3, "three") 
            ); 
     model.addAttribute("roleList", roleList); 

     return "view"; 
    } 
} 

classe User:

import java.util.HashSet; 
import java.util.Set; 

public class UserEntity { 
    private Set<RoleEntity> roles = new HashSet<RoleEntity>(); 

    public Set<RoleEntity> getRoles() { 
     return roles; 
    } 
    public void setRoles(Set<RoleEntity> roles) { 
     this.roles = roles; 
    } 
} 

ruoli classe (preavviso la equals e hashcode metodi; se li rimuovi, il esempio non funziona più):

public class RoleEntity { 
    private long id; 
    private String name; 

    @Override 
    public int hashCode() { 
     return new Long(id).hashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (! (obj instanceof RoleEntity)) { 
      return false; 
     } 
     return this.id == ((RoleEntity)obj).getId(); 
    } 

    public RoleEntity(long id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public long getId() { 
     return id; 
    } 
    public void setId(long id) { 
     this.id = id; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
} 

Vista:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> 
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<form:form modelAttribute="userAttribute" method="POST" action="/something"> 
    <table align="center"> 
     <tr> 
      <td>ID</td> 
      <td>Role Name</td> 
     </tr> 
     <c:forEach items="${roleList}" var="role"> 
      <tr> 
       <td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td> 
       <td><c:out value="${role.name}" /></td> 
      </tr> 
     </c:forEach> 
    </table> 
</form:form> 

P.S. Una sola osservazione sulla tua JSP. Se esegui lo value="${role}" per il tuo modulo: checkbox otterrai gli attributi della casella di controllo HTML come value="[email protected]" che potrebbero metterti in un altro tipo di problema in seguito.

+0

Grazie mille, Bogdan. Questa risposta mi ha davvero aiutato !! Tuttavia, le caselle di controllo vengono verificate solo quando aggiungo i ruoli utente alla vista: model.addAttribute ("roleList", userEntity.getRoles()); ma non funziona con tutti i ruoli. –

+0

@Paul Kuhn: prego. Ho aggiunto alcune spiegazioni come risposta al tuo commento per migliorare la risposta. [Qui] (http://tutorials.jenkov.com/java-collections/hashcode-equals.html) è una presentazione più dettagliata. Spero che aiuti a spiegare ulteriormente cosa stava causando il comportamento. – Bogdan

Problemi correlati