Spring数据更新实体而没有事务

时间:2017-11-27 17:53:14

标签: hibernate jpa spring-data

我有Spring Data的简单代码示例:

实体

@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;
    }

}

我也有data.sql有3条记录:

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');

我的期望是从控制器调用change()之后实际上没有任何反应,因为此方法不是事务性的。那么为什么控制器中的home()方法返回带有更新实体的列表?

这个问题完全不同于Spring data jpa @transactional我不明白为什么你把它标记为重复。

2 个答案:

答案 0 :(得分:2)

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

Car one = carRepository.findOne(1L); //1
one.setName("changed"); //2
List<Car> all = carRepository.findAll(); //3
return all;
  1. 当程序到达上述代码时,会话将打开。 在第一行,从数据库中检索Car对象,并将该对象存储在First Level Cache中。
  2. 由于“ one ”引用指向缓存中的同一对象,因此在第二行,缓存的对象名称会更改。
  3. 在第三行,我们获得了对象的缓存值,该值是我们先前检索的,并且该值在结尾处返回。

由于修改后的值永远不会刷新到数据库,因此在控制器调用之后,您可以检查数据库,并且您会看到,尽管控制器响应中收到的值不同,对象的旧值仍然保留。 / p>

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

答案 1 :(得分:0)

如果你使用hibernate作为你的ORM工具,这可能是由于脏检查而发生的。如果你修改了一个hibernate会话已知的对象,当会话被刷新时它会被hibernate自动保存