春季数据更新实体无交易



我有带有弹簧数据的简单代码示例:

实体

@Entity
@Table(name = "car")
public class Car {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
//...
}

存储库:

@Repository
public interface CarRepository extends JpaRepository<Car, Long> {
}

服务与示例方法:

@Service
public class CarService {
    @Autowired
    private CarRepository carRepository;
    public void change() {
        Car one = carRepository.findOne(1L);
        one.setName("changed"); //important
    }
}

和控制器:

@RestController("/")
public class CarController {
    @Autowired
    private CarRepository carRepository;
    @Autowired
    private CarService carService;
    @GetMapping
    public List<Car> home() {
        carService.change();
        List<Car> all = carRepository.findAll();
        return all;
    }
}

我也有3个记录的data.sql:

insert into car values (1, 'aaa');
insert into car values (2, 'bbb');
insert into car values (3, 'ccc');

当我将请求发送到Localhost:8080时,我将获得三辆汽车的列表,其中第一辆车已更新:

insert into car values (1, 'changed');
insert into car values (2, 'bbb');
insert into car values (3, 'ccc');

我的期望是,从控制器调用更改后,实际上什么也没发生,因为此方法不是交易的。那么,为什么我的Home()方法在控制器返回列表中具有更新的实体?

这个问题与这个春季数据jpa @transactional完全不同,我不明白为什么您将其标记为重复。

我想,您正在使用Spring Boot。如果您将Spring Boot与Spring MVC和Spring Data一起使用,则每当您的控制器方法收到请求时,默认情况下将打开休眠式会话。会话提供您的应用程序和数据库之间的物理连接。可以使用spring.jpa.open-in-view应用程序属性来控制此功能。

Car one = carRepository.findOne(1L); //1
one.setName("changed"); //2
List<Car> all = carRepository.findAll(); //3
return all;
  1. 当程序达到上述代码时,将打开会话。在第一行中,从DB检索汽车对象,并且该对象存储在First Level Cache中。
  2. 作为" 一个"的引用指向同一对象,即在缓存中,在第2行中,缓存对象名称更改。
  3. 在第三行上,我们获得了我们之前检索到的对象的缓存值,该值在末尾返回。

由于修改后的值永远不会冲入DB,因此控制器调用后,您可以检查DB,您会发现,尽管您在控制器响应中收到了不同的值。<<<<<<<<<<<<<<

如果将spring.jpa.open-in-view属性设置为 false ,您的控制器将返回"正确"值。

根据春季数据文档方法是交易的!

4.7。交易性

存储库实例上的CRUD方法默认情况下是事务。用于阅读操作交易配置readonly标志设置为true,所有其他标志均配置使用普通的@transactional,以便默认交易配置适用。有关详细信息,请参见Javadoc。

在此处阅读完整文档:https://docs.spring.io/spring-data/jpa/docs/current/referent/referent/html/#transactions

a)弹簧数据jparepository的默认行为是返回附件的实体。如果您在同一持久性会话中对该附件对象执行更新,则刷新会话时对持久状态的更改将更新。

b)默认情况下,弹簧数据存储库上的方法是事务。默认设置为:

 propagation  REQUIRED
 isolation    DEFAULT
 timeout      -1
 read-only    false

c)最后您的主页()方法标记了交易和JPA会话的开始和结束。使用会话后,TransActionManager会创建会话。该方法完成交易后,交易将被提交或滚回去,JPA会话被冲洗并关闭。

我希望有助于解释您的结果。

如果您使用Hibernate作为ORM工具,则可能会由于脏检查而发生。如果您修改了Hibernate Session已知的对象会话被冲洗

最新更新