Hibernate在SpringBoot中不能在同一个事务中持久化所有实体。

huangapple go评论81阅读模式
英文:

Hibernate in SpringBoot does not persist all Entities in same transaction

问题

我使用的是Hibernate版本5.4.22.Final,SpringBoot版本为2.3.5.RELEASE,并且使用以下代码:

控制器(CONTROLLER):

@PostMapping("/insert/{id}")
public MyReposneEntitiy insertAutoAndSendNotification(@PathVariable("id") int id, @Valid @RequestBody Auto auto)  {
    MyReposneEntitiy e = service.insertAuto(auto, id);
    service.sendNotification(id);
    return e;
}

服务(SERVICE):

@Transactional
public MyReposneEntitiy insertAuto(Auto auto, int id) {

    InfoForAuto info = infoRepo.findById(id).get();
    entityManager.detach(info);
    // 这个字段用@Version注解标记,
    // 如果实体在持久化上下文中,它不能被更改
    // 这就是为什么我首先要将其分离,然后再保存
    info.setVersion(auto.getVersion());
    infoRepo.save(info);

    Person person = personService.createPerson(auto.getPerson());
    Eng eng = engService.createEng(auto.getEng(), person.getId());

    info.setMSDNumber(auto.getMSDNumber());
    info.setStatus(Constants.OK);

    MyReposneEntitiy response = new MyReposneEntitiy ();
    response.setStatus(Constants.OK);
    return response;
}

public void sendNotification(int id){
    // 一些代码...
}

被调用的服务方法(CALLED SERVICE METHOD):

@Transactional
public PersonResponse createPerson(PersonInput pesronInput) {...}

@Transactional
public EngResponse createEng(EngInput engInput, Integer personId) {...}

现在的问题是,当insertAuto()方法结束并且我处于sendNotification()方法的第一行(在调试模式下),我检查数据库发现,“person”和“eng”已经在数据库中创建,但“info”实体没有被更新。但我需要在调用sendNotification方法之前更新它,我无法弄清楚为什么?它们不都在同一个事务中吗?Hibernate应该要么保存所有实体,要么不保存任何实体吧?

英文:

I'm using Hibernate version 5.4.22.Final, with SpringBoot 2.3.5.RELEASE, and using this code:

CONTROLLER:

@PostMapping("/insert/{id}")
	public MyReposneEntitiy insertAutoAndSendNotification(@PathVariable("id") int id, @Valid @RequestBody Auto auto)  {
		MyReposneEntitiy e = service.insertAuto(auto, id);
		service.sendNotification(id);
		return e;
	}

SERVICE:

@Transactional
	public MyReposneEntitiy insertAuto(Auto auto, int id) {

		InfoForAuto info = infoRepo.findById(id).get();
		entityManager.detach(info);
        //this is annotated with @Version, 
        //and it can not be changed if the entity is in Persistence Contexxt
        //that's why I'm detaching first and then save
		info.setVersion(auto.getVersion());
		infoRepo.save(info);

		Person person = personService.createPerson(auto.getPerson());
		Eng eng = engService.createEng(auto.getEng(), person.getId());

		info.setMSDNumber(auto.getMSDNumber());
		info.setStatus(Constants.OK);

		MyReposneEntitiy response = new MyReposneEntitiy ();
		response.setStatus(Constants.OK);
		return response;
	}

	public void sendNotification(int id){
		//some code...
	}

CALLED SERVICE METHOD:

@Transactional
	public PersonResponse createPerson(PersonInput pesronInput) {...}
	
	@Transactional
	public EngResponse createEng(EngInput engInput, Integer personId) {...}

Now, the problem is, when insertAuto() method ends, and I'm in the first line in sendNotification() method (in debugging mode) I check the database and the "person" and "eng" are created in the database but the info entity is not updated, but I need it to be updated before I call sendNotification method, and I cant figure out why? Aren't they in the same transaction, and hibernate should either save all entities or save none?

答案1

得分: 1

当我调用 "infoRepo.save(info);" 时,save() 方法作为返回对象具有在Persistence Context中持久化的实体,所以我只需要执行 info = infoRepo.save(info);,现在它按预期工作。

英文:

OK, so I found what the problem was.

When I call "infoRepo.save(info);" the save() method as a return object have the entity that is persisted in Pestistence Context, so all I had to do is info = infoRepo.save(info); and now it works as it should.

huangapple
  • 本文由 发表于 2023年7月17日 16:45:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76702787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定