I am creating a Spring Boot application with thymeleaf where I have an relationship Many-to-One between a table named figures and a table named states (many figures to one state). Everything is OK when creating a state. The problem is with creating a figure. These are the classes:
@Entity
@Table(name = "state")
public class State implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_state")
private Integer idState;
@Column(name = "official_state_name")
private String officialStateName;
@Column(name = "official_language")
private String officialLanguage;
@Column(name = "state_currency")
private String stateCurrency;
//setters and getters
@Entity
@Table(name = "figure")
public class Figure implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_figure")
private Long idFigure;
@Column(name = "pib")
private String fullName;
@Column(name = "date_of_birth")
private java.sql.Date dateOfBirth;
@Column(name = "date_of_death", nullable = true)
private java.sql.Date dateOfDeath;
@Column(name = "kind_of_activity")
private String kindOfActivity;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "id_state", nullable = false)
private State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public Long getIdFigure() {
return this.idFigure;
}
public void setIdFigure(Long idFigure) {
this.idFigure = idFigure;
}
public String getFullName() {
return this.fullName;
}
public void setFullName(String pib) {
this.fullName = fullName;
}
public java.sql.Date getDateOfBirth() {
return this.dateOfBirth;
}
public void setDateOfBirth(java.sql.Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public java.sql.Date getDateOfDeath() {
return this.dateOfDeath;
}
public void setDateOfDeath(java.sql.Date dateOfDeath) {
this.dateOfDeath = dateOfDeath;
}
public String getKindOfActivity() {
return this.kindOfActivity;
}
public void setKindOfActivity(String kindOfActivity) {
this.kindOfActivity = kindOfActivity;
}
}
Now this is the controller for the Figure class:
@Controller
public class FigureController {
@Autowired
FigureService figureService;
@Autowired
FigureRepository figureRepository;
@Autowired
StateRepository stateRepository;
@Autowired
StateService stateService;
@GetMapping("/figures")
public String showAllFigures(Model model){
List<Figure> listFigures = figureService.findAllFigures();
model.addAttribute("listFigures", listFigures);
return "figures";
}
@GetMapping("/figures/new")
public String showNewFigureForm(Model model){
List <State> listStates = stateService.findAll();
model.addAttribute("listStates", listStates);
model.addAttribute("figure", new Figure());
model.addAttribute("pageTitleF", "Add New Figure");
return "figure_form";
}
@PostMapping("/figures/save")
public String saveFigure (Figure requestFigure, RedirectAttributes redirectAttributes) throws StateNotFoundException {
figureRepository.save(requestFigure);
redirectAttributes.addFlashAttribute("messageF", "The figure has been saved successfully!");
return "redirect:/figures";
}
@GetMapping("/figures/edit/{id}")
public String showEditFigureForm(@PathVariable("id") Integer id, Model model, RedirectAttributes redirectAttributes){
try {
Figure figure = figureService.findFigureById(id);
List <State> listStates = stateService.findAll();
model.addAttribute("listStates", listStates);
model.addAttribute("figure", figure);
model.addAttribute("pageTitleF", "Edit Figure (ID: " id ")");
return "figure_form";
} catch (EntityNotFoundException e) {
redirectAttributes.addFlashAttribute("messageF", e.getMessage());
return "redirect:/figures";
}
}
@GetMapping("/figures/delete/{id}")
public String deleteFigure(@PathVariable("id") Integer id, Model model, RedirectAttributes redirectAttributes){
try {
figureService.deleteFigure(id);
redirectAttributes.addFlashAttribute("messageF", "The figure ID " id " has been deleted!");
} catch (StateNotFoundException e) {
redirectAttributes.addFlashAttribute("messageF", e.getMessage());
}
return "redirect:/figures";
}
}
So I need to pass an id of state from drop-down list of states and assign it to the foreign key of the figure entity. These are the html files. figures.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Welcome to My Application</title>
<link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"/>
</head>
<body>
<div >
<div><h2>Manage Figures</h2></div>
<div >
<a th:href="@{/figures/new}">Add New Figure</a>
</div>
<div >
<a th:href="@{http://localhost:8080/}">Back to Main Menu</a>
</div>
<div th:if="${messageF}" >
[[${messageF}]]
</div>
<div>
<table >
<thead >
<tr>
<th>ID</th>
<th>Full Name</th>
<th>Date of Birth</th>
<th>Date of Death</th>
<th>kindOfActivity</th>
<th></th>
</tr>
</thead>
<tbody>
<th:block th:each="figure : ${listFigures}">
<tr>
<td>[[${figure.fullName}]]</td>
<td>[[${figure.dateOfBirth}]]</td>
<td>[[${figure.dateOfDeath}]]</td>
<td>[[${figure.kindOfActivity}]]</td>
<td>
<a th:href="@{'/figures/edit/' ${figure.idFigure}}">Edit</a>
<a th:href="@{'/figures/delete/' ${figure.idFigure}}">Delete</a>
</td>
</tr>
</th:block>
</tbody>
</table>
</div>
</div>
</body>
</html>
figure_form.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>[[${pageTitleF}]]</title>
<link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"/>
</head>
<body>
<div >
<div ><h2>[[${pageTitleF}]]</h2></div>
<form th:action="@{/figures/save}" method="post" th:object="${figure}"
style="max-width: 500px; margin: 0 auto;">
<input type="hidden" th:field="*{idFigure}">
<div >
<div >
<label >Full Name</label>
<div >
<input type="text" th:field="*{fullName}" required minlength="4" maxlength="40"/>
</div>
</div>
<div >
<label >Date of Birth</label>
<div >
<input type="date" th:field="*{dateOfBirth}" />
</div>
</div>
<div >
<label >Date of Death</label>
<div >
<input type="date" th:field="*{dateOfDeath}" />
</div>
</div>
<div >
<label >Kind of Activity</label>
<div >
<input type="text" th:field="*{kindOfActivity}" required maxlength="60"/>
</div>
</div>
<div >
<label >State</label>
<div >
<select id="idState" name="idState">
<option value="">Select State</option>
<option th:each="state : ${listStates}"
th:value="${state.idState}"
th:text="${state.idState} ' : ' ${state.officialStateName}"></option>
</select>
</div>
</div>
<div >
<button type="submit" >Save</button>
<button type="button" onclick="cancelForm()">Cancel</button>
</div>
</div>
</form>
</div>
<script type="text/javascript">
function cancelForm(){
window.location = "[[@{/figures}]]"
}
</script>
</body>
</html>
When I hit the save button I get an error status 500:
And the error description
org.hibernate.PropertyValueException: not-null property references a null or transient value : com.historicalreferencebook.historicalreferencebook.domain.Figure.state
As you can see even though I chose a state and therefore its key is assigned to the foreign key of the figure entity, it is null. Why? And what should I do to pass the value from the drop down list to the foreign key of the figure? Any help is appreciated! Thanks in advance!
CodePudding user response:
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "id_state", nullable = false)
private State state;
change to:
@ManyToOne(fetch = FetchType.LAZY,
optional = false,
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "id_state", nullable = false)
private State state;
CodePudding user response:
I got it sovled dropping a table and then creating it once again with maven installation, i changed id data type to Integer and used this as a drop down list (because there is a "th:field" which tells the spring which field will be filled with value from a drop down list):
<div >
<label >State</label>
<div >
<select th:field="*{state}" required>
<th:block th:each="state : ${listStates}">
<option th:text="${state.officialStateName}" th:value="${state.idState}"/>
</th:block>
</select>
</div>
</div>