【问题标题】:MVC and Object with Set<>MVC 和带有 Set<> 的对象
【发布时间】:2016-03-10 20:13:07
【问题描述】:

我有 2 个在 Hibernate 中映射的类。
1.类实现账号
2. 类实现账户类型。
重要!一个帐户可以有多种类型。

 Account.class
    @Entity
    @Table(name = "dp_account",
            uniqueConstraints={@UniqueConstraint(columnNames={"id"})})
        public class Account {

            @Id
            @Column(name="id", nullable = false, unique = true, length = 11)
            @GeneratedValue(strategy = GenerationType.AUTO)
            private long id;

            @Column(name = "price", nullable = false)
            private int price;

            @Column(name = "customer_id", nullable = false, unique = true, length = 11)
            private long customerId;

            @Column(name = "customer", length = 100, nullable = false, unique = true)
            private String customer;

            @Column(name = "comment", length = 1000)
            private String comment;

            @Column(name = "date", columnDefinition="TIMESTAMP")
            @Temporal(TemporalType.TIMESTAMP)
            private Date date;

            @Column(name = "is_deleted", nullable = false)
            private boolean deleted = false;

            @ManyToMany(fetch = FetchType.EAGER, targetEntity = AccountType.class, cascade = { CascadeType.ALL })
            @JoinTable(name = "account_accountType",
                    joinColumns = { @JoinColumn(name = "account_id") },
                    inverseJoinColumns = { @JoinColumn(name = "type_id") })
            private Set<AccountType> accountTypes;
        // дальше конструкторы и геттеры/сеттеры
        }

具有名称、描述、id 和所有者名称的帐户类型的本质。

    AccountType.class
    @Entity
    @Table(name = "account_type")
    public class AccountType {
        private static final Long serialVersionUID = -4727727495060874301L;

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

        @Column(name = "name", length = 25, nullable = false, unique = true)
        private String name;

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

        @Column(name = "user_login", length = 45, nullable = false, unique = true)
        private String login;
   //дальше геттеры/сеттеры и конструкторы
}

问题是 - 有一个页面让我填写表格以创建帐户 (Account.class),我做multiple select,填写账户类型 (AccountType.class)。 Account.class 有字段Set&lt;AccountType&gt; accountTypes,其中每个帐户都包含一个类型列表。 (这是我要填写的列表,然后在 MVC 控制器中传递 Account.class)。但是在控制器中我什至没有得到 400 错误。经过多次测试后,我意识到 Spring MVC 并没有绑定我的列表。我想知道怎么做?

MVC 控制器:

@RequestMapping(value = "/account/addAccount", method = RequestMethod.POST)
    public void addAccount(@ModelAttribute("accountAttribute") Account account) {
        System.out.println("Account on the top");
        System.out.println(account);
        ServiceFactory.getInstance().getAccountService().addAccount(account);
    }

JSP:

<div style="margin-top: 40px">
            <form:form action="${pageContext.request.contextPath}/account/addAccount" method="post" modelAttribute="accountAttribute">

                <label>
                    Сумма: <input type="number" name="price">
                </label>
                <br> <br>

                <label>
                    Категория:
                    <select multiple name="accountTypes">
                        <c:forEach items="${accountTypes}" var="accountType">
                        <option value="${accountType.name}">${accountType.name}</option>
                        </c:forEach>
                    </select>
                </label>
                <br><br>

                <label>Комментарий:
                    <br> <br>
                    <textarea name="comment" rows="5" cols="30"></textarea>
                </label>
                <br><br>

                <input type="submit" value="Внести">

            </form:form>
        </div>

截图示例:

更新:

@RequestMapping(value = "/welcome", method = RequestMethod.GET)
    public ModelAndView welcomePage() {
        ModelAndView model = new ModelAndView();
        List<GrantedAuthority> grantedAuthorityList = (List<GrantedAuthority>) SecurityContextHolder.getContext().getAuthentication().getAuthorities();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String login = authentication.getName();
        if (grantedAuthorityList.contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
            model.setViewName("admin");
        } else {
            List<AccountType> accountTypes = ServiceFactory.getInstance().getAccountService().getAllAccountTypeByLogin(login);
            model.addObject("accountTypes", accountTypes);
            model.setViewName("user");
        }
        return model;
    }

【问题讨论】:

    标签: java spring hibernate jsp spring-mvc


    【解决方案1】:

    您正在使用 html 选择元素,但您需要做的是使用 spring 标签库的选择,即:

    <form:select path="accountTypes" multiple="true">
      <form:options items="${accountTypes}"/>
    </form:select>
    

    这样spring会绑定控制器中的值。

    试试这个

    @RequestMapping(value = "/welcome", method = RequestMethod.GET)
    public ModelAndView welcomePage() {
        ModelAndView model = new ModelAndView();
        List<GrantedAuthority> grantedAuthorityList = (List<GrantedAuthority>) SecurityContextHolder.getContext().getAuthentication().getAuthorities();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String login = authentication.getName();
        if (grantedAuthorityList.contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
            model.setViewName("admin");
        } else {
            List<AccountType> accountTypes = ServiceFactory.getInstance().getAccountService().getAllAccountTypeByLogin(login);
            model.addObject("accountTypes", accountTypes);
            model.setViewName("user");
    //Add here
    model.addObject("accountAttribute", new Account());
        }
        return model;
    }
    

    【讨论】:

    • 感谢您的回答,但是当我使用您的解决方案时。我有一个问题“java.lang.IllegalStateException:Bean 名称 'accountAttribute' 的 BindingResult 和普通目标对象都不能用作请求属性”
    • 这可能是因为您没有在控制器中的模型中添加 accountAttribute,它会返回您作为屏幕截图附加的页面。
    • 签入我的问题帖子 MVC 控制器。我认为我添加了 accountAttribute。我弄错了吗?
    • 您发布的控制器方法映射到您附加的页面的提交操作,对吗?而我正在谈论将您带到表单页面的控制器功能的变化。你看到我更新的答案了吗?
    • 说实话,我不太明白这个控制器是什么。我有一个创建对象的表单,该控制器该怎么做?
    【解决方案2】:

    问题是您需要注册一个能够将您的帐户类型名称转换为 AccountType 对象的属性编辑器或转换器。您的视图发送 accountTypes 元素的字符串值。 Spring 需要知道如何将 String 值绑定到 Object。

    public class AccountTypeEditor extends PropertyEditorSupport{
    
       public void setAsText(String text){
            AccountType accountType = // some logic to find account type by name
            setValue(accountType);
       }
    }
    

    在您的控制器中,您需要一个 @InitBinder 方法来注册您的编辑器

    @InitBinder
    public void initBinder(WebDataBinder binder){
       binder.registerCustomEditor(AccountType.class , new AccountTypeEditor());
    }
    

    }

    【讨论】:

    • 我解决了这个问题,有兴趣的可以看看。我回复了
    【解决方案3】:

    我能够解决这个问题,我开始分别传递Set和对象本身的Account。问题是我从 jsp Account 传递过来,我想得到 Set,这是不可能的,因为我只选择了 name 类型的帐户。这是解决我的问题:

    JSP:

    <form:form action="${pageContext.request.contextPath}/account/addAccount" method="post" modelAttribute="accountAttribute">
    
                    <label>
                        Сумма: <input type="number" name="price">
                    </label>
                    <br> <br>
    
                    <select multiple name="accountTypeNameSet" size="4s">
                        <c:forEach items="${accountTypes}" var="accountType">
                            <option >${accountType}</option>
                        </c:forEach>
                    </select>
    
                    <label>Комментарий:
                        <br> <br>
                        <textarea name="comment" rows="5" cols="30"></textarea>
                    </label>
                    <br><br>
    
                    <input type="submit" value="Внести">
    
                </form:form>
    

    控制器:

    @RequestMapping(value = "/account/addAccount", method = RequestMethod.POST)
        public void addAccount(@ModelAttribute("accountAttribute") Account account, @RequestParam(value="accountTypeNameSet") Set<String> accountTypeNameSet) {
        // implementation here
    // accountTypeNameSet - This is the list of names account type, which user selected. On the basis of these names we can pull your invoice from database. 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-24
      • 2011-09-21
      • 1970-01-01
      • 2015-09-03
      • 2014-01-15
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      相关资源
      最近更新 更多