Home > Net >  Thymeleaf spring save new object instead of update
Thymeleaf spring save new object instead of update

Time:05-07

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 
    }
   
}
  • Related