java Sping Boot 3和JPA with H2:无法提交JPA事务

8mmmxcuj  于 5个月前  发布在  Java
关注(0)|答案(2)|浏览(52)

我正在使用Sping Boot 3,Java 21 restful API和JPA with H2,我在处理事务方面遇到了问题。
我有3个控制器(用户,角色,角色)与基本的CRUD(获取,发布和删除)工作。
对于Colony控制器,我在使用post方法创建一个新的Colony时遇到了问题。错误消息是:
无法保存菌落,原因是:无法提交JPA事务
下面是关于Colony的详细信息。
ColonyController:

@RestController
@RequestMapping("/colonies")
public class ColonyController {
    ColonyService colonyService;

    public ColonyController(ColonyService colonyService) {
        this.colonyService = colonyService;
    }

    @PostMapping("")
    public Colony createColony(@RequestBody Colony colony) {
        return colonyService.createColony(colony);        
    }
}

字符串
殖民地服务:

public interface ColonyService {     
    public List<Colony> findAll();     
    public Colony createColony(Colony colony);     
    public Colony deleteById(String id);     
    public Colony findById(UUID id); 
}


殖民地服务实施

@Component
public class ColonyServiceImpl implements ColonyService{
    ColonyRepository colonyRepository;

    public ColonyServiceImpl(ColonyRepository colonyRepository) {
        this.colonyRepository = colonyRepository;
    }

    @Override
    public Colony createColony(Colony colony) {
        Colony newColony = null;
        try {
            colony.setAddresses(Collections.emptySet());
            newColony = colonyRepository.save(colony);
        } catch (Exception e) {
            throw new ColonyRepositoryException("Failed to save colony with reason: " + e.getMessage());
        }
        return newColony;
    }
   
}


菌落模型:

@Data
@NoArgsConstructor
@Entity
public class Colony extends Audit{
    
    @Id
    @GeneratedValue
    @UuidGenerator
    private UUID id;

    @OneToMany(mappedBy = "colony")
    private Set<Address> addresses;

    @NotEmpty
    private String name;

    @NotEmpty
    private boolean active = true;

    @PrePersist
    public void setCreatedAt() {
        this.setCreatedAt(LocalDateTime.now());
    }
}


地址型号:

@Data
@NoArgsConstructor
@Entity
public class Address extends Audit {

    @Id
    @GeneratedValue
    @UuidGenerator
    private UUID id;

    @OneToOne(mappedBy = "address", fetch = FetchType.LAZY)
    @JsonIgnore
    private User user;

    @ManyToOne()
    @JsonIgnore
    private Colony colony;

    @NotEmpty
    @Size(min = 3, max = 55)
    private String line1;

    private String line2;

    private String line3;

    @NotEmpty
    private String postalCode;

    @NotEmpty
    @Size(min = 2,max = 2)
    private String country; // (always required, 2 character ISO code)

    @NotEmpty
    private String state; // (ISO code when available)

    @NotEmpty
    private String city;  // (City)

    private String locality;  //(Neighborhood / Suburb)
    
    private String premise; // house / apt / building

    @NotNull
    private boolean active = true;

    @PrePersist
    public void setCreatedAt() {
        this.setCreatedAt(LocalDateTime.now());
    }
}


菌落储存库:

public interface ColonyRepository extends JpaRepository<Colony, UUID> {
}


我的 Postman 请求如下
postman request
我对请求的唯一标题是:
Accept: application/json
JSON响应和堆栈跟踪如下:

{
    "timestamp": "2024-01-02T00:27:36.124+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "trace": "com.toshi.rest.residencial.exceptions.ColonyRepositoryException: Failed to save colony with reason: Could not commit JPA transaction\n\tat com.toshi.rest.residencial.services.ColonyServiceImpl.createColony(ColonyServiceImpl.java:36)\n\tat com.toshi.rest.residencial.controllers.ColonyController.createColony(ColonyController.java:63)\n\tat java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:580)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:262)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:190)\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:917)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:829)\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\n\tat org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.base/java.lang.Thread.run(Thread.java:1583)\n",
    "message": "Failed to save colony with reason: Could not commit JPA transaction",
    "path": "/colonies"
}


我希望发生的事情:新的条目添加到H2菌落表。
发生了什么:500响应,错误消息:“无法提交JPA事务”
任何帮助或见解将不胜感激!
堆栈跟踪:

com.toshi.rest.residencial.exceptions.ColonyRepositoryException: Failed to save colony with reason: Could not commit JPA transaction
    at com.toshi.rest.residencial.services.ColonyServiceImpl.createColony(ColonyServiceImpl.java:36)
    at com.toshi.rest.residencial.controllers.ColonyController.createColony(ColonyController.java:63)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:262)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:190)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:917)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:829)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    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:1583)

vkc1a9a2

vkc1a9a21#

错误“Could not commit JPA transaction”通常表示Spring Data JPA应用程序中transaction的提交阶段存在问题。您可以看看以下几点:Database Constraint Violation:检查Colony实体的约束(例如,@NotEmpty、@Size等)。确保您尝试保存的数据符合这些约束。如果存在约束冲突,它可能导致交易失败。检查你的输入。

Nested Transactions:
    If you are using nested transactions, especially if you have multiple @Transactional methods being called within one another, ensure that you are handling transactions correctly. Nested transactions might not be supported or behave as expected in all scenarios.
check on call your making

Optimistic Locking:
    If you have fields annotated with @Version for optimistic locking in your entities, ensure that these fields are being updated correctly. Optimistic locking can cause transaction failures if the version doesn't match during an update.

Database Connection Issues:
    Check your H2 database connection. Ensure that the database is running and that your application can connect to it. Look for any additional error messages in the logs related to database connection issues.

Transaction Timeout:
    Check if there is a transaction timeout configured, and if the operation takes too long, it might result in a transaction failure. You can adjust the transaction timeout if needed.

Transactional Method Placement:
    Ensure that the @Transactional annotation is applied to the correct method. It should be on the method that initiates the transaction. In your case, it seems like createColony should be annotated with @Transactional.

Logging:
    Add more logging statements in your code to trace the flow of execution. This can help you identify the point where the transaction fails.

字符串
以下是ColonyServiceImpl的修订版本,其中包含额外的日志记录:

@Component
public class ColonyServiceImpl implements ColonyService {

    private final ColonyRepository colonyRepository;

    public ColonyServiceImpl(ColonyRepository colonyRepository) {
        this.colonyRepository = colonyRepository;
    }

    @Override
    @Transactional
    public Colony createColony(Colony colony) {
        try {
            colony.setAddresses(Collections.emptySet());
            Colony newColony = colonyRepository.save(colony);
            return newColony;
        } catch (Exception e) {
            // Log the exception for debugging purposes
            e.printStackTrace();
            throw new ColonyRepositoryException("Failed to save colony with reason: " + e.getMessage());
        }
    }
}


在这个版本中,我将@ transmittance注解添加到了异常Colony方法中。此外,我还使用e.printStackTrace()添加了一个log语句来打印异常的堆栈跟踪。这可以帮助您识别问题的根本原因。
请查看上面提到的几点,并根据日志和其他信息,您可能能够查明导致事务失败的问题。

epfja78i

epfja78i2#

Spring(包括Sping Boot )中的@ translation annotation用于定义单个数据库事务的范围。它可以在方法级别或类级别应用。

什么时候使用@ translation:

1.数据库操作:当您有多个数据库操作需要被视为一个工作单元时。例如,考虑一个场景,您需要在一个事务中保存或更新多个实体。
1.防止不一致状态:为了确保数据一致性,特别是当多个操作需要同时成功或失败时。如果事务中的任何操作失败,@ transmittance annotation有助于回滚所有更改,防止数据库中的状态不一致。
1.默认事务配置:当在类级别应用时,服务类上的@ translation表示该类中的所有公共方法都是translational。
在您的代码中,您尝试在数据库中执行操作,因此它要求您在服务层使用**@ translation**注解(您尝试使用Repository Instance保存它)。

@Override
    @Transactional
    public Colony createColony(Colony colony) {...}

字符串
如果答案有效,请接受。

相关问题