The relationship between classes is 1:N. In Thymeleaf, I created a split form object to submit form data. But when I press send, it sends, but I don't see any data on the screen.
Professor.class
@Entity
@Getter
@Setter
@Table(name = "professor")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "userid", "position", "sal", "hiredate"})
public class Professor {
@Id @GeneratedValue
@Column(name = "profno", nullable = false)
private Long id;
@Column(name = "name", nullable = false, length = 50)
private String username;
@Column(nullable = false, length = 50)
private String userid;
@Column(nullable = false, length = 20)
private String position;
private int sal;
private String hiredate;
private int comm;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "deptno")
private Department department;
@OneToMany(mappedBy = "professor")
private List<Student> students = new ArrayList<>();
public Professor(String username) {
this.username = username;
}
public Professor(String username, String position) {
this.username = username;
this.position = position;
}
public Professor(String username, String position, int sal, String hiredate, int comm, String userid, Department department) {
this.username = username;
this.hiredate = hiredate;
this.userid = userid;
this.sal = sal;
this.comm = comm;
this.position = position;
if (department != null) {
setDepartment(department);
}
}
// ===== Method ===== //
public void setDepartment(Department department) {
this.department = department;
department.getProfessors().add(this);
}
Department.class
@Entity
@Getter
@Setter
@Table(name = "department")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name", "loc"})
public class Department {
@Id @GeneratedValue
@Column(name = "deptno", nullable = false)
private Long id;
@Column(name = "dname", length = 100)
private String name;
@Column(length = 100)
private String loc;
@OneToMany(mappedBy = "department")
private List<Professor> professors = new ArrayList<>();
@OneToMany(mappedBy = "department")
private List<Student> students = new ArrayList<>();
public Department(String name) {
this.name = name;
}
public Department(String name, String loc) {
this.name = name;
this.loc = loc;
}
}
ProfessorForm.class
@Getter
@Setter
public class ProfessorForm {
private Long id;
@NotEmpty()
private String username;
private String userid;
private String position;
private String hiredate;
private int sal;
private int comm;
private Department department;
}
Controller.class
Professor professor = new Professor(form.getUsername(), form.getUserid(),
form.getComm(), form.getHiredate(), form.getSal(), form.getPosition(), form.getDepartment());
Thymeleaf
<form th:action="@{/professor/add}" th:object="${professorForm}" method="post">
<div class="form-group">
<label th:for="username">name</label>
<input type="text" th:field="*{username}" class="form-control" placeholder="">
</div>
<div class="form-group">
<label th:for="userid">id</label>
<input type="text" th:field="*{userid}" class="form-control" placeholder="">
</div>
<div class="form-group">
<label th:for="position">position</label>
<input type="text" th:field="*{position}" class="form-control" placeholder="">
</div>
<div class="form-group">
<label th:for="sal">sal</label>
<input type="number" th:field="*{sal}" class="form-control" placeholder="">
</div>
<div class="form-group">
<label th:for="hiredate">hiredate</label>
<input type="date" th:field="*{hiredate}" class="form-control" placeholder="">
</div>
<div class="form-group">
<label th:for="comm">comm</label>
<input type="range" th:field="*{comm}" class="form-control" min="0" max="100" value="0" placeholder="">
</div>
<div class="form-group">
<label th:for="departmentId">loc</label>
<input type="text" th:field="*{department.loc}" class="form-control" placeholder="">
</div>
At the end, it is confirmed that department.loc is the problem. How should we deal with this?
I assume you want to user of the HTML form to select a certain department for the to-be-created professor entity. The easiest way to support this is adding a HTML select that shows all possible departments, allowing the user to select one.
To make this possible with Thymeleaf, you need the following:
ProfessorForm
to use the primary key of the entity that should be referenced (Department
in this case, so use long
):public class ProfessorForm {
// instead of: private Department department;
private long departmentId;
}
@GetMapping
controller method, return all department names and id's. This is needed to fill up the HTML selectList<DepartmentNameAndId> departments = ...
model.addAttribute( "departments", departments);
<select th:field="*{departmentId}">
<option th:each="department : ${departments}"
th:text="${department.name}"
th:value="${department.id}">
</select>
@PostMapping
in the controller, use the departmentId
to get the corresponding Department
object and use that to create the Professor
object.See Using HTML select options with Thymeleaf for some more details.