java - 字段 'user' 上的对象 'userProfiles' 中的字段错误 : rejected value [3];

标签 java spring jsp spring-mvc jpa

我已经下载了一个工作演示,在我运行它时运行得非常好。但是当我刚刚完成我的方式并且我使用与注册页面相同的页面和功能然后我提交表格时我收到错误:

[Field error in object 'user' on field 'userProfiles': rejected value [3]; codes [typeMismatch.user.userProfiles,typeMismatch.userProfiles,typeMismatch.java.util.Set,typeMismatch]; arguments 
    [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.userProfiles,userProfiles]; arguments []; default message [userProfiles]]; default message 
[Failed to convert property value of type 'java.lang.String' to required type 'java.util.Set' for property 'userProfiles'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type 
[com.idev.tpt.model.UserProfile] for property 'userProfiles[0]': no matching editors or conversion strategy found]]

JSP 文件:

<form:form id="userForm" action="newuser" modelAttribute="user">
    <form:input type="hidden" path="id" id="id" />
    <div class="form-group">
        <form:input type="text" path="firstName" id="firstName" placeholder="First Name" class="form-control input-sm" />
    </div>
    <div class="form-group">
        <form:input type="text" path="lastName" id="lastName" placeholder="Last Name" class="form-control input-sm" />
    </div>
    <div class="form-group">
        <c:choose>
            <c:when test="${edit}">
                <form:input type="text" path="ssoId" id="ssoId" placeholder="SSO ID" class="form-control input-sm" disabled="true" />
            </c:when>
            <c:otherwise>
                <form:input type="text" path="ssoId" id="ssoId" placeholder="SSO ID" class="form-control input-sm" />
                <div class="has-error">
                    <form:errors path="ssoId" class="help-inline" />
                </div>
            </c:otherwise>
        </c:choose>
    </div>
    <div class="form-group">
        <form:input type="password" path="password" id="password" placeholder="password" class="form-control input-sm" />
        <div class="has-error">
            <form:errors path="password" class="help-inline" />
        </div>
    </div>
    <div class="form-group">
        <form:input type="text" path="email" id="email" placeholder="email" class="form-control input-sm" />
        <div class="has-error">
            <form:errors path="email" class="help-inline" />
        </div>
    </div>

    <div class="form-group">
        <form:select path="userProfiles" items="${roles}" multiple="true" itemValue="id" itemLabel="type" class="form-control input-sm" />
    </div>
    <!-- <div class="form-group">
                                            <textarea class="form-control" id="prop_note" name="note" placeholder="Note" ></textarea>
                                        </div> -->
    <p class="demo-button btn-toolbar">
        <span id="warningLbl" class="label label-warning" style="display: none;"></span>
        <button id="propAddBtn" type="submit" class="btn btn-primary pull-right">Save</button>
        <button id="propUpdateBtn" type="submit" class="btn btn-primary pull-right" style="display: none;">Update</button>&nbsp;
        <button id="propClearBtn" type="button" class="btn btn-primary pull-right" style="display: none;">Clear</button>
    </p>
    <br>
</form:form>

Controller :

@RequestMapping(value = { "/newuser" }, method = RequestMethod.GET)
    public String newUser(ModelMap model) {
        User user = new User();
        model.addAttribute("user", user);
        model.addAttribute("edit", false);
        model.addAttribute("roles", userProfileService.findAll());
        model.addAttribute("loggedinuser", getPrincipal());
        return "registration";
    }

    /**
     * This method will be called on form submission, handling POST request for
     * saving user in database. It also validates the user input
     */
    @RequestMapping(value = { "/newuser" }, method = RequestMethod.POST)
    public String saveUser(@Valid User user, BindingResult result,
            ModelMap model) {
        if (result.hasErrors()) {
            return "registration";
        }

        if(!userService.isUserSSOUnique(user.getId(), user.getSsoId())){
            FieldError ssoError =new FieldError("user","ssoId",messageSource.getMessage("non.unique.ssoId", new String[]{user.getSsoId()}, Locale.getDefault()));
            result.addError(ssoError);
            return "registration";
        }

        userService.saveUser(user);

        model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " registered successfully");
        model.addAttribute("loggedinuser", getPrincipal());
        //return "success";
        return "registrationsuccess";
    }

模型:

package com.websystique.springmvc.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.validator.constraints.NotEmpty;

@SuppressWarnings("serial")
@Entity
@Table(name="APP_USER")
public class User implements Serializable{

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    @NotEmpty
    @Column(name="SSO_ID", unique=true, nullable=false)
    private String ssoId;

    @NotEmpty
    @Column(name="PASSWORD", nullable=false)
    private String password;

    @NotEmpty
    @Column(name="FIRST_NAME", nullable=false)
    private String firstName;

    @NotEmpty
    @Column(name="LAST_NAME", nullable=false)
    private String lastName;

    @NotEmpty
    @Column(name="EMAIL", nullable=false)
    private String email;

    @NotEmpty
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "APP_USER_USER_PROFILE", 
             joinColumns = { @JoinColumn(name = "USER_ID") }, 
             inverseJoinColumns = { @JoinColumn(name = "USER_PROFILE_ID") })
    private Set<UserProfile> userProfiles = new HashSet<UserProfile>();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getSsoId() {
        return ssoId;
    }

    public void setSsoId(String ssoId) {
        this.ssoId = ssoId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Set<UserProfile> getUserProfiles() {
        return userProfiles;
    }

    public void setUserProfiles(Set<UserProfile> userProfiles) {
        this.userProfiles = userProfiles;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((ssoId == null) ? 0 : ssoId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof User))
            return false;
        User other = (User) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (ssoId == null) {
            if (other.ssoId != null)
                return false;
        } else if (!ssoId.equals(other.ssoId))
            return false;
        return true;
    }

    /*
     * DO-NOT-INCLUDE passwords in toString function.
     * It is done here just for convenience purpose.
     */
    @Override
    public String toString() {
        return "User [id=" + id + ", ssoId=" + ssoId + ", password=" + password
                + ", firstName=" + firstName + ", lastName=" + lastName
                + ", email=" + email + "]";
    }

}

我也在使用演示中提供的相同模型。我没有更改模型中的任何内容,也没有更改与 jsp 和 Controller 相关的内容。我不明白为什么我在使用与演示中相同的方式时遇到错误。

用户个人资料

package com.websystique.springmvc.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name="USER_PROFILE")
public class UserProfile implements Serializable{

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id; 

    @Column(name="TYPE", length=15, unique=true, nullable=false)
    private String type = UserProfileType.USER.getUserProfileType();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((type == null) ? 0 : type.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof UserProfile))
            return false;
        UserProfile other = (UserProfile) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (type == null) {
            if (other.type != null)
                return false;
        } else if (!type.equals(other.type))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "UserProfile [id=" + id + ", type=" + type + "]";
    }
}

用户资料转换器

package com.websystique.springmvc.converter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import com.websystique.springmvc.model.UserProfile;
import com.websystique.springmvc.service.UserProfileService;

/**
 * A converter class used in views to map id's to actual userProfile objects.
 */
@Component
public class RoleToUserProfileConverter implements Converter<Object, UserProfile>{

    static final Logger logger = LoggerFactory.getLogger(RoleToUserProfileConverter.class);

    @Autowired
    UserProfileService userProfileService;

    /**
     * Gets UserProfile by Id
     * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
     */
    public UserProfile convert(Object element) {
        Integer id = Integer.parseInt((String)element);
        UserProfile profile= userProfileService.findById(id);
        logger.info("Profile : {}",profile);
        return profile;
    }

}

已更新

还有一件事,当我使用模型 getter 方法 getUserProfiles() 打印表单数据时,我得到的是空白数据,所以我认为它没有绑定(bind)所选值。但是我正在打印的任何其他列都将完美绑定(bind)。

最佳答案

在你发表评论后我更新了我的回复:

问题可能出在 JSP 代码中。当应用程序调用 saveUser() Controller 中的方法,将创建一个新的 User 对象。但是因为你有 UserProfile输入应用程序必须知道如何创建的用户对象 UserProfile来自字符串(当从 <form:select path="userProfiles"> 传递时)。

要么添加一个从 String 到 UserProfile 的自定义转换器或者创建一个 UserDTO使用 Java 标准类型进行分类,并在您的 Controller 保存操作中使用它。代码将类似于:

public String saveUser(@Valid UserDTO dto, ...) {
    User user = createUserFromDTO(dto);
    userService.saveUser(user);
}

如果您定义了转换器,请检查它是否已添加到 FormatterRegistry在应用程序配置期间。

还要确保您拥有 UserProfile使用 JPA 注释正确定义的实体。

关于java - 字段 'user' 上的对象 'userProfiles' 中的字段错误 : rejected value [3];,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50173341/

相关文章:

java - 有数据库逆向工程的框架吗?

java - 配置基本路径下的 Spring Data REST Controller

java - JPA 添加逻辑以删除实体

java - 修剪() List<String> 中所有元素的最佳方法是什么?

java - Spring JPA : XML Configuration - No qualifying bean of Repository/no declaration can be found for element 'jpa:repositories'

java - spring状态机并行实例中子状态的异步执行

java - 自定义 validator 是否可以根据 hibernate validator 中验证失败的内容有多条消息?

java - JSTL嵌套foreach循环不打印

java - Heroku 上的 JSP - "Unable to compile class for JSP"

jsp - JSP页面内textarea的占位符