博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Hibernate SQL优化技巧dynamic-insert="true" dynamic-update="true"
阅读量:6815 次
发布时间:2019-06-26

本文共 3350 字,大约阅读时间需要 11 分钟。

最近正在拜读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://ipbzl.baihongyu.com/

你可能感兴趣的文章
Go结构体标签表达式v1.0发布,参数校验杀手锏
查看>>
对react中setState的总结
查看>>
[回炉计划]-实现一个图片预加载
查看>>
正则表达式
查看>>
360前端星计划学习-html
查看>>
专注dApp高效执行和高并发的下一代公有链
查看>>
ONE-sys 整合前后端脚手架 koa2 + pm2 + vue-cli3.0 + element
查看>>
携带更方便功能全 iPone与Apple Watch球形尿袋
查看>>
行为型模式:策略模式
查看>>
实现批量数据增强 | keras ImageDataGenerator使用
查看>>
太忙女友消息未及时回复,分手吗?python微信自动消息帮你谈恋爱
查看>>
Java 多线程NIO学习
查看>>
命名实体识别
查看>>
动态切换的动态代理
查看>>
电商项目(下)
查看>>
vue 数字滚动递增效果
查看>>
vue2.0中父子,兄弟组件的传值2
查看>>
Spring Boot注解常用!!!看了就可以开发大量项目了
查看>>
音频编码 Audio Converter
查看>>
SQL - case when then else end 的用法
查看>>