zoukankan      html  css  js  c++  java
  • Hibernate SQL优化技巧dynamic-insert="true" dynamic-update="true"

    最近正在拜读Hibernate之父大作<Java Persistence with Hibernate>,颇有收获。
    在我们熟悉的Hibernate映射文件中也大有乾坤,很多值得我注意的地方。
    在Hibernate的映射文件的class tag使用dynamic-insert,dynamic-update,可以优化生成的SQL语句,提高SQL执行效率,最终可以提高系统性能。
    如,有一个User类。

     
    1.   
    2. public class User {   
    3.       
    4.     /** Creates a new instance of User */  
    5.     public User() {   
    6.     }   
    7.     private long id;   
    8.     private int age;   
    9.   
    10.     private String firstname;   
    11.     private String lastname;   
    12.     private Set emailAddresses;   
    13. //省略getter 和setter方法   
    14. }   


    Hibernate映射文件(User.hbm.xml,省略了文件头声明)定义为:

     
    1. <hibernate-mapping>  
    2.     <class name="model.User" table="Users" >  
    3.         <id name="id" column="ID">  
    4.             <generator class="native"/>  
    5.         </id>  
    6.         <property name="age"/>  
    7.         <property name="firstname"/>  
    8.         <property name="lastname"/>  
    9.            
    10.         <set name="emailAddresses" table="PERSON_EMAIL_ADDR">  
    11.             <key column="PERSON_ID"/>  
    12.             <element type="string" column="EMAIL_ADDR"/>  
    13.         </set>  
    14.     </class>  
    15. </hibernate-mapping>  

    我们写一个测试类进行测试UserTest。


     
    1. public class UserTest extends TestCase {   
    2.        
    3.     public UserTest(String testName) {   
    4.         super(testName);   
    5.     }   
    6.        
    7.     private Session session;   
    8.     private SessionFactory sessionFactory;   
    9.        
    10.     protected void setUp() throws Exception {   
    11.         sessionFactory=HibernateUtil.getSessionFactory();   
    12.         session=sessionFactory.openSession();   
    13.         session.getTransaction().begin();   
    14.     }   
    15.        
    16.     protected void tearDown() throws Exception {   
    17.         session.getTransaction().commit();   
    18.         session.close();   
    19.            
    20.     }   
    21.        
    22.     /**  
    23.      * Test of getAge method, of class model.User.  
    24.      */  
    25.     public void testSaveUser() {   
    26.         System.out.println("================testSaveUser=================");   
    27.            
    28.         User user = new User();   
    29.         user.setAge(29);   
    30.         session.save(user);   
    31.         assertNotNull("id is assigned !",user.getId());   
    32.     }   
    33.     public void testUpdateUser() {   
    34.         System.out.println("================testUpdateUser=================");   
    35.            
    36.         User user = new User();   
    37.         user.setAge(29);   
    38.         session.save(user);   
    39.         assertNotNull("id is assigned !",user.getId());   
    40.            
    41.         User _user=(User) session.get(User.class, user.getId());   
    42.         _user.setFirstname("Array");   
    43.         session.update(_user);   
    44.            
    45.     }   
    46.        
    47.        
    48. }   

    运行测试后,此时会生成完整的SQL语句(注意将hibernate属性show_sql设置成true)。

     
    1. ================testSaveUser=================   
    2. Hibernate: insert into Users (age, firstname, lastname) values (?, ?, ?)   
    3. ================testUpdateUser=================   
    4. Hibernate: insert into Users (age, firstname, lastname) values (?, ?, ?)   
    5. Hibernate: update Users set age=?, firstname=?, lastname=? where ID=?  

    如果我们在<class ...>中加上 dynamic-insert="true" dynamic-update="true",变成如下。

     
    1. <class name="model.User" table="Users" dynamic-insert="true" dynamic-update="true">  

    再次运行测试类,就会发现生成的SQL中涉及的字段只包含User类中修改的属性所对应的表字段。

     
    1. ================testSaveUser=================   
    2. Hibernate: insert into Users (age) values (?)   
    3. ================testUpdateUser=================   
    4. Hibernate: insert into Users (age) values (?)   
    5. Hibernate: update Users set firstname=? where ID=?  

    如果一个表的结构很复杂,字段很多的情况下,使用dynamic-insert,dynamic-update能够性能上的少许提升。

     

    -------------------------------------------

    Hibernate的映射文件中,class元素中可以定义 
    dynamic-update="true|false" 
    dynamic-insert="true|false" 

    dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。 

    dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。 

    请注意dynamic-update和dynamic-insert的设置并不会继承到子类, 所以在<subclass>或者<joined-subclass>元素中可能 需要再次设置。 

    性能问题:SQL update语句是预先生成的,如果加上dynamic的话,每次update的时候需要扫描每个属性的更改,然后生成update,效率会稍微有点影响。 
    如果不是有特殊的需求,默认就好了。 

    如果你一次更新多条记录,hibernate将不能使用executeBatch进行批量更新,这样效率降低很多。同时,在这种情况下,多条sql意味着数据库要做多次sql语句编译。 

    应否使用: 
    具体问题具体分析了,如果一个表字段比较多,并且经常只是更新一条记录的一两个字段,那么动态更新会更有效些。而且生成的SQL语句也容易懂。 

    转自:http://blog.163.com/ma_yaling/blog/static/245367201051854849268/

    相关:

    Hibernate update 只更新被修改字段  

  • 相关阅读:
    LeetCode 295. Find Median from Data Stream (堆)
    LeetCode 292. Nim Game(博弈论)
    《JavaScript 模式》读书笔记(4)— 函数2
    《JavaScript 模式》读书笔记(4)— 函数1
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数3
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数2
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数1
    《JavaScript 模式》读书笔记(2)— 基本技巧3
    《JavaScript 模式》读书笔记(2)— 基本技巧2
    《JavaScript 模式》读书笔记(2)— 基本技巧1
  • 原文地址:https://www.cnblogs.com/langtianya/p/4747239.html
Copyright © 2011-2022 走看看