即使在两者之间发生错误,休眠也会自动更新我的实体

Posted

技术标签:

【中文标题】即使在两者之间发生错误,休眠也会自动更新我的实体【英文标题】:Hibernate is auto updating my entity, even if error occurred in between 【发布时间】:2022-01-01 15:25:18 【问题描述】:

我有一个名为“程序”的实体。我正在对这个实体进行一些操作。但我不知道如何或为什么,即使我遇到异常,我的实体也会更新。所以谁能帮我解决这个问题。

控制器

@GetMapping("/testtransaction/tid")
public ApiResponse testTransaction(@PathVariable("tid") String tid)
     return gsService.testTransaction(tid);

服务

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
public ApiResponse testTransaction(String tid) 
    ApiResponse apiResponse = new ApiResponse();
    try 
        Optional<Program> existProgram = programRepository.findById(tid);
        if(existProgram.isPresent()) 
            //For testing I am setting random value
            existProgram.get().setProgramName("tid_"+(Math.floor(Math.random() * 90 + 10)));
                
            try 
                int err = 8/0;
            catch(Exception e) 
                throw new EntityNotFoundException(Program.class, "prog cd", tid);
            
                    
            programRepository.save(existProgram.get());
            apiResponse.setData("Success");
        else 
            apiResponse.setError("Program details not found for "+tid);
            apiResponse.setStatusCode(500);
        
    catch(Exception e) 
        apiResponse.setError("Something went wrong while testing.");
        apiResponse.setStatusCode(500);
        return apiResponse;
    
    return apiResponse;

实体

package com.edudb.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Size;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
@JsonInclude(value=Include.NON_NULL)
@Table(name = "PROGRAM_MASTER")
public class Program 
    @Id
    @Column(name = "PROGRAM_CD")
    private String programCd;
    
    @Column(name = "PROGRAM_NAME")
    @Size(min=1, max=100, message = "Minimum 1 & maximum 100 characters only")
    private String programName;
    
    @Column(name="ENT_BY")
    @Size(min=1, max=12, message = "Minimum 1 & maximum 12 characters only")
    private String entBy;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="dd MMM yyyy")  
    @Column(name = "ENT_DT")
    @Temporal(TemporalType.DATE)
    private Date entDt;
    
    @Column(name="DEL_BY")
    @Size(min=1, max=12, message = "Minimum 1 & maximum 12 characters only")
    private String delBy;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="dd MMM yyyy")  
    @Column(name = "DEL_DT")
    @Temporal(TemporalType.DATE)
    private Date delDt;
    
    @Column(name="LAST_UPDT_BY")
    @Size(min=1, max=12, message = "Minimum 1 & maximum 12 characters only")
    private String updtBy;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="dd MMM yyyy")  
    @Column(name = "LAST_UPDT_DT")
    @Temporal(TemporalType.DATE)
    private Date updtDt;

在邮递员中回复我收到的内容


    "statusCode": 500,
    "error": "Something went wrong while testing."

春季开机日志

2021-11-23 10:34:20 DEBUG --- origin:null
 : com.datanet.filter.SimpleCorsFilter     2021-11-23 10:34:20 DEBUG --- 
    select
        program0_.program_cd as program_cd1_83_0_,
        program0_.del_by as del_by2_83_0_,
        program0_.del_dt as del_dt3_83_0_,
        program0_.ent_by as ent_by4_83_0_,
        program0_.ent_dt as ent_dt5_83_0_,
        program0_.program_name as program_name6_83_0_,
        program0_.last_updt_by as last_updt_by7_83_0_,
        program0_.last_updt_dt as last_updt_dt8_83_0_ 
    from
        program_master program0_ 
    where
        program0_.program_cd=?
 : org.hibernate.SQL                       2021-11-23 10:34:20 TRACE --- binding parameter [1] as [VARCHAR] - [demo]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 DEBUG --- 
    update
        program_master 
    set
        del_by=?,
        del_dt=?,
        ent_by=?,
        ent_dt=?,
        program_name=?,
        last_updt_by=?,
        last_updt_dt=? 
    where
        program_cd=?
 : org.hibernate.SQL                       2021-11-23 10:34:20 TRACE --- binding parameter [1] as [VARCHAR] - [john]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [2] as [DATE] - [2021-10-06]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [3] as [VARCHAR] - [peter]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [4] as [DATE] - [2021-10-06]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [5] as [VARCHAR] - [tid_52.0]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [6] as [VARCHAR] - [john]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [7] as [DATE] - [2021-10-06]
 : ibernate.type.descriptor.sql.BasicBinder2021-11-23 10:34:20 TRACE --- binding parameter [8] as [VARCHAR] - [demo]
 : ibernate.type.descriptor.sql.BasicBinder

所以如果有人以前遇到过这个问题,请帮我解决这个问题:(

【问题讨论】:

你能不能在你的ide里面显示stack trace 您的代码错误。从来没有例外......至少对于您正在捕获所有内容的事务,事务永远不会看到它并且只会提交。所以基本上你让@Transactional 你没用了。您应该让异常冒泡,以便事务拦截器可以相应地采取行动。 @FaeemazazBhanej 我已经将 IDE 的堆栈跟踪添加为“Spring boot log” @M.Deinum 我的代码是正确的。问题是,如果我在异常之前使用Entiry data 更改任何内容,那么只有我面临这个问题。否则我的代码工作得很好。注意:如果我在异常之前更新实体,休眠本身会触发更新查询。 去掉@Transactional里面的try-catch,使用全局异常处理器处理异常 【参考方案1】:

通过在 catch 或 finally 或函数末尾添加以下代码行,休眠回滚整个事务。

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

【讨论】:

以上是关于即使在两者之间发生错误,休眠也会自动更新我的实体的主要内容,如果未能解决你的问题,请参考以下文章

休眠实体不删除关系

为啥即使存在列,我也会有 ORA-00904?

即使驱动程序类名和休眠方言的值错误,Spring Hibernate 集成示例也会执行

即使实体中包含名称获取器,也会烘焙错误的表 displayField

即使有事务回滚,SQL 标识(自动编号)也会增加

即使在我指定了自定义 VPC 之后,我的用于自动缩放组的 Cloudformation YAML 也会继续在默认 VPC 中创建 EC2 实例