К примеру у нас есть сущность Пользователь, которая в БД представлена таблицей 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.