Hibernate中如何做批量删除

Hibernate中如何做批量删除,第1张

批量删除虽然在hibernate里也可以,但他却是一个一个删除,在数量大的情况下很影响效率,昨天在网站上看到了个更好的方法,原来hibernate也提供了JDBC接口,实在是太方便了。

把他cope过来了:

批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段:

tx = session.beginTransaction()Iterator customers=session.find("from Customer c where c.age>0").iterator()while(customers.hasNext()){Customer customer=(Customer)customers.next()customer.setAge(customer.getAge()+1)}tx.commit()session.close()

如果CUSTOMERS表中有1万条年龄大于零的记录,那么Session的find()方法会一下子加载1万个Customer对象到内存。当执行tx.commit()方法时,会清理缓存,Hibernate执行1万条更新CUSTOMERS表的update语句

update CUSTOMERS set AGE=? …. where ID=iupdate CUSTOMERS set AGE=? …. where ID=j……update CUSTOMERS set AGE=? …. where ID=k

以上批量更新方式有两个缺点:

(1)占用大量内存,必须把1万个Customer对象先加载到内存,然后一一更新它们。

(2)执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必须通过1万条update语句才能更新一万个Customer对象,频繁的访问数据库,会大大降低应用的性能。

为了迅速释放1万个Customer对象占用的内存,可以在更新每个Customer对象后,就调用Session的evict()方法立即释放它的内存:

tx = session.beginTransaction()Iterator customers=session.find("from Customer c where c.age>0").iterator()while(customers.hasNext()){Customer customer=(Customer)customers.next()customer.setAge(customer.getAge()+1)session.flush()session.evict(customer)}tx.commit()session.close()

在以上程序中,修改了一个Customer对象的age属性后,就立即调用Session的flush()方法和evict()方法,flush()方法使Hibernate立刻根据这个Customer对象的状态变化同步更新数据库,从而立即执行相关的update语句;evict()方法用于把这个Customer对象从缓存中清除出去,从而及时释放它占用的内存。

但evict()方法只能稍微提高批量 *** 作的性能,因为不管有没有使用evict()方法,Hibernate都必须执行1万条update语句,才能更新1万个Customer对象,这是影响批量 *** 作性能的重要因素。假如Hibernate能直接执行如下SQL语句:

update CUSTOMERS set AGE=AGE+1 where AGE>0

那么,以上一条update语句就能更新CUSTOMERS表中的1万条记录。但是Hibernate并没有直接提供执行这种update语句的接口。应用程序必须绕过Hibernate API,直接通过JDBC API来执行该SQL语句:

tx = session.beginTransaction()Connection con=session.connection()PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGE=AGE+1 "+"where AGE>0 ")stmt.executeUpdate()tx.commit()

以上程序演示了绕过Hibernate API,直接通过JDBC API访问数据库的过程。应用程序通过Session的connection()方法获得该Session使用的数据库连接,然后通过它创建PreparedStatement对象并执行SQL语句。值得注意的是,应用程序仍然通过Hibernate的Transaction接口来声明事务边界。

如果底层数据库(如Oracle)支持存储过程,也可以通过存储过程来执行批量更新。存储过程直接在数据库中运行,速度更加快。在Oracle数据库中可以定义一个名为batchUpdateCustomer()的存储过程,代码如下:

create or replace procedure batchUpdateCustomer(p_age in number) asbeginupdate CUSTOMERS set AGE=AGE+1 where AGE>p_ageend

以上存储过程有一个参数p_age,代表客户的年龄,应用程序可按照以下方式调用存储过程:

tx = session.beginTransaction()Connection con=session.connection()String procedure = "{call batchUpdateCustomer(?) }"CallableStatement cstmt = con.prepareCall(procedure)cstmt.setInt(1,0)//把年龄参数设为0cstmt.executeUpdate()tx.commit()

从上面程序看出,应用程序也必须绕过Hibernate API,直接通过JDBC API来调用存储过程。

Session的各种重载形式的update()方法都一次只能更新一个对象,而delete()方法的有些重载形式允许以HQL语句作为参数,例如:

session.delete("from Customer c where c.age>0")

如果CUSTOMERS表中有1万条年龄大于零的记录,那么以上代码能删除一万条记录。但是Session的delete()方法并没有执行以下delete语句:

delete from CUSTOMERS where AGE>0

Session的delete()方法先通过以下select语句把1万个Customer对象加载到内存中:

select * from CUSTOMERS where AGE>0

接下来执行一万条delete语句,逐个删除Customer对象:

delete from CUSTOMERS where ID=idelete from CUSTOMERS where ID=j……delete from CUSTOMERS where ID=k

由此可见,直接通过Hibernate API进行批量更新和批量删除都不值得推荐。而直接通过JDBC API执行相关的SQL语句或调用相关的存储过程,是批量更新和批量删除的最佳方式,这两种方式都有以下优点:

(1)无需把数据库中的大批量数据先加载到内存中,然后逐个更新或修改它们,因此不会消耗大量内存。

(2)能在一条SQL语句中更新或删除大批量的数据。

本文是记录Java中实现批量删除 *** 纵(Java对数据库进行事务处置),在开始之前先来看上面这样的一个页面图:

上面这张图片表现的是从数据库中查询出的出租信息,信息中进行了分页处置,然后每行的后面提供了一个复选按钮和对应的一个删除 *** 纵,可以选中多个进行 *** 纵,这里主要是进行删除 *** 纵。在执行删除 *** 纵之前先要选中对应的行信息,点击删除选中按钮进行删除。当进行多条信息删除的时候,需要使用java的事务处置机制对数据库进行删除,也就是说删除的时候如果选中的要删除的说有信息其中一条没有成功删除的话,那么就都不删除。

现在是在java中对数据库实现这一 *** 纵,我们可看上面的代码,它实现了对数据库的批量删除 *** 纵,代码如下:

public Connection con=null

public PreparedStatement pstmt=null

/**

* 失掉连接对象

*/

public void getConnection(){

String driver="com.mysql.jdbc.Driver"

String url="jdbc:mysql://localhost:3306/zufang?user=root&password=root&useUnicode=true&characterEncoding=GB2312"

try {

Class.forName(driver)

con=DriverManager.getConnection(url,"root","root")

} catch (ClassNotFoundException e) {

e.printStackTrace()

} catch (SQLException e) {

e.printStackTrace()

}

}

/** * 批量删除信息表中的信息 * @param sql * @param param * @return */ public boolean updateBatchDel(String sql,String[] param){ boolean flag = falsegetConnection()try { con.setAutoCommit(false)pstmt = con.prepareStatement(sql)for(int i =0 i<param.lengthi++){ pstmt.setString(1,param[i].trim())pstmt.addBatch()} pstmt.executeBatch()//批量执行 con.commit()//提交事务 flag = true} catch (SQLException e) { try { con.rollback()//进行事务回滚 } catch (SQLException ex) { ex.printStackTrace()} }finally { closeAll(null,pstmt,con)} return flag}

当然上面是进行批量删除,如果我们只删除一条信息的话也可以使用独自的删除方法,即是:点击删除,当然上面的方法也是可以完成的,还是再看一下吧:

/**

* 删除某条求租表中的信息

* @param id 删除信息的id

* @return 如果删除成功,返回true否则返回false

*/

public boolean delQiuZu(String id){

boolean flag=false

String sql="delete from qiuzhu where id=?"

String[] param={id}

flag=bd.updateDate(sql, param)

return flag

}

控制器servlet中的处置 *** 纵代码如下:

package com.sxt.servlet

import java.io.IOException

import java.io.PrintWriter

import java.util.List

import javax.servlet.ServletException

import javax.servlet.http.HttpServlet

import javax.servlet.http.HttpServletRequest

import javax.servlet.http.HttpServletResponse

import com.sxt.biz.ChuZuBiz

import com.sxt.biz.PageBiz

import com.sxt.biz.QiuZuBiz

public class OutDateQiuzuServlet extends HttpServlet {

QiuZuBiz qzb=new QiuZuBiz()

PageBiz pb=new PageBiz()

int pagesize=10

boolean flag=true

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

request.setCharacterEncoding("gb2312")

response.setContentType("text/htmlcharset=gb2312")

int countpage=pb.getOutDatePageCountQiuzu(pagesize)

request.setAttribute("countpage", countpage)

String nowpage=request.getParameter("nowpage")

String id=request.getParameter("id")

PrintWriter out = response.getWriter()

String command = request.getParameter("command")

   if ("del".equals(command)) {  

       String[] qiuzuIds = request.getParameterValues("selectFlag")

       boolean flag = qzb.delQiuzuMany(qiuzuIds)

       if(flag){  

           out.print("<script>alert('删除成功!')</script>") 

       }else{  

           out.print("<script>alert('删除失败!')</script>") 

       }  

   }  

if(nowpage==null){

nowpage="1"

}

if(Integer.valueOf(nowpage)<=0){

nowpage="1"

}

if(Integer.valueOf(nowpage)>countpage){

nowpage=countpage+""

}

if(id!=null){

flag=qzb.delQiuZu(id)

}

request.setAttribute("currentpage", nowpage)

List list=qzb.getOutDateQiuZuInfo(Integer.valueOf(nowpage), pagesize)

request.setAttribute("list1", list)

if(flag){

request.getRequestDispatcher("admin/OutDateQiuzu.jsp").forward(request, response)

}

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request,response)

}

}

上面是对数据库的 *** 纵代码,上面看一下页面中怎样实现的,代码如下:

每日一道理 

灯,带有一种明亮的光,每当深夜来临,是它陪伴着你,如此默默无闻。它是平凡的,外表华丽与否,那都是一样的,珍珠点缀,水晶加饰的灯它只能用以装饰,来满足人们的虚荣心,比起这,普普通通的日光灯是幸运的,因为它照明的本性没有改变,如同生活中的一部分人平平凡凡却实实在在。

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

<%@ taglib uri="#"  prefix="c" %>

<html>

 <head>

  <title>house</title>

  <script type="text/javascript">

  //删除用户控制  

   function deleteSelect() {  

       var select  = document.getElementsByName("selectFlag") 

       var flag = false 

       for (var i=0i<select.lengthi++) {  

           if (select[i].checked) {  

               flag = true 

               break 

           }  

       }  

       if (!flag) {

        alert("请选择需要删除的过期求租信息!") 

           return 

       }  

       if (window.confirm("确认要删除过期的求租信息吗?")) {  

           with (document.getElementById("userform")) {  

               action="OutDateQiuzuServlet?command=del" 

               method="post" 

               submit() 

           }  

       }  

   }

   

   //全选/反选 *** 纵    

   function checkAll(ifAll) {

    var select = document.getElementsByName("selectFlag") 

           for(var i = 0i<select.lengthi++){  

               select[i].checked = ifAll.checked 

           }      

   }

   </script>

 </head>

 <link rel="stylesheet" href="./skin/css/lianjie.css" type="text/css" />

 <body>

  <form name="userform" action="ChuzuServlet" method="get">

  <table width="1000" height="80" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC">

  <tr>

  <td height="40" align="center" bgcolor="#F1F1F1"><font color="#FF0000"><b>已过期的求租信息</b></font></td>

  </tr>

  <tr>

  <td align="left">

      <input name="btnDelete" class="button1" type="button"  

           id="btnDelete" value="删除选中" onClick="deleteSelect()"> 

  </td>

  </tr>

  </table>

    <table width="1000" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC" style="word-break:break-all">

    <tr align="center">

    <td width="15%" height="25" bgcolor="#F1F1F1"><font size="3"> <input type="checkbox" name="ifAll" title="全选/反选"  onClick="checkAll(this)" checked="checked"/></font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">期望区域</font></td>

    <td width="15%" bgcolor="#F1F1F1"><font size="3">装修水平</font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">房型</font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">面积(平米)</font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">价格(元)</font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">添加日期</font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">有效天数</font></td>

    <td width="10%" bgcolor="#F1F1F1"><font size="3">残余天数</font></td>

    </tr>

    <c:choose>

<c:when test="${empty list1}">

<tr><td colspan="8" align="center"><font color="red">还没有过期的求租信息!</font></td></tr>

</c:when>

<c:otherwise>

    <c:forEach var="qiuzu" items="${list1}" >

    <tr>

    <td height="25" align="center" bgcolor="#FFFFFF"><input type="checkbox" name="selectFlag" value="${qiuzu.id}" checked="checked"/></font>

     <a href="javascript:if(confirm('确定要删除这条过期的求租信息吗?')){location.href='OutDateQiuzuServlet?id=${qiuzu.id}'}" style="COLOR: #0000fffont-size:14pxTEXT-DECORATION:none"><font size="2">删除</font></a></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.qwqy}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.zxcd}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.hx}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.jzmj}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.zj}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.addDate}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2">${qiuzu.yxts}</font></td>

    <td align="center" bgcolor="#FFFFFF"><font size="2" color="red">${qiuzu.syts}</font></td>

   

    </tr>

    </c:forEach>

    </c:otherwise>

</c:choose>

    </table>

    </p>

    <table width="300" align="center" >

    <tr>

    <td align="center"><font size="2">共${countpage}页</font></td>

    <td align="center"><font size="2">${currentpage}/${countpage}页</font></td>

    <td align="center"><a href="OutDateQiuzuServlet?nowpage=${1}"><font size="2">首页</font></a></td>

    <td align="center"><a href="OutDateQiuzuServlet?nowpage=${currentpage-1}"><font size="2">上一页</font></a></td>

    <td align="center"><a href="OutDateQiuzuServlet?nowpage=${currentpage+1}"><font size="2">下一页</font></a></td>

    <td align="center"><a href="OutDateQiuzuServlet?nowpage=${countpage}"><font size="2">尾页</font></a></td>

    </tr>

    </table>

    </form>

  </body>

</html>

/*

怎么用java同时实现批量删除,批量修改?

*/

//1,可以利用循环批量来 *** 作数组元素

int arr[] = new int[100]//定义一个数组,长度为100

//对该数组进行批量赋值

for (int i = 0i <arr.lengthi++) {

arr[i] = i

}

//2,对于集合,可以使用removeALL方法进行批量删除

List<String>list = new ArrayList<String>()

list.add("1")

list.add("2")

list.add("3")

list.add("4")

list.add("5")

list.removeAll(list)

System.out.println(list)

//这上是java自带的一些方法

//3,JDBC

/**

* 对于数据库的 *** 作,就需要用SQL语言来批量处理了;

* 比如:select *from EMP

*

* 利用JDBC的一些方法,比如预处理命令,可以对数据库进行批量 *** 作,

*/


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/9775938.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存