`

hibernate_02 四种状态 多对一级联操作

 
阅读更多

 *一)持久化对象的状态变化和对应的方法
   (1)持久化对象在整个hibernate框架中运行,一共有四种不同的状态产生:
 我们从三个方面进行比较:A)位于session缓存内外;B)是否有与数据库交互能力;C)OID是否有值
        A)临时状态
    就是通过关健字new创建出来的对象
    session缓存【外】
    不能与数据库进行交互
    无OID值,此时hibernate框架没有为customer对象分配OID值

        B)持久化状态【重要】
    session缓存【内】 
    能与数据库进行交互
    有OID值,此时hibernate框架根据OID生成策略,自动产生id值,通过setId()方法,传入到持久化对象中   
 
        C)游离状态
    session缓存【外】 
    不能与数据库进行交互
    有OID值,该OID值是原来持久化对象留下来的值

        D)删除状态
    session缓存【外】
    不能与数据库进行交互
    有OID值,该OID值是原来持久化对象留下来的值
        参见<<PPT第7,8,9页>>

 

 
   (2)测试addCustomer()和findCustomerById()演示上述四种不同的状态产生
   (3)curd方法使用的细节
 A)save()方法细节
    1)解析映射文件,并检查正确性
    2)根据OID生成策略,hibernate为对象分配值
    3)动态生成对应的SQL语句,暂未执行,就时也叫计划执行一条SQL命令  
       *B)update()方法细节
    >>持久化对象和游离对象都可以操作update()方法
    >>当update()方法关联一个游离对象时,如果这时Session缓存中已经存在相同OID的持久化对象, 会抛出异常
    >>当update()方法关联一个游离对象时,如果在数据库中不存在相应的记录,也会抛出异常.
    >>Session缓存特有的快照功能,即自动更新
    >>save()方法 + update()方法 = saveOrUpdate()方法
 C)get() 和 load() 方法
    load()方法如果找到了,返回该对象;如果找不到,抛异常java.lang.ObjectNotFoundException
    get()方法如果找到了,返回该对象;如果找不到,抛异常java.lang.NullPointerException
    这二个方法的查找策略也不同,第四天再讲。 
        D)持久化对象和游离对象都可以操作delete()方法
    只要调用delete()方法,对象就会进入删除状态
         
二)映射持久化对象的标识符
    (1)Java中采用什么来区别同一个类的不同对象?
         通过hashCode()来区分同一个类的不同对象
 
    (2)表中采用什么来区别不同记录
  通过主键来区别不同记录

    (3)Hibernate中采用什么来区别Session一级缓存中的持久化对象?
  通过OID来区别Session一级缓存中的持久化对象

    (4)表中有哪些字段适合作主键?
  A)【单个、组合】自然主健:具有业务含义的字段做主键,叫自然主健
  B)【单个】代理主健:无任何业务含义的字段做主键,代理主键

   *(5)hibenate内置主健生成策略:
  我们从三个方面进行比较:A)主键类型;B)是否依赖于底层数据库;C)多线程情况下是否安全;
         >>increment
    int/long/short
           不需要依赖于底层数据库
    不能在多线程下运行  
    争对代理主健 
         >>identity
    int/long/short
           需要依赖于底层数据库,在MySQL中,一定要加上auto_increment关健字
    能在多线程下运行
    争对代理主健 
         >>native【重要】
    如果底数据库是MySQL或SQLServer等支持自动增长id的数据库,选用identity 
    如果底数据库是Oracle等不支持自动增长id的数据库,选用sequence 
    争对代理主健 
         >>uuid
    只能是字符串类型(varchar/String)
           不需要依赖于底层数据库
    能在多线程下运行
    id值,所占空间相对整型而言,较大
  >>sequence【专用于oracle数据库,学完oracle再用】
         >>assigned
    与业务字段同类型
           不需要依赖于底层数据库
           不能在多线程下运行  
    争对自然主键
         >>composite-id
    与业务字段同类型
           不需要依赖于底层数据库
    不能在多线程下运行
    争对多个自然主键
    需要实现序列化接口
  参见<<PPT第24页>>

三)【单向】多对一【客户(id/name/age/des) vs 订单(id/orderno/price/time)】

     order.java

   

private Integer id;//与记录的主键一一对应
private String orderno;
private Integer price;
private Timestamp time;//下订单时间
private Customer customer;//关联属性

 
     Order.hbm.xml文件

   <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
<!-- hibernate映射文件 -->    
<hibernate-mapping package="cn.itcast.web.hibernate.many2one_single">
 <class name="Order" table="ORDERS">
  <id name="id" column="ID">
   <generator class="native"/>
  </id>
  <property name="orderno" column="ORDERNO"/>
  <property name="price"  column="PRICE"/>
  <property name="time"  column="TIME"/>
  
  <!-- 映射关联属性
    name:表示Order类的关联属性
    column:orders表的外健
    cascade:表示当操作Order对象时,级联Order对象所关联的其它对象
    常用的取值如下:
        save-update:表示级联保存和更新
        delete    : 表示级联删除
        all        : save-update + delete 的所有功能  
   -->
  <many-to-one 
   name="customer"
   column="customers_id"
  />
  
 </class> 
</hibernate-mapping> 

  
     1)先保存1客户,再保存2订单-----3条SQL
     2)先保存2订单,再保存1客户-----5条SQL
     3)只保存2订单,级联保存1客户【cascade="save-update"】
     4)删除订单,级联删除客户【cascade="delete/all"】
     5)只删除订单,不级联删除客户
     参见<<PPT第43页>>  

四)【单向】一对多【客户 vs 订单】

     Customer.java

  

        private Integer id;
	private String name;
	private Integer age;
	private String des;
	private Set<Order> orderSet = new HashSet<Order>();//关联属性

 
     Customer.hbm.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
<!-- hibernate映射文件 -->    
<hibernate-mapping package="cn.itcast.web.hibernate.one2many_double">
	<class name="Customer" table="CUSTOMERS">
		<id name="id" column="ID">
			<generator class="native"/>
		</id>
		<property name="name" column="NAME"/>
		<property name="age"  column="AGE"/>
		<property name="des"  column="DES"/>
		
		
		<!-- 映射关联属性 
			 name表示Customer类的关联属性
			 table表示Customer类对应的Order表名
			 column表示orders表的外健
			 class表示Order的类型 	
		-->		
		<set name="orderSet" table="ORDERS" cascade="all">
			<key column="CUSTOMERS_ID"/>
			<one-to-many class="Order"/>
		</set>
		
	</class>	
</hibernate-mapping>    

 
     1)只保存客户,级联保存订单
     2)只更新客户,级联更新订单
     3)只删除客户,级联删除订单

*五)【双向】一对多【客户 vs 订单】
     1)增加1个客户,级联增加3个订单
     2)查询和修改1个客户,级联查询和修改3个订单
     3)删除1个客户,级联删除3个订单

六)动手练习
   【需求】
    Student(id编号/name姓名/gender性别) vs Phone(id编号,no手机号码,address归属地)
    Student(单方)vs Phone(多方)
    1)保存Student,级联保存Phone
    2)删除Student,级联删除Phone
    3)更新Student,级联更新Phone 

 

public class StudentDao {
	public void saveStudent() {
		Student student = new Student("貂蝉", "女");
		Phone phone1 = new Phone("1234", "三国");
		Phone phone2 = new Phone("1212", "三国");
		student.getPhoneset().add(phone1);
		student.getPhoneset().add(phone2);
		// phone1.setStudent(student);
		// phone2.setStudent(student);
		Session session = DBUtils.getFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.save(student);
		transaction.commit();
		session.close();
	}

	public Student getStudent(int stu_id) {
		Student student = new Student();
		Session session = DBUtils.getFactory().openSession();
		student = (Student) session.get(Student.class, stu_id);
		return student;
	}

	public void delstudent(int stu_id) {
		Session session = DBUtils.getFactory().openSession();
		Transaction transaction = session.beginTransaction();
		Student student = (Student) session.get(Student.class, 3);
		session.delete(student);
		transaction.commit();
		session.close();
	}

	public void update(int stu_id) {
		Session session = DBUtils.getFactory().openSession();
		Transaction transaction = session.beginTransaction();
		Student student = (Student) session.get(Student.class, stu_id);
		student.setName("大乔");
		for (Phone phone : student.getPhoneset()) {
			phone.setNumber(phone.getNumber() + "1");
		}
		transaction.commit();
		session.close();
	}
}

 

 

 

  • 大小: 25.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics