• 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 只更新被修改字段  

  • 相关阅读:
    通信专业术语解释
    STM32F10系列管脚设置
    [笔试题]使用回调函数编写冒泡排序,可以排序整形数组,也可以排序字符串
    Date常用转换、比较
    哈希映射
    APP技巧格式
    $.get/$.post/$.ajax/$.getJSON
    使用Rss框架PHP开发流程
    测试rss与navicat连接
    验证码技术
  • 原文地址:https://www.cnblogs.com/langtianya/p/4747239.html
Copyright © 2020-2023  润新知