现在的位置: 首页 > 综合 > 正文

Hibernate一对一操作

2013年08月13日 ⁄ 综合 ⁄ 共 7747字 ⁄ 字号 评论关闭

 [Hibernate的连表操作]
 多个实体(表)的关联关系,继承关系,如何用Hibernate实现级联操作?
  关联关系:   继承关系:
   级联操作:     级联的增、删、改;   连表查询;
  
           
 在PO中要添加关联属性 ,在映射配置中要添加关联配置,表达关联关系。            表达关联关系。
 优点:
       ①表间耦合度降低。表间可以尽量少建关联(及主外键关系+约束),使表易于修改、添加
      
       ②建立PO间关联。而需要时,可以随时建立PO间关联,实现级联操作、联表查询等功能。如此使用关联,灵活,易于修改。
      
       ③关联关系的配置化表达实现。解放了表间的耦合关系,将表间的关联关系等耦合,表达在O/RMapping的配置和PO中。
                                                           //也易于阅读。    Session的API:查、.save()、.delete()、.update()方法,会读取关联配置,自动实现级联操作,
                                                                                      不用你单写关联操作语句;
◆一对一映射
  特点:Table间没有关联关系,Hibernate也能通过 两个.hbm.xml映射文件间配置,及两个PO互相添加关联属性,实现PO间关联。

  步骤:
    1)先建SQL,客户和地址是一对一的关系:
                          
                create table CUSTOMER (                             create table ADDRESS(           关联的业务意义:
                      ID bigint not null auto_increment,                ID bigint not null auto_increment,
                      NAME varchar(15),                                      STREET varchar(128),
                     primary key (ID)                                             CITY varchar(128),
                );                                                                           PROVINCE varchar(128),
                                                                                             ZIPCODE varchar(6),
                                                                                             primary key (ID)
                                                                                          );         

     2)建立项目,建包,打入Hibernate capabilities;
 
               i) 先用工具,生成各个单表的配置;
             
              ii) 在《表1.hbm.xml》与《表2.hbm.xml》中添加关联映射配置;
           
                 address的映射配置信息                             customer的映射配置信息
                
               ◆<one-to-one name="address"                     ◆<one-to-one name="customer"            //本PO类引用对方PO对象
                     ━━━━━                                                         ━━━━━
                       class="mypack.Customer"                                  class="mypack.Address"              //属性Type---对方PO类名
                       cascade="all"              //可做所有级联操作        constrained="true"                         //彼此两个PO类间,还建立约束。
                    />                                                                          />                                              

        
            ◆一边的<one-to-one>配置,只负责单向的关联操作。
           
               iii)在各PO类中添加关联映射属性,PO中属性名及类型,必须与*.hbm.xml中的对应。
            
              private Address address;              private Customer customer;              ◆添加的关联属性----引用目标方对象。
               ━━━━━━━━━━━━              ━━━━━━━━━━━━

     3)DAO中实现关联映射操作
 
          /**
           * 保存Customer PO对象映射的记录时,级联插入关联的Address PO对象映射的记录;
           * @param c---临时态PO;
           */
          public void saveCustomer(Customer c){
            Session session=null;
            Transaction tr =null;
            try {
               session = HibernateSessionFactory.getSession();
               //获得session的另外一种方式:new Configuration().configure().bulidSessionFactory().openSession();
               tr= session.beginTransaction();
               session.save(c); ▲此PO对象放入缓存,进入持久态;其关联属性存放的关联PO对象也被带入缓存进入持久态;将形成两句insert的请求;
               tr.commit();   ▲因此本句session.flush()生成sql语句时,两个PO都生成insert()语句,级联插入;提交事务时,确认执行
           } catch (Exception e) {
              try {
              tr.rollback();
            } catch (HibernateException e1) {
              e1.printStackTrace();
            }
              e.printStackTrace();
           }finally{
              try {
               session.close();
            } catch (HibernateException e) {
               e.printStackTrace();
            }
           }
     
     4)模拟BO中用main()方法来调用DAO 方法:
            /**
              *级联插入
              */ 
            public static void main(String[] args){
              CustomerAddressDAO dao = new CustomerAddressDAO();
              Customer customer = new Customer();
              customer.setName("夏沫");
              Address address = new Address();
              address.setCity("长春");
              address.setProvince("吉林省");
              address.setStreet("台湾街");
              address.setZipcode("130003");
              customer.setAddress(address);  ▲customer的关联属性中放入关联address;由customer--->address单向关联;
              dao.saveCustomer(customer);   ▲插入Customer PO,会级联插入Address PO;
            }
 

    5)

            /**
             * 根据名字查询用户
             * @param name
             * @return
             */
            public Customer findCustomerByName(String name){
             Session session=null;
             Transaction tr=null;
             Customer c=null;
             try {
               session = HibernateSessionFactory.getSession();
                tr = session.beginTransaction();
               Query query = session.createQuery("from Customer u where u.name  like '%"+name+"%'");
                c = (Customer)query.list().get(0);//▲查取customer PO也将连表查取address PO;
               tr.commit();
             } catch (Exception e) {
               try {
                tr.rollback();
               } catch (HibernateException e1) {
                e1.printStackTrace();
               }
             }finally{
               session.close();
             }
              return c;
             }
             
    6)         
            /**
             *
             * 根据id主键号查询用户,使用session.load()方法
             */
            public Customer loadCustomer(long id){
             Transaction tr =null;
             Session session=null;
             Customer c=null;
             try {
              session = HibernateSessionFactory.getSession();
                 tr = session.beginTransaction();
                 c = (Customer)session.load(Customer.class,id);
                 ▲缺省的检索策略下,load()方法不能关闭session,否则,无法加载关联PO的代理对象;
                 tr.commit();
             } catch (HibernateException e) {
              try {
               tr.rollback();
              } catch (HibernateException e1) {
               e1.printStackTrace();
              }
               e.printStackTrace();
             }finally{
               //session.close();
             }
              return c;
            }
             ★通过主键ID值,查询;
                 方式I)通过session.load()方法,连表查询;
                 ◆理论:使用session.load();不能session.close();因为load()方法默认使用<惰性加载(也叫延迟检索策略)>;        
                     该方式为避免加载过多PO,先仅加载 主PO的代理对象和关联PO的代理对象,将来使用哪个代理对象时,再临时加载其字段属性值,如此节省内存;//1-*时就必需如此;
                     关闭session,将导致代理对象消失,之后无法提取关联PO值;强行提取抛异常:LazyInitalizationException;
                  优点:节省内存;
                  缺点:不能关闭session;
  
               方式II)通过session.get()方法,连表查询;
                 ◆理论:使用session.get();可以session.close();
                     因为get()方法默认使用<立即加载策略,该方式将立即得到关联PO属性值,关联PO已生成,关闭session也无影响.
                  优点:可以关闭session;
                  缺点:关联PO多时,浪费内存
  
    7)       /**
             *级联删除
             */
    
            Customer customer = dao.findCustomerByName("貂蝉");
            Address address = customer.getAddress();
            System.out.println("address:"+address.getId());
            dao.deleteCustomer(customer);
           
            DAO:
            /**
             * 删除Customer PO对象映射的记录时,级联删除关联的Address PO对象映射的记录;
             */
            public void deleteCustomer(Customer customer){
             Session session=null;
             Transaction tr =null;
             try {
               session = HibernateSessionFactory.getSession();
               tr= session.beginTransaction();
               session.delete(customer);//会级联删除关联属性中的address PO记录;
               tr.commit();
             } catch (Exception e) {
              try {
               tr.rollback();
              } catch (HibernateException e1) {
               e1.printStackTrace();
              }
              e.printStackTrace();
             }finally{
              try {
               session.close();
              } catch (HibernateException e) {
               e.printStackTrace();
              }
             }
            }

 

 

 

 

 

 

 

抱歉!评论已关闭.