首页 > 其他分享 >hibernate——Session接口中定义的saveOrUpdate()方法浅析

hibernate——Session接口中定义的saveOrUpdate()方法浅析

时间:2023-08-27 11:06:56浏览次数:39  
标签:hibernate saveOrUpdate unsaved value 浅析 Session user id User


Session接口中定义的saveOrUpdate方法,集合了save和update方法,根据对象的状态来选择是进行保存还是更新,那它是怎么判断当前对象的状态的呢?API中对这个方法是这样说的,它是根据一个unsaved-value来决定的。这个值是在映射文件中的<id>标签中的一个属性。<id>标签表示的是表的主键,若主键是字符串,那么这个值默认的是空,如果主键是int型,那么这个值默认的是0。然而我们可以改变这个默认的值,虽然一般都用默认的值,但是为了弄清saveOrUpdate这个方法,我们这里对这个值进行改变,看它到底是怎么工作的。此外,为了更清楚的说明问题,对hibernate.cfg.xml文件再进行一下配置,加上这样一条语句:<property name="hibernate.show_sql">true</property>,这条语句的作用,就是将hibernate使用到的sql语句打印到控制台。

首先看下面这个例子:

User类:

public class User {
	
	private int id;
	private String name;
	private Date birthday;

	……
}



User.hbm.xml文件:

<hibernate-mapping package="com.suo.domain">
	
	<class name="User">
		<id name="id" unsaved-value="2">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="birthday"/>
		
	</class>
	
</hibernate-mapping>

注意:在id标签中,将unsaved-value值设置为2,默认的是0。


Test.java:

public class Test {

	public static void main(String[] args) {
		
		User user=new User();
		
		user.setId(2);//这里将id设置为2
		user.setBirthday(new Date());
		user.setName("suo");
		
		//此时的user对象是瞬时状态(Transient)
		
		System.out.println(user.getId()+" in transient status");
		
		addUser(user);
		
		//此时的user对象是脱管的(Detached)
		
		System.out.println(user.getId()+" in detached status");
	}
	
	public static void addUser(User user){
		Session session=null;
		Transaction transaction=null;
		
		try{
			session=HibernateUtil.getSession();//获得一个连接
			transaction=session.beginTransaction();//开启一个事务
			
			session.saveOrUpdate(user);
			
			System.out.println(user.getId()+" in persistent status");
			
			//此时的user对象是持久的(Persistent)
			
			transaction.commit();/*设置为自动提交,因为hibernate默认的设置为不自动提交,
								        这时候使用的数据库引擎为InnoDB,支持事务*/
			
		}catch(HibernateException e){
			if(transaction!=null){
				transaction.rollback();
			}
			e.printStackTrace();
		}finally{
			if(session!=null){
				session.close();
			}
		}
	}
}

注意:在对user进行set的时候,将id设置为2,和unsaved-value的值是相等的。


运行结果如下:

2 in transient status
Hibernate: insert into User (name, birthday) values (?, ?)
1 in persistent status
1 in detached status

根据输出的sql语句可以知道,saveOrUpdate()执行的是save方法,并且持久态的user的id值已经改变,所以save方法也执行成功了。


此时,将user的id的初始值set为3,和unsaved-value的值不相等,执行结果如下:

3 in transient status
3 in persistent status
Hibernate: update User set name=?, birthday=? where id=?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

……

3 in detached status

根据输出的sql语句可以知道,saveOrUpdate执行的是update方法,但是抛出了异常,并且持久态和脱管态的对象的id没有改变,说明更新没有成功,为什么呢?

这个很明显了,saveOrUpdate方法到底是执行保存还是更新,是以对象中的id的初始值和unsaved-value值进行比较来为依据的。unsaved-value值相当于一个标志位,它定义了若这个对象没有被保存,那么它的id值应该是什么值,即处于瞬时状态的对象的id,应该具有的值。如果对象的id值和这个值相等,说明这个对象还没有被保存,即处于瞬时状态,那么saveOrUpdate方法就执行保存的操作;如果对象的id值和这个不相等,说明这个对象已经被保存过了,那么就应该执行更新的操作了。上例中,我们将user的id属性初始值设置为3,和unsaved-value的值不相等,就让hibernate误以为这个对象是保存过的了,所以它就执行了更新的操作,但是,数据库中并没有这个对象对应的记录,无法完成更新,所以就抛出了异常。

通过上面的分析,我们可以得出一个结论,即不要随便改变unsaved-value的值,尽量用它的默认值,如果真的要改变的话,就要将对象的id属性的初始值设置为和unsaved-value值相等的值,才可以进行正常的操作。


标签:hibernate,saveOrUpdate,unsaved,value,浅析,Session,user,id,User
From: https://blog.51cto.com/u_5173797/7251408

相关文章

  • hibernate——初步认识
    开始学习hibernate了,跟着网上的教学视频边看边学。现在有些迷茫,不知道学这些东西,以后能不能用得上,也不知道未来会发展成什么样子,也不知道我的基础算是打好了没有,总觉得学这些框架,有点浮沙筑高台的感觉,心里很不踏实。知道的都是些表面的东西,框架底层是什么样的,看看那些源代码,想看懂......
  • 用拦截器实现session登录
    这个功能是这样的,用户在访问网站时,先要进行登录,即要访问处理登录的Action,若没有登录,即访问除了登录的Action之外的Action,则会被拦截器拦截,跳转到错误页面,提示用户还没有进行登录。所以这个拦截器的作用是如果是登录,即请求的是LoginAction,那么就不拦截这个请求,让其通过拦截器,进行登......
  • hibernate——两种查询方式
    一种是hql语句查询,用Query接口去实现;一种是条件查询,用Criteria接口去实现。这两种方式作用差不多,只是后者更符合面向对象一些。用hql语句查询,如下例:publicstaticvoidquery(Stringname){ Sessionsession=null; try{ session=HibernateUtil.getSession(); //St......
  • hibernate——和数据库关联的对象的三种状态
    和数据库关联的对象有三种状态:瞬时,持久,脱管。瞬时:在数据库中还没有与该对象关联的记录,仅仅是一个普通的对象而已,超过作用域,就会被回收。一般都是new出来的对象,并且还没有与session建立联系。持久:与session建立了联系,并且在数据库中已经有了和该对象关联的记......
  • hibernate——一对一、多对一和多对多关系的比较
    现在学习完了这几种映射关系,但是有点乱,这里来小结一下。关键是表之间如何产生映射关系,以及产生的表的结构。1、一对一映射:一对一是通过one-to-one标签来产生映射关系的,其实,如果单单说是建立两个表之间的关联,只要在一个映射文件中配置one-to-one标签就可以了,在另一个映射文件中,也做......
  • 商品推荐系统浅析
     一、综述本文主要做推荐系统浅析,主要介绍推荐系统的定义,推荐系统的基础框架,简单介绍设计推荐的相关方法以及架构。适用于部分对推荐系统感兴趣的同学以及有相关基础的同学,本人水平有限,欢迎大家指正。二、商品推荐系统2.1推荐系统的定义推......
  • Spring Data JPA查询报错java.lang.StackOverflowError hibernate SpringBoot
    toString()造成死循环,重写toString()方法现象测试JPA的多对多查询时,有一个User对象,该User有多个Role,然后报错User@Data@Entity@Table(name="user")publicclassUser{@Id//主键自动增长@GeneratedValue(strategy=GenerationType.IDENTITY)@Co......
  • 浅析三维模型OBJ格式轻量化处理常见问题与处理措施
    浅析三维模型OBJ格式轻量化处理常见问题与处理措施 在三维模型OBJ格式轻量化处理过程中,可能会遇到一些问题。以下是一些常见问题以及相应的解决方法:1、文件大小过大:OBJ格式的三维模型文件通常包含大量的顶点、面片和纹理信息,导致文件体积较大。这会影响加载和渲染速度。解决......
  • Django项目异常:AttributeError: 'SessionStore' object has no attribute '_session_c
    Traceback(mostrecentcalllast):File"C:\ProgramFiles\python37\lib\site-packages\django\contrib\sessions\backends\base.py",line189,in_get_sessionreturnself._session_cacheAttributeError:'SessionStore'objecthas......
  • Cookie、Session及Token详解
    CookieCookie,有时也用其复数形式Cookies,类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息以加入购物车为例,每次浏览器请求后server都会将本次商品id存储在Cookie中......