I am asking for a hint. I searched the internet for a long time for a solution to the problem, but I'm already desperate. I would like the update operation to update a record in the table instead of writing a new one. Sorry for my code i am a beginner.
It is my code:
@Entity
public class Job {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotEmpty(message = "You must enter the title.")
@Size(min=2, max = 30, message = "You must add a description with length beetwen 2 and 30 letters.")
@Column(name = "title")
private String title;
@NotEmpty(message = "You must enter the description.")
@Size(min=10, max = 150, message = "You must add a description with length beetwen 10 and 150 letters.")
@Column(name = "description")
private String description;
@NotEmpty(message = "You must select profession")
@Column(name = "profession")
private String profession;
@NotEmpty(message = "You must select status")
@Column(name = "status")
private String status;
@NotEmpty(message = "You must select location")
@Column(name = "location")
private String location;
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "publishDate")
private Date publishDate;
- getters setters and constructors
service layer:
@Service
public class JobServiceImpl implements JobService {
@Autowired
private JobRepository repository;
@Override
public Job saveJob(Job job) {
return repository.save(job);
}
@Override
public Job getJobById(Long id) throws JobNotFoundException {
Optional<Job> optional = repository.findById(id);
if (optional.isPresent()) {
return optional.get();
} else {
throw new JobNotFoundException("Job with id: " id " not found ");
}
}
@Override
public void deleteJobById(Long id) throws JobNotFoundException {
repository.delete(getJobById(id));
}
@Override
public void updateJob(Job job) {
repository.save(job);
}
controller methods :
@GetMapping("/edit")
public String getEditPage(Model model, RedirectAttributes attributes, @RequestParam Long id) {
String page = null;
initModel(model);
try {
Job job = service.getJobById(id);
model.addAttribute("job", job);
page = "editJobPage";
} catch (JobNotFoundException e) {
e.printStackTrace();
attributes.addAttribute("message", e.getMessage());
page = "redirect:getAllJobs";
}
return page;
}
@PostMapping("/edit")
public String updateJob(@ModelAttribute Job job, Model model, RedirectAttributes attributes) {
initModel(model);
service.updateJob(job);
Long id = job.getId();
attributes.addAttribute("message", "Job advertisement with id: '" id "' is updated successfully !");
return "redirect:getAllJobs";
}
and view layer:
<html xmlns:th="https://www.thymeleaf.org">
<head>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" />
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" />
</head>
<body>
<div >
<div >
<div >
<div >
<h3>Edit advertisement</h3>
</div>
<div >
<form action="/job/edit" th:action="@{/job/edit}" th:object="${job}"
method="POST" id="editJobPage">
<div >
<div >
<label for="title"><b>Title</b></label>
</div>
<div >
<input type="text"
name="title" th:field="*{title}"><br />
</div>
</div>
<br />
<div >
<div >
<label for="location"><b>Location</b></label>
</div>
<select id="location" name="location">
<option value="" disabled selected>Select location</option>
<option th:each="location : ${locationsList}"
th:text="${location}" />
</select>
</div>
<br />
<div >
<div >
<label for="description"><b>Description</b></label>
</div>
<div >
<textarea rows="3"
name="description"
th:field="*{description}"></textarea>
<br />
</div>
</div>
<br />
<div >
<div >
<label for="profession"><b>Profession</b></label>
</div>
<select name="profession">
<option value="" disabled selected>Select profession</option>
<option th:each="profession : ${professionsList}"
th:text="${profession}" />
</select>
</div>
<br />
<div >
<div >
<label for="status"><b>Status</b></label>
</div>
<select name="status">
<option value="" disabled selected>Select status</option>
<option th:each="status : ${statusList}" th:text="${status}" />
</select>
</div>
<br />
<button type="submit" >
Update Advertisement <i
aria-hidden="true"></i>
</button>
</form>
</div>
<div th:if="${message!=null}" >
<span th:text="${message}"></span>
</div>
</div>
</div>
</div>
</body>
</html>
CodePudding user response:
The reason you're seeing this is because your persistence provider (presumably hibernate) doesn't know which version you want to update, so it treats it as a new object.
To your model, simply add
@Version
private Long version;
and what you have there should work. The version will be a part of the object now and when your request to update comes back in, provided the version field is populated, hibernate will know which row it needs to update.
Also, you'll need to add the id and version to your view layer (they can be hidden fields), they will look like this in your view
<input type="hidden" name="id" th:field="*{id}">
<input type="hidden" name="version" th:field="*{version}">
CodePudding user response:
One way to do this is by first fetching the job from the repository and then applying the necessary changes to it before saving (updating) it to the database.
@Override
public void updateJob(Job job) {
Job dbJob = getJobById(job.getId());
if(dbJob != null){
dbJob.setStatus(job.getStatus());
...set the other fields
repository.save(dbJob);//this updates an existing job record
}else{
repository.save(job);//this inserts a new job
}
}