使用JPA时对象在set属性时更新了数据库问题,没有save操作
使用JPA时对象在set属性时更新了数据库问题,没有save操作。
使用JPA时对象在set属性时更新了数据库问题,没有save操作
问题原因(抄的)
Hibernate有三种基本状态: 简单的说
自由态(临时状态):直接new出来的对象,既没有被保存到数据库中,也不处于session缓存中
游离态:已经被保存到数据库中但不处于session缓存中
持久态:已经被保存到数据库中并且加入到session缓存中
上述代码中的对象是持久化状态的对象,对其进行set操作时session缓存中的数据发生了改变,数据库也会跟着进行相应的改变,所以执行了update的更新操作
瞬时状态(Transient) 复杂的说
通过new创建对象后,对象并没有立刻持久化,它并未与数据库中的数据有任何关联,此时Java对象的状态为瞬时状态。Session对于瞬时状态的Java对象是一无所知的,当对象不再被其他对象引用时,它的所有数据也就丢失了,对象将会被Java虚拟机按照垃圾回收机制处理。
持久状态(Persistent)
当对象与Session关联,被Session管理时,它就处于持久状态。处于持久状态的对象拥有数据库标识(数据库中的主键值)。那么,对象是什么时候与Session发生关联的呢?有两种方法:
第一种,通过Sesison的查询接口,或者get()方法,或者load()方法从数据库中加载对象的时候,加载的对象是与数据库表中的一条记录关联的,此时对象与加载它的Session发生关联;
第二种,瞬时状态的对象,通过Session的save()方法或SaveOrUpdate()方法时,Java对象也与Session发生关联。
对于处于持久状态的对象,Session会持续跟踪和管理它们,如果对象的内部状态发生了任何变更,Hibernate会选择合适的时机(如事务提交时)将变更固化到数据库中。
游离状态
处于持久状态的对象,脱离与其关联的Session的管理后,对象就处于游离状态。
处于游离状态的对象,Session无法保证对象所包含的数据与数据库中的记录一直,因为Hibernate已经无法感知对该对象的任何操作。
Session提供了两个方法(update()、merge()),将处于游离状态的对象,与一个新的Session发生关联。
此时,对象的状态就从游离状态重新转换为持久状态。
问题解决 1 使用BeanUtils.copyProperties
使用赋值的对象,而不使用数据库查出来的对象。
优点,可以避免所谓的代码污染
OrderGoods orderGoodsCopy = new OrderGoods();
BeanUtils.copyProperties(orderGoods,orderGoodsCopy);
//可退商品数量
orderGoodsCopy.setGoodsInfoNum(goodsNumSum);
//可退商品总价
orderGoodsCopy.setGoodsBackPrice(goodsPriceSum);
问题解决 2 使用 detach
private final EntityManager entityManager;
@Transactional //不开事务是不会有什么游离态的
@Commit
public void testUpdateEntity(){
UserInfo userInfo = userInfoRepository.get(2103031645422940000L);
userInfo.setFullName("我不是管理员111");
entityManager.detach(userInfo);
}
查看save保存的源码
private final EntityManager em;
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity); //这里才是真正保存的地方
return entity;
} else {
return em.merge(entity);
}
}
具体的em.persist(entity); 的源码,还需要深入学习
具体是再那里保存的数据,session是怎么自动保存的,代码还没有找到

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)