首页 > 解决方案 > 弹簧靴。@Transactional 方法调用 @Transactional(readonly=true) 方法

问题描述

我有下一个问题。当控制器调用带有@Transactional注释的服务方法并且此方法调用@Transactional(readonly=true)方法时,对象中的更改不会保存在数据库中。我不知道为什么。我认为第一种方法开始一个“读写”事务,而第二种方法使用相同的事务。

例子 :


/** Controller class **/

@RestController
@RequestMapping("/path1")
public class MyObjectRestController {

    ... 

    @Autowired
    MyObjectService myObjectService;

    @PostMapping(value = "/path2")
    @ResponseStatus(HttpStatus.CREATED) 
    public void save(@RequestBody MyObject myObject) {
        myObjectService.save(myObject);
    }
    
    ...
}
/** Service class **/

public interface MyObjectService {
    public MyObject save(MyObject myObject);
    public MyObject findOne(long id);
}
/** Service implementation class **/

@Service
public class MyObjectServiceImpl implements MyObjectService {

    /**
     * Save Object
     */
    @Override
    @Transactional  
    public Object save(Object newObject) {

        Object myObject = this.findOne(newObject.getId());
        
        // Modify Object
        myObject.setAttribute1(...)
        myObject.setAttribute2(...)
        
        // Save Object (using Repository)
        return MyObjectDao.save(myObject);
    }

    /**
     * Get Object by Id 
     */
    @Override
    @Transactional(readOnly = true)
    public MyObject findOne(long id) {
        Optional<MyObject> myObject = MyObjectDao.findById(id);
        return myObject.isPresent() ? myObject.get() : null;
    }   
}

此示例不更新对象属性。但是如果我删除@Transactionalsave(..) 方法中的注释......这个例子成功了!(对象被修改)。

为什么会这样?

标签: javaspringspring-boottransactionsreadonly

解决方案


我看到save方法被注释@Transactional并调用findOne方法也是@Transactional. 因此,在这种情况下,相同的事务被传播到findOne方法,并将只读行为应用于当前事务。因此它不执行刷新,你会看到实体没有被修改。

因此,在这种情况下,您应该使用单独的事务进行读取和写入。

findOne方法可以用以下注释 -

@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)

推荐阅读