使用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是怎么自动保存的,代码还没有找到

Logo

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

更多推荐