Thymeleaf + spring 保存新对象而不是更新
Thymeleaf + spring save new object instead of update
我正在寻求提示。我在互联网上搜索了很长时间以解决问题,但我已经绝望了。我希望更新操作更新 table 中的记录,而不是写入新记录。对不起我的代码,我是初学者。
这是我的代码:
@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;
- getter、setter 和构造函数
服务层:
@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);
}
控制器方法:
@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";
}
和视图层:
<html xmlns:th="https://www.thymeleaf.org">
<head>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" />
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/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 class="col-md-12">
<div class="container">
<div class="card">
<div class="card-header text-center text-black">
<h3>Edit advertisement</h3>
</div>
<div class="card-body">
<form action="/job/edit" th:action="@{/job/edit}" th:object="${job}"
method="POST" id="editJobPage">
<div class="row">
<div class="col-2">
<label for="title"><b>Title</b></label>
</div>
<div class="col-6">
<input type="text" class="form-control"
name="title" th:field="*{title}"><br />
</div>
</div>
<br />
<div class="row">
<div class="col-2">
<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 class="row">
<div class="col-2">
<label for="description"><b>Description</b></label>
</div>
<div class="col-6">
<textarea class="form-control" rows="3"
name="description"
th:field="*{description}"></textarea>
<br />
</div>
</div>
<br />
<div class="row">
<div class="col-2">
<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 class="row">
<div class="col-2">
<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" class="btn btn-success">
Update Advertisement <i class="fa fa-plus-square"
aria-hidden="true"></i>
</button>
</form>
</div>
<div th:if="${message!=null}" class="card-footer bg-white text-info">
<span th:text="${message}"></span>
</div>
</div>
</div>
</div>
</body>
</html>
新错误:
2022-05-07 15:51:48.027 DEBUG 29284 --- [nio-8080-exec-7] org.hibernate.SQL : select job0_.id as id1_0_0_, job0_.description as descript2_0_0_, job0_.location as location3_0_0_, job0_.profession as professi4_0_0_, job0_.publish_date as publish_5_0_0_, job0_.status as status6_0_0_, job0_.title as title7_0_0_ from job job0_ where job0_.id=?
2022-05-07 15:51:48.027 TRACE 29284 --- [nio-8080-exec-7] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [0]
com.example.job.advertisements.web.app.exceptionHandler.JobNotFoundException: Job with id: 0 not found
at com.example.job.advertisements.web.app.service.JobServiceImpl.getJobById(JobServiceImpl.java:39)
at com.example.job.advertisements.web.app.service.JobServiceImpl.updateJob(JobServiceImpl.java:53)
at com.example.job.advertisements.web.app.controller.JobController.updateJob(JobController.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.servlet.resource.ResourceUrlEncodingFilter.doFilter(ResourceUrlEncodingFilter.java:67)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829)
2022-05-07 15:51:48.049 DEBUG 29284 --- [nio-8080-exec-8] org.hibernate.SQL : select job0_.id as id1_0_, job0_.description as descript2_0_, job0_.location as location3_0_, job0_.profession as professi4_0_, job0_.publish_date as publish_5_0_, job0_.status as status6_0_, job0_.title as title7_0_ from job job0_
2022-05-07 15:51:48.050 TRACE 29284 --- [nio-8080-exec-8] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_0_] : [BIGINT]) - [1]
您看到这种情况的原因是因为您的持久性提供程序(大概是休眠)不知道您要更新哪个版本,所以它将它视为一个新对象。
在您的模型中,只需添加
@Version
private Long version;
你那里的东西应该有用。该版本现在将成为对象的一部分,当您的更新请求返回时,如果填充了版本字段,hibernate 将知道它需要更新哪一行。
此外,您还需要将 id 和版本添加到您的视图层(它们可以是隐藏字段),它们在您的视图中将如下所示
<input type="hidden" name="id" th:field="*{id}">
<input type="hidden" name="version" th:field="*{version}">
一种方法是首先从存储库中获取与您的作业参数匹配的作业,然后在将其保存(更新)到数据库之前对其应用必要的更改。
@Override
public void updateJob(Job job) {
//I assume job.getId() returns an integer here, otherwise use another field that uniquely identifies a job
Job dbJob = getJobById(job.getId());
if(dbJob != null){
dbJob.setStatus(job.getStatus());
dbJob.setTitle(job.getTitle());
//set all the other fields except id
repository.save(dbJob);//this updates an existing job record
}else{
repository.save(job);//this inserts a new job
}
}
更新:该错误是由您的方法 getJobById 引发的。当然,您可以更改该方法,以便每当在存储库中找不到记录时它 returns null(而不是像您现在所做的那样抛出异常)。请注意,本例中的作业 ID 为 0,并且存储库中不存在具有该 ID (0) 的记录。如果要更新记录,则必须提供数据库中已存在的唯一 ID(无论是 ID 还是其他)。我猜你没有将 Job.id 显式设置为 0,而是将 id 初始化为其默认值,即 0.
我正在寻求提示。我在互联网上搜索了很长时间以解决问题,但我已经绝望了。我希望更新操作更新 table 中的记录,而不是写入新记录。对不起我的代码,我是初学者。
这是我的代码:
@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;
- getter、setter 和构造函数
服务层:
@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);
}
控制器方法:
@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";
}
和视图层:
<html xmlns:th="https://www.thymeleaf.org">
<head>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" />
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/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 class="col-md-12">
<div class="container">
<div class="card">
<div class="card-header text-center text-black">
<h3>Edit advertisement</h3>
</div>
<div class="card-body">
<form action="/job/edit" th:action="@{/job/edit}" th:object="${job}"
method="POST" id="editJobPage">
<div class="row">
<div class="col-2">
<label for="title"><b>Title</b></label>
</div>
<div class="col-6">
<input type="text" class="form-control"
name="title" th:field="*{title}"><br />
</div>
</div>
<br />
<div class="row">
<div class="col-2">
<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 class="row">
<div class="col-2">
<label for="description"><b>Description</b></label>
</div>
<div class="col-6">
<textarea class="form-control" rows="3"
name="description"
th:field="*{description}"></textarea>
<br />
</div>
</div>
<br />
<div class="row">
<div class="col-2">
<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 class="row">
<div class="col-2">
<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" class="btn btn-success">
Update Advertisement <i class="fa fa-plus-square"
aria-hidden="true"></i>
</button>
</form>
</div>
<div th:if="${message!=null}" class="card-footer bg-white text-info">
<span th:text="${message}"></span>
</div>
</div>
</div>
</div>
</body>
</html>
新错误:
2022-05-07 15:51:48.027 DEBUG 29284 --- [nio-8080-exec-7] org.hibernate.SQL : select job0_.id as id1_0_0_, job0_.description as descript2_0_0_, job0_.location as location3_0_0_, job0_.profession as professi4_0_0_, job0_.publish_date as publish_5_0_0_, job0_.status as status6_0_0_, job0_.title as title7_0_0_ from job job0_ where job0_.id=?
2022-05-07 15:51:48.027 TRACE 29284 --- [nio-8080-exec-7] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [0]
com.example.job.advertisements.web.app.exceptionHandler.JobNotFoundException: Job with id: 0 not found
at com.example.job.advertisements.web.app.service.JobServiceImpl.getJobById(JobServiceImpl.java:39)
at com.example.job.advertisements.web.app.service.JobServiceImpl.updateJob(JobServiceImpl.java:53)
at com.example.job.advertisements.web.app.controller.JobController.updateJob(JobController.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.servlet.resource.ResourceUrlEncodingFilter.doFilter(ResourceUrlEncodingFilter.java:67)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829)
2022-05-07 15:51:48.049 DEBUG 29284 --- [nio-8080-exec-8] org.hibernate.SQL : select job0_.id as id1_0_, job0_.description as descript2_0_, job0_.location as location3_0_, job0_.profession as professi4_0_, job0_.publish_date as publish_5_0_, job0_.status as status6_0_, job0_.title as title7_0_ from job job0_
2022-05-07 15:51:48.050 TRACE 29284 --- [nio-8080-exec-8] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_0_] : [BIGINT]) - [1]
您看到这种情况的原因是因为您的持久性提供程序(大概是休眠)不知道您要更新哪个版本,所以它将它视为一个新对象。
在您的模型中,只需添加
@Version
private Long version;
你那里的东西应该有用。该版本现在将成为对象的一部分,当您的更新请求返回时,如果填充了版本字段,hibernate 将知道它需要更新哪一行。
此外,您还需要将 id 和版本添加到您的视图层(它们可以是隐藏字段),它们在您的视图中将如下所示
<input type="hidden" name="id" th:field="*{id}">
<input type="hidden" name="version" th:field="*{version}">
一种方法是首先从存储库中获取与您的作业参数匹配的作业,然后在将其保存(更新)到数据库之前对其应用必要的更改。
@Override
public void updateJob(Job job) {
//I assume job.getId() returns an integer here, otherwise use another field that uniquely identifies a job
Job dbJob = getJobById(job.getId());
if(dbJob != null){
dbJob.setStatus(job.getStatus());
dbJob.setTitle(job.getTitle());
//set all the other fields except id
repository.save(dbJob);//this updates an existing job record
}else{
repository.save(job);//this inserts a new job
}
}
更新:该错误是由您的方法 getJobById 引发的。当然,您可以更改该方法,以便每当在存储库中找不到记录时它 returns null(而不是像您现在所做的那样抛出异常)。请注意,本例中的作业 ID 为 0,并且存储库中不存在具有该 ID (0) 的记录。如果要更新记录,则必须提供数据库中已存在的唯一 ID(无论是 ID 还是其他)。我猜你没有将 Job.id 显式设置为 0,而是将 id 初始化为其默认值,即 0.