我有带有弹簧数据的简单代码示例:
实体
@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;
- 当程序达到上述代码时,将打开会话。在第一行中,从DB检索汽车对象,并且该对象存储在
First Level Cache
中。 - 作为" 一个"的引用指向同一对象,即在缓存中,在第2行中,缓存对象名称更改。
- 在第三行上,我们获得了我们之前检索到的对象的缓存值,该值在末尾返回。
由于修改后的值永远不会冲入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已知的对象会话被冲洗