【Java】Hibernate(二)持久化对象的三种状态和CRUD

【Hibernate中的Session】

      第一点申明, Hibernate的session和HTTP的session会话是两码事。
      Session是Java应用程序和Hibernate进行交互时使用的主要接口,也是持久化操作的核心。它提供了很多持久化的方法,如save update delete等。通过这些方法我们就可以透明的完成对象的增删改查CRUD。透明是指Session在读取,创建,和删除映射实体对象的实例时,这些操作将回被转换为数据库表中数据的读取、创建、删除操作。

      Session对象是有生命周期的,它以transaction对象的开始和结束作为边界。Session是由SessionFactory生产出来的,SessionFactory是线程安全的,多个线程并发可以同时访问一个SessionFactory并从中获取Session实例。但是Session不是线程安全的,多线程同时使用一个实例进行数据存取操作的时候,就会导致混乱。所以我们需要保证每个线程一个session。


【持久化对象的三种状态】

      ☆Transient  瞬时状态:
      我们使用new操作符初始化对象,不是立刻就持久的。它们的状态是瞬时的,也是他们没和数据库表发生任何关系。如果应用不再引用这些对象或也不再被其他任何对象所引用,它们的状态就会丢失,并由垃圾回收机制回收。
      Transient 状态,因为没有被session管理,所以数据库里没有数据。

      ☆Persistent 持久状态:
      持久实例是任何具有数据库标识的实例。它由持久化管理器Session统一管理,持久实例在事务中进行操作,它们的状态在事务结束时,同数据库进行同步。当事务提交时,通过执行SQL的insert、update、delete语句把内存中的状态同步到数据库中。
      对象属性发生改变,也就是数据发生变化,再提交事务。事务提交的时候会清理缓存,就是检查脏数据(数据变了,数据库没变),检查哪些数据变化了。完成数据和内存的同步,不需要再写update语句。
 
      ☆Detached 离线(托管)状态:
      Session对象关闭之后,持久状态就变为离线状态。离线就表示这个对象不能再和数据库保持同步,它们就脱离了Hibernate的管理。
      Detached状态下, 数据库里是有数据的,只是不被session管理。我们可以执行update操作,就可以将detached状态对象重新纳入session管理,变为persistent状态对象。persistent状态下,清理缓存是会和数据库同步。(关于缓存的知识后面会详细介绍)
    

     我们发现这三种状态就是针对session来说的,是否受session的管理,是在session里,还是在session外。

      代码举例:

      User.hbm.xml 关联映射

     

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping >  <!-- hibernate关联映射 -->
	<class name="com.bjpowernode.hibernate.User">
		<id name="id">  <!-- 主键生成策略 -->
			<generator class="uuid"/>
		</id>
		<property name="name"/>
		<property name="password"/>
		<property name="createTime"/>
		<property name="expireTime"/>
	</class>
</hibernate-mapping>

     hibernate.cfg.xml配置

      

 <!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
	        <!-- MySQL数据库连接 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>		
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_basicmapping</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<!-- MySQL方言配置 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.show_sql">true</property>
		
		<!-- Hibernate映射文件配置 -->
		<mapping resource="com/bjpowernode/hibernate/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>  


     结合三种状态在Test中对User的增加、更新代码举例: 

import org.hibernate.Session;
public  void testSave1(){
		Session session=null;
		Transaction tx=null;
		User user=null;
		try{
			session =HibernateUtils.getSession();//获得session
			tx=session.beginTransaction();//事务建立
			
			//Transient
			user=new User();
			user.setName("辛巴");
			user.setPassword("123");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			//Persistent
			session.save(user);
			user.setName("娜拉");
			tx.commit();//事务提交
			 
		}catch (Exception e) {
			e.printStackTrace();//打印堆栈 
			if(tx!=null){
				tx.rollback();//事务回滚
			}
		}finally{
			HibernateUtils.closeSession(session);//关闭session
		}
		
		//detached,此时已脱离session
		user.setName("丁满");
		try{
		           //将detached状态对象重新纳入session管理
			session=HibernateUtils.getSession();
			session.beginTransaction();//事务建立
			
			//此时变为persistent状态对象,persistent状态下,清理缓存是会和数据库同步。
			session.update(user);
			session.getTransaction().commit();//事务提交
		}catch(Exception e){
			e.printStackTrace();
			session.getTransaction().rollback();
			
		}finally{
			HibernateUtils.closeSession(session);//关闭session
		}
	}	


【Hibernate 的CRUD】

        结合上面提到的session知识,我们所有的增删改操作都需要放到事务内执行。

Delete :只能删除数据库里存在的数据,需要先加载再删除。
1.先使用load/get方法查询。
2.再使用delete方法。

Update:只能更新数据库里存在数据。只有在没被session管理的时候,也就是detached状态才能更新。
怎么得到detached对象?
1.先查,使用load或get方法,先加载出数据。
2.再使用update更新。

对User 执行update举例:
public void testUpdate(){
			Session session=null;
			try{
				session=HibernateUtils.getSession();
				session.beginTransaction();
				//建议采用load方式更新,先加载再更新
				User user=(User)session.load(User.class, "4028168160bab3280160bab378980001");
				user.setName("穆法沙");
				//可以显示的update
				session.update(user);
				session.getTransaction().commit();
				
			}catch (Exception e) {
				e.printStackTrace();
				session.getTransaction().rollback();
			}finally{
				HibernateUtils.closeSession(session);
			}
		}		


【get方法和load方法区别】

       上面提到了加载时load和get两种方法,它们的区别也是很重要的。
       ·get只能根据主键进行查询,加载上来的对象为持久对象,执行get方法时会马上发出查询语句,所以get不支持延迟加载。如果查询不存在的数据,返回null。

      · load也只能根据主键查询。但不会马上发出查询语句,load支持延迟加载。只有真正使用对象时,对Hibernate来说才真正发出查询语句,这样做主要为了提高性能。lazy是Hibernate中非常重要的特性,主要通过代理对象实现,采用的是CGLIB库生成的,并不是jdk的动态代理。因为jdk的动态代理只能对实现了接口的类生成代理,而CGLIB可以直接对类生成代理,采用的是继承方式。如果load查询不存在的数据,Hibernate会抛异常ObjectNotFoundException。


【小结】

     下篇博客会分享一个简单的实现query接口来实现分页查询的功能,下篇见~
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值