将某个 class 的集合的布尔属性绑定到复选框

Binding boolean properties of a Set of a certain class to checkboxes

我希望(从我的数据库中)获取每个大陆的国家/地区列表作为带有复选框的标签,使特定国家/地区成为 shown/used 在我的网络应用程序中。

这是它的视觉效果。

因此我使用 Continentclass:

@Entity
public class Continent implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    
    private String name;
    
    @OneToMany(mappedBy = "continent")
    private Set<Country> countries;

    // Getters, equals, hashCode...
}

还有 Country class:

@Entity
public class Country implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    
    private String name;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "continentid")
    private Continent continent;
    
    private boolean enabled; // THE CHECKBOX
   
    // Getters, equals, hashCode...
}

然后我在适当的控制器中为 Continent 初始化一个活页夹,并将请求的大陆(使用干净的 URL 作为参数)作为对象添加到我的 ModelAndView (GET) :

@Controller
@RequestMapping("/continent")
public class LocaleController {

    private final LocaleService localeService;
    
    @Autowired
    LocaleController(LocaleService localeService) {
        this.localeService = localeService;
    }
    
    @InitBinder("continent")
    void initBinderContinent(WebDataBinder binder) {
        binder.initDirectFieldAccess();
    }
    
    @RequestMapping(path="{continent}", method = RequestMethod.GET)
    ModelAndView readContinent(@PathVariable Continent continent) {
        return new ModelAndView("continent",
                "continent", continent);
    }
    
    @RequestMapping(path="{continent}", method = RequestMethod.POST)
    String editContinent(@PathVariable Continent continent) {
        //TODO hasErrors etc.
        localeService.updateContinent(continent);
        return "redirect:/continents";
    }
}

在我的 JSP 文件的 body 中,我编写了(将 taglib 用于 Spring 表单和 JSTL 核心):

<form:form commandName='continent' id='continentform'>
    
</form:form>
  <h1>${continent.name}</h1>
  <!-- SelectAll and UnselectAll buttons, other HTML tags -->
  <c:forEach var="country" items="${continent.countries}" varStatus="loop">
    <form:checkbox path="countries['${loop.index}'].enabled"/>
    <form:label path="countries['${loop.index}'].enabled">
      ${country.name}
    </form:label>
  </c:forEach>

但这行不通:

首先:循环中的loop.index不对应当前countrySet<Country> countries索引;我知道是因为 country.name 不等于 countries['${loop.index}'].name

其次: 标签 for= 属性与相应的复选框属性不对应 id=.

ThirdlocaleService.updateContinent(continent)调用continentDAO.save(continent)ContinentDAO是扩展JpaRepository<Continent, Long>的接口)但不更新启用状态国家。

我的错误是什么?

为了解决 第一个问题,我不再 return Continent class 中的 Set<Country> countries TreeSet (我只是returncountries)。

为了解决第二个问题我编辑了我的JSP<c:forEach>内容:

<c:forEach var="country" items="${continent.countries}" varStatus="loop">
  <form:checkbox path="countries['${loop.index}'].enabled" cssClass="medium"
          label="${country.name}"/>
</c:forEach>

为了解决第三个问题,我在 LocaleController 中编辑了 editContinent 函数,现在可以使用了:

 @RequestMapping(path="{continent}", method = RequestMethod.POST)
    String editContinent(@Valid Continent continent, BindingResult bindingResult) {
        //TODO hasErrors etc.
        localeService.updateContinent(continent);
        return "redirect:/continents";
 }

感谢 M. Deinum 非常有用的评论。