在JPA中,触发器在插入后返回的字段值与使用@Transactional和saveAndFlush()调用[duplicate]注解的方法不同步

gr8qqesn  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(241)

此问题在此处已有答案

Refresh and fetch an entity after save (JPA/Spring Data/Hibernate)(5个答案)
两个月前关门了。
触发器工作正常,在脚本中执行时会生成值。在执行使用@Transactional注解保存的方法后,触发器生成的值为空。在数据库中检查时,此字段具有值。在执行保存方法后,我尝试使用findById刷新记录,但该字段仍为空。奇怪的是,当我运行API来获取执行相同findById方法的记录时,它会显示值。
我有另一个表的类似代码,它工作得很完美。不同的是在触发器中调用的函数比这个执行得更快。
@Transactional是否执行提交?当带有@Transaction注解的方法执行完成时,提交是否也完成?那么为什么执行findById时数据库记录与实体记录不相同?
以下是可供参考的示例代码片段:

@Entity
@Table(name = "my_table")
@EntityListeners(AuditingEntityListener.class)
public class MyTableEntity implements Serializable {
...
@Id
@GeneratedValue(generator = "iDGenerator")
@Column(name="column1", nullable=false, updatable=false)
private Long column1;

@Column(name="column2", length=5, nullable=false, updatable=false)
private String column2;

@Column(name="column3", length=10)
private String column3;

@Column(name="column4", insertable=false, updatable=false)
private Long column4;

@Column(name="cre_userid", length=30, nullable=false, updatable=false)
@CreatedBy
private String createdBy;

@Column(name="cre_date", nullable=false, updatable=false)
@CreatedDate
private LocalDateTime dateCreated;
...

它的数据表有一个触发程序,会设定column 4的值,如下所示:

CREATE OR REPLACE TRIGGER MY_TABLE_BIUFER 
BEFORE INSERT ON MY_TABLE
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
  :new.column4 := workflow_pkg.create_workflow (:new.column1);
END;

控制器和服务代码片段如下所示:

@Service
public class MyServiceImpl implements MyService{

    @Autowired
    MyTableRepository myTableRepo;

    @Override
    public MyTableDto getRecord(Long pk) {
        MyTableDto returnValue;
        MyTableEntity myTableEntity = myTableRepo.findById(pk)
                                                 .orElseThrow(() -> new IIBSException("Transaction Id " + pk + " not found. Process Terminated."));
        myTableDto = convertToDto(myTableEntity); //use ModelMapper to convert entity to dto
        return returnValue;
    }

    @Override
    @Transactional
    public Long saveRecord(MyTableDto myTableDto) {
        MyTableEntity myTableEntity, storedDetails;
        Long returnValue;

        myTableEntity = convertToEntity(myTableDto); //use ModelMapper to convert dto to entity
        storedDetails = myTableRepo.saveAndFlush(myTableEntity);

        returnValue = storedDetails.getQuotApplTransNo();
        return returnValue;                 
    }
}


@RestController
@RequestMapping
public class MyController {

    @Autowired
    MyService myService;

    @GetMapping(path="/{pk}")
    public MyTableDto getRecord (@PathVariable Long pk) throws MyException {        
        if (pk == null) throw new MyException(ErrorMessage.MISSING_PARAMETER.getErrorMessage());
        
        MyTableDto returnValue = myService.getRecord(pk);   
        return returnValue;
    }

    @PostMapping
    public MyTableDto saveRecord (@RequestBody MyTableDto myTableDto) throws MyException
    {       
        //.. validations .. //

        Long pk = myService.saveRecord(myTableDto); 
        if (pk == null) throw new MyException("Error in saving Request for Quotation Package");

        MyTableDto returnValue = myService.getRecord(pk);   
        return returnValue;
    }
}
vcirk6k6

vcirk6k61#

保存时,数据库表中的值不会同步回实体。
如果需要这些值,必须在保存后调用EntityManager.refresh()
JpaRepository上没有刷新,因此必须将EntityManager注入到服务中。

相关问题