在咱們作.net系統的時候,所作的最多見的批量操做就是批量導入、插入、更新、刪除等等,之前咱們怎麼作呢?基本上有如下幾種方式:html
一、利用循環調用insert方法,一條條插入。java
- public boolean insertStudent(List<Student> studentList)
- {
- try{
- if(studentList.count !=0){
- for(int i=0;i<studentList.count;i++){
-
- }
- return true;
- }
- }catch(Exception ex){
- throw New Exception("插入失敗,請重試!")
- return false;
- }
- }
二、利用循環作sql語句拼接,而後批量執行sql語句。mysql
- public boolean insertStudent(List<Student> studentList)
- {
- try{
- if(studentList.count !=0){
- stringBuffer strSqltxt="";
- for(int i=0;i<studentList.count;i++){
- strSqltxt.append("insert into TableName (……) values (……);"
- }
- cmd.executesql(strSqltxt.toString());
- }
- }catch(Exception ex){
- throw New Exception("插入失敗,請重試!")
- return false;
- }
- }
但是,對於封裝比較完善的hibernate持久層,咱們又能怎麼作呢?web
最多見的,也是利用循環來批量操做,可是,這裏有一個必需要注意的點,就是緩存或者說是session區的空間是有限的,禁不起咱們無限制的存放,因此,當咱們執行如下操做時,會拋異常,內存溢出OutOfMemoryException!sql
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- for ( int i=0; i<100000; i++ ) {
- Customer customer = new Customer(.....);
- session.save(customer);
- }
- tx.commit();
- session.close();
這樣是不能夠的,可是在這時,hibernate也給咱們提供瞭解決方法,就是咱們能夠經過設置JDBC的批量抓去數量參數(batch size)來設置一個合適的值,好比說10-50-100不等,配置:數據庫
- <span style="font-size:18px;"><property name="hibernate.jdbc.batch_size">100</property></span>
另外,咱們還能夠顯示的禁用二級緩存,之前咱們也提到過:緩存
<property name="hibernate.cache.use_second_level_cache">false</property>session
正確代碼:app
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- for ( int i=0; i<100000; i++ ) {
- Customer customer = new Customer(.....);
- session.save(customer);
- if(i%100==0){
- session.fulsh();
- session.clear();
- }
- }
- tx.commit();
- session.close();
這樣就能解決咱們的那個內存溢出的問題,由於當你的存儲對象數超過你設定的能接受的合理值的時候,程序會自動將持久化對象flush進數據緩存起來,而後清空session,進行下一輪存儲,待全部數據所有完成,執行commit進行提交,數據庫更新數據,說的簡單,這樣的效率是不咋地的,不信你能夠試試,你想一想,先發出sql,100一輪,執行1000輪用來緩存sql語句,而後數據庫統一執行sql,時間啊!less
StatelessSession(無狀態session)接口
可是這不是問題,由於hibernate還給咱們提供了一個StatelessSession(無狀態session)接口,做爲選擇,Hibernate提供了基於命令的API:
一、能夠用detached object(託管對象)的形式把數據以流的方法加入到數據庫,或從數據庫輸出。
二、StatelessSession沒有持久化上下文,也不提供多少高層的生命週期語義。
三、無狀態session不實現第一級cache;
四、也不和第二級緩存交互,也不和查詢緩存交互。
五、它不實現事務化寫,也不實現髒數據檢查。
六、用stateless session進行的操做甚至不級聯到關聯實例。
七、stateless session忽略集合類(Collections)。
八、經過stateless session進行的操做不觸發Hibernate的事件模型和攔截器。
九、無狀態session對數據的混淆現象免疫,由於它沒有第一級緩存。
十、無狀態session是低層的抽象,和低層JDBC至關接近。換句話說,它能夠直接操做數據。
- StatelessSession session = sessionFactory.openStatelessSession();
- Transaction tx = session.beginTransaction();
-
- ScrollableResults customers = session.getNamedQuery("GetCustomers")
- .scroll(ScrollMode.FORWARD_ONLY);
- while ( customers.next() ) {
- Customer customer = (Customer) customers.get(0);
- customer.updateStuff(...);
- session.update(customer);
- }
-
- tx.commit();
- session.close();
DML(Data Manipulation Language數據操做語言)風格操做
再有就是特殊服務(業務需求)須要咱們採用DML(Data Manipulation Language數據操做語言)風格操做,從一張表導入另外一張表數據,比方說從學生表(T_Studeng)裏面往大三學生表(T_ThreeStudent)裏面倒數據.
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
-
- String hqlInsert = "insert into ThreeStudent(id, name) select s.id, s.name from Student s where ...";
- int createdEntities = s.createQuery( hqlInsert )
- .executeUpdate();
- tx.commit();
- session.close();
以上就是對批量操做的一點總結,萬望對你們能有點幫助