【问题标题】:form:select does not set the selected valueform:select 不设置选中的值
【发布时间】:2026-02-05 14:30:01
【问题描述】:

基本上我需要一个用于付款的 CRUD 应用程序。每笔付款都分配给一个帐户。

我的 jsp 页面显示了正确的“帐户”对象列表,但没有设置所选帐户。

  1. 问题:如何实现预选指定帐户的下拉框?

  2. 问题:分配(帐户到付款)有效,但仅适用于我的 PaymentDaoImpl.java 中的以下代码(标记为解决方法)。为什么会这样?

PaymentDaoImpl.java

..
@Override
@Transactional
public int insertRow(Payment obj) {
    // Session session = HibernateUtil.getSessionFactory().openSession();
    Session session = sessionFactory.openSession();

    // !!!! workaround?? If I don't do this, account won't be assigned
    int accountId = obj.getAccount().getId();   
    Account account = (Account) session.get(Account.class, accountId);
    obj.setAccount(account);

    Transaction tx = session.beginTransaction();
    session.saveOrUpdate(obj);
    tx.commit();
    Serializable id = session.getIdentifier(obj);
    session.close();
    return (Integer) id;
}
..

jsp:

<form:select path="account.id"   >
    <form:option  value="-1" label="Select Account" />         
    <form:options items="${accountList}" itemValue="id" itemLabel="iban" />
</form:select>

域帐户.java:

package com.beingjavaguys.domain;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.persistence.Entity;  
import javax.persistence.GeneratedValue;  
import javax.persistence.GenerationType;  
import javax.persistence.Id;
import javax.persistence.*;

import org.springframework.beans.factory.annotation.Autowired;


@Entity
public class Account {

    @Id
    @GeneratedValue
    private int id;

    private String iban;

    private String bank;

    private String beschreibung;


    public int getId() {
        return id;
    }

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

    public String getIban() {
        return iban;
    }

    public void setIban(String iban) {
        this.iban = iban;
    }

    public String getBank() {
        return bank;
    }

    public void setBank(String bank) {
        this.bank = bank;
    }

    public String getBeschreibung() {
        return beschreibung;
    }

    public void setBeschreibung(String beschreibung) {
        this.beschreibung = beschreibung;
    }

}

域名支付

package com.beingjavaguys.domain;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import org.springframework.beans.factory.annotation.Autowired;



@Entity
public class Payment {


    private int id;


    private Account account;

    private float amount;

    private String text;

    private String comment;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    @ManyToOne(cascade = CascadeType.ALL, targetEntity = Account.class, fetch=FetchType.EAGER)
    @JoinColumn(name="fk_account")
    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public float getAmount() {
        return amount;
    }

    public void setAmount(float amount) {
        this.amount = amount;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }


}

PaymentController.java

package com.beingjavaguys.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.beingjavaguys.domain.Payment;
import com.beingjavaguys.services.AccountService;
import com.beingjavaguys.services.PaymentService;

@Controller
@RequestMapping("/payment")
public class PaymentController {

    @Autowired
    PaymentService dataService;
    @Autowired
    AccountService accountService;

    @RequestMapping("form")
    public ModelAndView getForm(@ModelAttribute Payment obj) {
        ModelAndView mav = new ModelAndView("payment/form");
        mav.addObject("accountList", accountService.getList());
        return mav;
    }

    @RequestMapping("insert")   
    public ModelAndView insert(@ModelAttribute Payment obj) {       
        dataService.insertRow(obj);
        return new ModelAndView("redirect:list");
    }

    @RequestMapping("list")
    public ModelAndView getList() {
        List objList = dataService.getList();
        return new ModelAndView("payment/list","objList",objList);
    }

    @RequestMapping("delete")
    public ModelAndView deleteUser(@RequestParam int id) {
        dataService.deleteRow(id);
        return new ModelAndView("redirect:list");
    }

    @RequestMapping("edit")
    public ModelAndView editUser(@RequestParam int id,@ModelAttribute Payment obj) {
        ModelAndView mav = new ModelAndView("payment/form");

        Payment paymentObj = dataService.getRowById(id);
        mav.addObject("accountList", accountService.getList());
        mav.addObject("paymentObj", paymentObj);

        return mav;
    }

    @RequestMapping("update")
    public ModelAndView updateUser(@ModelAttribute Payment obj) {
        dataService.updateRow(obj);
        return new ModelAndView("redirect:list");
    }

}

您能看看我的 AccountEditor 实现吗?我是否需要 AccountService 来查找帐户?但是,我没有在这里实例化服务..

public class AccountEditor extends PropertyEditorSupport {
    @Autowired
    AccountService dataService; // == null ??

    @Override
    public void setAsText(String text) {
        Account account = lookupAccount(text); // lookup account by accountId
                                                // text
        setValue(account);
    }

    private Account lookupAccount(String text) {
        int id = Integer.parseInt(text);
        return dataService.getRowById(id);
    }
}

【问题讨论】:

    标签: spring forms hibernate model-view-controller


    【解决方案1】:

    您需要一个 PropertyEditor 实现来将 String accountId 转换为 Account 对象。然后在您的 jsp 中,您使用路径形式:select path="account" 而不是 form:select path="account.id"

    如下实现一个PropertyEditor

    public class AccountEditor extends PropertyEditorSupport{
    
       @Override 
       public void setAsText(String text){
          Account account = lookupAccount(text); //lookup account by accountId text
          setValue(account);
      }
    }
    

    然后在您的控制器中注册您的 AccountEditor

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

    通过上述更改,您将不需要解决方法。您的解决方案只是设置帐户的 id 属性,而不是整个对象

    【讨论】:

    • 你能看看我的 AccountEditor 实现吗?
    • 完美。要允许注入 AccountService 依赖项,请将您的 AccountEditor 作为 bean 添加到您的上下文中并将其注入到您的控制器中
    • 谢谢,这解决了我的第二个问题。我还不能解决第一个问题。