Вывод списка checkbox-ов на Spring MVC + Hibernate

К примеру у нас есть сущность Пользователь, которая в БД представлена таблицей USER с полями ID и NAME. Кроме идентификатора и имени соответственно у пользователя может быть включен какой-то набор опций. Т.к. один пользователь может иметь много опций и одна опция может принадлежать многим пользователям, то это связь называется многие-ко-многим. Для того чтобы представить эту связь в БД нужна дополнительная таблица USER_OPTIONS c с полями USER_ID и OPTION_ID. Ниже представлен класс UserDTO, который отображается на таблицу USER.

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "USER") // таблица пользователей
public class UserDTO implements java.io.Serializable {
    private static final Long serialVersionUID = 1670764402691479710L;

    @Id
    @Column(name="ID")
    private Long id; // идентификатор

    @Column(name="NAME")
    private String name; // имя пользователя

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "USER_OPTIONS", 
        joinColumns = { @JoinColumn(name = "USER_ID") }, 
        inverseJoinColumns = { @JoinColumn(name = "OPTION_ID") })
    private Set<OptionDTO> options = new HashSet<OptionDTO>(0);

    public UserDTO() {
    }

    public UserDTO(Long id, String name, Set<OptionDTO> options) {
        this.id = id;
        this.name = name;
        this.options = options;
    }

    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;
    }

    public Set<OptionDTO> getOptions() {
        return options;
    }

    public void setOptions(Set<OptionDTO> options) {
        this.options = options;
    }
}

Далее показан класс OptionDTO, который обязательно должен включать в себя методы hashCode и equals. Это нужно т.к. OptionDTO будет у нас перечисляться.

import javax.persistence.*;

@Entity
@Table(name = "OPTION_TYPE") 
// OPTION_TYPE - название таблицы в которой хранится справочник опций
public class OptionDTO implements java.io.Serializable {
    private static final Long serialVersionUID = 1670764402695872711L;

    @Id
    @Column(name="ID")
    private Long id; // идентификатор

    @Column(name="NAME")
    private String name; // наименование опции

    public OptionDTO() {
    }

    public OptionDTO(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;
    }

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

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

Метод контроллера для вывода списка условно выглядит так:

model.addAttribute("userObject", userObject);
model.addAttribute("allOptionsList", allOptionsList);

Здесь userObject это экземпляр класса UserDTO, а optionList типа List<OptionDTO>.

А представление (view) выглядит примерно так:

<sf:form method="POST" id="frmEdit" modelAttribute="userObject">
    <fieldset>
        <form:checkboxes items="${allOptionsList}" itemLabel="name" 
            itemValue="id" path="options" element="div" />
    </fieldset>
</sf:form>

В переменной itemLabel указывается наименование поля которое будет заголовком каждого checkbox-a. В переменной path указывается куда запишется список после submit-a. А в переменной element указывается тег которым будет обрамлен каждый элемент списка. Во view мы передаем все доступные опции, а Spring MVC выберет сам те которые есть в userObject.options.