• hibernate save,update,saveorupdate方法有什么区别


    save肯定是添加的时候用,update修改时候用,saveorupdate是添加或修改,如果真是这样save和update的存在就没意义了,我们直接saveorupdate就行了。
    save在添加用的时候  不会出现索引机制(即遍历目录  效率最高)
    update在修改时候要遍历 不存在则会异常
    saveorupdate是优先遍历 如果不存在则创建(效率最低)
    merge和saveOrUpdate方法区别在于:merge方法是把我们提供的对象转变为托管状态的对象;而saveOrUpdate则是把我们提供的对象变成一个持久化对象;
    说的通俗一点就是:saveOrUpdate后的对象会纳入session的管理,对象的状态会跟数据库同步,再次查询该对象会直接从session中取,merge后的对 
    象不会纳入session的管理,再次查询该对象还是会从数据库中取。

     Session的save()方法使一个临时对象转变为持久化对象。例如以下代码保存一个Customer对象:

            Customer customer = new Customer();

            customer.setId(new Long(9)); // 为Customer临时对象设置OID是无效的

            customer.setName("Tom");

            Session session = sessionFactory.openSession();

            Transaction tx = session.beginTransaction();

            session.save(customer);

            session.close();

        Session的save()方法完成以下的操作:

        (1)把Customer对象加入到缓存中,使它变为持久化对象。

        (2)选用映射文件指定的标识符生成器为持久化对象分配惟一的OID。Customer.hbm.xml文件中<id>元素的<generator>子元素指定标识符生成器:

            <id name="id" column="ID">

                <generator class="increment"/>

            </id>

        以上程序试图通过setId()方法为Customer临时对象设置OID是无效的。假如起初CUSTOMERS表中没有记录,那么执行完save()方法后,Customer对象的ID为1。如果希望由程序来为Customer对象指定OID,可以调用save()的另一个重载方法:

            save(customer, new Long(9));

        以上save()方法的第二参数显示指定Customer对象的OID。这种形式的save()方法不推荐使用,尤其在使用代理主键的场合,不应该由程序为持久化对象指定OID。

        (3)计划执行一个insert语句,把Customer对象当前的属性值组装到insert语句中:

            insert into CUSTOMERS(ID, NAME, ......) values(1, 'Tom', ......);

        值得注意的是,save()方法并不立即执行SQL insert语句。只有当Session清理缓存时,才会执行SQL insert语句。如果在save()方法之后,又修改了持久化对象的属性,这会使得Session在清理缓存时,额外执行SQL update语句。以下两段代码尽管都能完成相同的功能,但是左边代码仅执行一条SQL insert语句,而右边代码执行一条SQL insert和一条SQL update语句。左边代码减少了操作数据库的次数,具有更好的运行性能。

            Customer customer = new Customer();         Customer customer = new Customer();

            // 先设置Customer对象的属性,再保存它       session.save(customer);

            customer.setName("Tom");                    // 先保存Customer对象,再修改它的属性

            session.save(customer);                    customer.setName("Tom");

            transaction.commit();                      transaction.commit();

        Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系。当Customer对象处于持久化状态时,不允许程序随意修改它的OID,例如:

            Customer customer = new Customer();

            session.save(customer);

            customer.setId(new Long(100)); // 抛出HibernateException

            transaction.commit();

        以上代码会导致Session在清理缓存时抛出异常。


    Hibernate <wbr>Session的save()方法无论Java对象处于临时状态、持久化状态还是游离状态,应用程序都不应该修改它的OID。因此,比较安全的做法是,在定义持久化类时,把它的setId()方法高为private类型,禁止外部程序访问该方法。


        Session的save()方法是用来持久化一个临时对象的。在应用程序中不应该把持久化对象或游离对象传给save()方法。例如以下代码两次调用了Session的save()方法,第二次传给save()方法的Customer对角处于持久化状态,这步操作其它是多余的:

            Customer customer = new Customer();

            session.save(customer);

            customer.setName("Tom");

            session.save(customer); // 这步操作是多余的

           transaction.commit();

        在例如以下代码把Customer游离对象传给session2的save()方法,session2会把它当做临时对象处理,再次向数据库中插入一条Customer记录:

            Customer customer = new Customer();

            customer.setName("Tom");

            Session session1 = sessionFactory.openSession();

            Transaction tx1 = session1.beginTransaction();

            session1.save(customer); // 此时Customer对象的ID变为1

            tx1.commit();

            session1.close(); // 此时Customer对象变为游离对象

            Session session2 = sessionFactory.openSession();

            Transaction tx2 = session2.beginTransaction();

            session2.save(cutomer); // 此时Customer对象的ID变为2

            tx2.commit();

            session2.close();

        尽管以上程序代码能正常运行,但是会导致CUSTOMERS表中有两条代表相同业务实体的记录,因此不符合业务逻辑。

     

    hibernate提供了saveOrUpdate的方法来进行数据库的操作。hibernate会根据对象的状态决定是insert还是update,
    其根本是通过xml文件中unsaved-value来确定的。如果设置null,系统会根据传入的对象的id的值判断,如果是null,
    则表示对象不存在,那么insert;如果不是Null,则表示已经存在,那么update.如果设置为none,那么表示对象不存在,
    会始终调用insert;如果设置为any,那么表示对象始终存在,会始终调用update

    
    


        数据库表主键的知识点:
        Generator 为每个 POJO 的实例提供唯一标识。一般情况,我们使用“native”。
    class 表示采用由生成器接口net.sf.hibernate.id.IdentifierGenerator 实现的某个实例,其中包括:

    
    

       “assigned” 主键由外部程序负责生成,在 save() 之前指定一个。

    
    

       “hilo” 通过hi/lo 算法实现的主键生成机制,需要额外的数据库表或字段提供高位值来源。

    
    

       “seqhilo”与hilo 类似,通过hi/lo 算法实现的主键生成机制,需要数据库中的 Sequence,
                适用于支持 Sequence 的数据库,如Oracle。

    
    

       “increment”主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,
                之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:不能在集群下使用。

    
    

       “identity”采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL 中的主键生成机制。

    
    

       “sequence”采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequence。

    
    

       “native”由 Hibernate 根据使用的数据库自行判断采用 identity、hilo、sequence 其中一种作为主键生成方式。

    
    

       “uuid.hex”由 Hibernate 基于128 位 UUID 算法 生成16 进制数值(编码后以长度32 的字符串表示)作为主键。

    
    

       “uuid.string”与uuid.hex 类似,只是生成的主键未进行编码(长度16),不能应用在 PostgreSQL 数据库中。

    
    

       “foreign”使用另外一个相关联的对象的标识符作为主键。

    
    

       以下举例:
       1、指定参数的情况:
          <id name="id" unsaved-value="0"> 
            <generator class="sequence">
              <param name="sequence">SEQ_CHILD</param>
            </generator>
          </id>
         使用的是sequence,适合oracle数据库;

    
    

       2、对于sql server2000中的数据库子增字段,在配置文件使用下列方法实现:
          <id name="id" type="long" unsaved-value="0">
            <column name="id" sql-type="numeric" not-null="true" />
            <generator class="identity" /> 
          </id>
        这里主要是:identity:代表由sql server2000数据库自己提供子增字段.如果要hibernate自己提供,则用increment关键字来实现

    
    

       3、如果表中的主键用字符串类型:可以用hibernate自己提供的方法实现主键唯一:
         <id name="id" type="string" unsaved-value="null">
             <column name="cid" sql-type="char(32)" not-null="true" />
             <generator class="uuid.hex" />
         </id>
         使用的是uuid.hex: 采用128位的算法来生成一个32位字符串。最通用的一种方式。适用于所有数据库。

    
    

       重要的知识点:
       1. 如果有部门表,有员工表,员工表中有dep_id,则表部门类和员工类是one-to-many的关系:
          可以使用: ( 在部门类department中使用下列)
          Department类: 
            /** 部门的所有员工   */
           private Set staffs = new TreeSet();
         
           xml的文件:
             <set name="staffs" >
                 <key column="dep_id"/>
                 <one-to-many class="hbp.sys.data.Staff"/>
             </set>
             如果是list,需要用索引<index> </index>,具体其中的含义,不是很明白.待以后研究
          
        2. 如果部门要有一个负责人,即部门表(tb_department)中有一个字段:staff_id.
            那么表示部门和负责人之间的关系是many-to-one的关系
            Department类: 
             /** 部门负责人id */
           private Staff staff;
        
           xml 文件
            <many-to-one name="staff" class="hbp.sys.data.Staff" column="staff_id"/> 

        3. 多对多关系,一般我们是做一个中间关联表.我用角色和权限做了个例子,
             Right(id,name)     Role(id,name)   中间表:tb_role_right(role_id,right_id)
             Right类中有一个Role的集合:private Set roles=new TreeSet();
             Role类中也有一个Right的集合:private Set rights=new TreeSet();
             则两者是明显的多对多关系.使用many-to-many来实现;
             xml文件中
             right.hbm.xml:如下:
               <set name="roles" table="tb_role_right" cascade="all">
                  <key column="right_id"/>
                  <many-to-many column="role_id" class="hbp.sys.data.Role"/>
               </set> 
             role.hbm.xml文件中类似:
               <set name="rights" table="tb_role_right" cascade="all">
                 <key column="role_id"/>
                 <many-to-many column="right_id" class="hbp.sys.data.Right"/>
               </set>

    
    

       4. 几个值得注意的问题:
               a)在xml?映射文件中,写类的名字时一定用类的全名:即:包+类名如:(hbp.sys.data.Staff),这个错误使我费了半天劲.:(
               b)我在写实现基本DAO操作时,写了
                    session.delete("from Right as right where right.id="+id); 
                    程序死活报错,我折腾了半天,跟踪到底,才恍然大悟,hibernate在解析sql语句的时候把
                    其中的right,当成了数据库中的右连接("保留字"),唉,这种关键字,不能随便用啊,:)

    
    

       5. hibernate中HQL语言的查询根据你的sql的不同而返回不同的对象类型.
                如果你使用session.find(String hql)
                一般会返回一个List,如:from Staff staff;返回的是包含所有的员工对象的集合
                如你的hql为:select count(*) from Staff staff;则返回的是一个Integer对象
                如果你使用的hql为:select count(distinct staff.name),count(*) from Staff staff;则返回的是一个Object
                即Object[],需要先把他转换成Object[],然后在取[0],[1].
                这种设计我不知道hibernate是如何处理的,感觉既好也不好.好的是可以使用一个find获得任意查询
                不好在于根据hql来处理返回结果,容易出错.

    
    
  • 相关阅读:
    jQuery的遍历方法
    xampp配置host和httpd可以随意访问任何本机的地址
    JavaScript的this简单实用
    移动端rem布局和百分比栅格化布局
    你知道用AngularJs怎么定义指令吗?
    谈谈Angular关于$watch,$apply 以及 $digest的工作原理
    深入了解Angularjs指令中的ngModel
    如何将angularJs项目与requireJs集成
    requireJS(二)
    requireJS(一)
  • 原文地址:https://www.cnblogs.com/WuXuanKun/p/5826918.html
Copyright © 2020-2023  润新知