`
还有也许
  • 浏览: 169286 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

Hibernate处理大数据量的问题初探

阅读更多

 

解决数据量大的问题我觉得最主要的有两点:
1、即使清理缓存
在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,所以在使用Hibernate处理大数据量的,可以使用session.clear()或者session. evict(Object) 在处理过程中,清除全部的缓存或者清除某个对象。
2、减少与数据库的交互次数
对于大数据量新增、修改、删除操作或者是对大数据量的查询,与数据库的交互次数是决定处理时间的最重要因素,减少交互的次数是提升效率的最好途径。 
在Hibernate的配置文件中有一项hibernate.jdbc.batch_size
Hibernate提供了配置参数来设置JDBC的批处理操作的大小。但并不是说这个数值越大就越好。一般设为30,50就够了,至于这个参数的性能问题,找了许久也没人能说出个大概。这里不做讨论。
如果启用了二级缓存,从机制上讲Hibernate为了维护二级缓存,我们在做插入、更新、删除操作时,Hibernate都会往二级缓存充入相应的数据。性能上就会有很大损失,所以笔者建议在批处理情况下禁用二级缓存。
将use_second_level_cache=false;
接着就熟悉的代码坐下解释。
public ModelAndView saveImport(HttpServletRequest request
    ,HttpServletResponse response) {
   String fileName = StringUtils.varFormat(request.getParameter("fileName"));
   boolean successful = true;
   if (fileName.equals("")) {
    request.setAttribute("mesage", this.MSG_NO_DATA_FOUND);
    return new ModelAndView(this.failView);
   }
   Map formatMap = new HashMap();
   int i=0;
   formatMap.put(i++, "customerName");
   formatMap.put(i++, "customerSex");
   formatMap.put(i++, "phoneNo");
   formatMap.put(i++, "categoryName");
   formatMap.put(i++, "cardType");
   formatMap.put(i++, "cardId");
   //添加2010-03-31

   formatMap.put(i++,"customerCorp");
   formatMap.put(i++,"homeAddr");
   formatMap.put(i++,"customerJoy");
   List data = ExcelUtils.importExcel(fileName, formatMap, true);//包含标题
   if (data.size() == 0) {
    request.setAttribute("mesage", this.MSG_NO_DATA_FOUND);
    return new ModelAndView(this.failView);
   }
   //定义手机集合,判断导入的数据是否重复
   StringBuffer phoneNos=new StringBuffer();
   //定义客户类型集合,避免每次查询,节约时间
   StringBuffer types=new StringBuffer();
   //开启事务
   Session session = customerDao.openSession();
   Transaction tx = session.beginTransaction();
   tx.begin();
   //定义循环因素
   int num=1;

   //获得公司部门Id与实体,节省时间
   int corpSid=this.staff.getCompany().getCorpSid();
   String deptSid=this.staff.getDepartment().getDepartmentSid();
   Company company=this.staff.getCompany();
   Department department=this.staff.getDepartment();
   //导入数据
    try{
     //将客户类型从数据库中拿出来放入List中,以后有用到客户类型表的时候就不用在从数据库中去取了,减少数据库访问的次数。这点很重要。
     CustomerCategory category = new CustomerCategory();
     List<CustomerCategory> categoryList=customerCategoryDao.createQuery("from CustomerCategory t WHERE " +
       "t.department.departmentSid='"+deptSid+"' and t.company.corpSid="+corpSid).list();

   for (Map map : (List<Map>)data) {
      String customerName = StringUtils.varFormat(String.valueOf(map.get("customerName")));
      String categoryName = StringUtils.varFormat(String.valueOf(map.get("categoryName")));
      String sex = StringUtils.varFormat(String.valueOf(map.get("customerSex")));
     String phoneNo = StringUtils.varFormat(String.valueOf(map.get("phoneNo")));
     String cardType = StringUtils.varFormat(String.valueOf(map.get("cardType")));
     String cardId = StringUtils.varFormat(String.valueOf(map.get("cardId")));
     String customerCorp=StringUtils.varFormat(String.valueOf(map.get("customerCorp")));
     String homeAddr=StringUtils.varFormat(String.valueOf(map.get("homeAddr")));
     String customerJoy=StringUtils.varFormat(String.valueOf(map.get("customerJoy")));

     int index=phoneNos.indexOf(phoneNo);
     //判断导入的手机号码自身有没有重复
     if(index!=-1){
      continue;
     }
     phoneNos.append(phoneNo+",");
     //判断手机号码长度
     if((!("".equals(phoneNo)))&& (phoneNo.length()==11||phoneNo.length()==7||phoneNo.length()==8)) {

     String sql;
     sql="select * from customer  where phone_no='"+phoneNo+"' and dept_sid_fk='"+deptSid+"' and corp_sid_fk="+corpSid;
     //在此我用了session.createSQLQuery(sql).list(),而不是customerDao.find(hql),避免了数据从数据库中查出来以后,封装成对象的过程。不过这样会带来一个数据对象转换的问题,可以对比下边的一处代码,那个地方我还是用了hql.
     List<Customer> customers=session.createSQLQuery(sql).list();
     if(customers.size()==0){

      Customer customer = new Customer();
      customer.setCustomerSex(sex);
      customer.setPhoneNo(phoneNo);
      customer.setCompany(company);
      customer.setDepartment(department);
      customer.setCardType(cardType);
      customer.setCardId(cardId);
      customer.setSmsConfirmState("N");
      customer.setCustomerCorp(customerCorp);
      customer.setHomeAddr(homeAddr);
      customer.setCustomerJoy(customerJoy);
      if ("".equals(customerName)) {
       customerName = "--UNNAMED--";
      }
      customer.setCustomerName(customerName);

      if (!("".equals(categoryName))) {//指定分类
       //这里就是我为什么要定义一个StringBuffer类型的types的原因,当前面已经执行过相同客户类型的操作时,就可以完全的跳过index_type==-1中的操作,减少数据库的访问。
       int index_type=types.indexOf(categoryName);

       if(index_type==-1){
        //这里用了session.createQuery(hql).list().而不是session.createSQLQuery(sql).list(),因为这样会在category=categoryList.get(m);时报类型转换异常。
        List<CustomerCategory> categorys = session.createQuery("from CustomerCategory t WHERE t.department.departmentSid='"+deptSid+"' AND t.categoryName='"+StringUtils.sqlFormat(categoryName)+"'").list();

        if (categorys.size() == 0) {
         category = new CustomerCategory();
         category.setCategoryName(categoryName);
         category.setCompany(company);
         category.setDepartment(department);
         category.setCreateDate(new Date());

         customerCategoryDao.save(category);

        }else{

         category=categorys.get(0);
        }
        types.append(categoryName+",");
       }else{
        for(int m=0;m<categoryList.size();m++){
         if(categoryList.get(m).getCategoryName().equals(categoryName)){
          category=categoryList.get(m);
         }
        }

       }
       //前边的if...else都是为了得到category对象。
       customer.setCustomerCategory(category);

      }
      customer.setCreateDate(new Date());
      session.save(customer);
      //此处很重要,这就是在前便提到的及时清除session中的缓存的地方,当数量达到40时及时清除,和batch_size数值对应。
      if(num%40==0){
       session.flush();
       session.clear();
         }

        }
     }
      num++;
    }
    }catch(Exception e){
      e.printStackTrace();
      tx.rollback();
      successful=false;

    }

    if (successful) {

     tx.commit();
     session.close();
     request.setAttribute("message", this.MSG_SUCCESS);
     request.setAttribute("redirectUrl", this.requestUri+".do?method=list");
     return new ModelAndView(this.successView);
    } else {
     session.close();
     request.setAttribute("message", this.MSG_FAIL);
     return new ModelAndView(this.failView);
    }

   }

 

分享到:
评论

相关推荐

    pring初探共18页.pdf.zip

    10. **Spring Batch**:处理批量操作的模块,适用于大数据量的读写,如日志处理、数据迁移等任务。 11. **Spring Cloud**:在分布式系统中提供服务发现、配置中心、断路器、智能路由等功能,构建微服务架构。 这个...

    SQL注入初探,实例

    5. **使用ORM(对象关系映射)**:如Hibernate或Entity Framework,它们可以自动处理SQL语句,降低注入风险。 6. **代码审计和更新**:定期检查代码中可能存在的SQL注入漏洞,并及时修复已知的安全问题。 7. **...

    javaeye热点阅读

    12. 大数问题的解决:大数运算在某些场景下是必须的,文中介绍了如何处理Java中的大数计算问题。 13. Excel Report:这是一个基于Java实现的轻量级Excel报表生成工具,适合快速生成和导出数据报表。 14. Spring与...

    2.spring_beginning

    Spring通过DI解决了这一问题,使得对象间的依赖关系可以通过配置文件或注解来管理,极大地提高了代码的灵活性和可维护性。 其次,Spring的另一大特色是面向切面编程(Aspect-Oriented Programming,简称AOP)。AOP...

    Nhibernate从入门到精通

    - **应用场景**:NHibernate特别适用于那些基于.NET平台并能够实现面向对象业务模型的应用,它可以极大地提高开发效率,尤其是在处理大量数据时。 #### 二、对象/关系映射(ORM) **对象-关系映射(ORM)**是随着...

    JSF资料以及深入开发

    **JSF_Hibernate_Spring构建WEB应用.pdf** 这份教程很可能讲解了如何将JSF与两个流行的Java开发框架——Hibernate(对象关系映射工具)和Spring(轻量级容器)——结合使用,构建复杂的Web应用程序。这涉及到数据...

    课程设计RoubSite是一个简单、轻量、易上手的java web开发框架.zip

    模型(Model)负责处理数据,视图(View)负责展示数据,控制器(Controller)负责协调模型和视图之间的交互。RoubSite提供了一套易于理解的API,使得开发者可以轻松创建和管理这些组件。 ### 3. URL映射与路由 ...

    Struts2讲义-作者:吴峻申

    - 第一代Struts(Struts 1)采用MVC设计模式,将业务逻辑与视图分离,极大地简化了Web应用的开发过程。 - 随着Web应用需求的不断增长和技术的发展,第一代Struts逐渐显露出一些不足之处,如强耦合性等。 - 为了...

    java学习之spring2.0

    - **Spring 初探**:Spring的核心在于依赖注入(DI)和面向切面编程(AOP),提供了一个轻量级的容器来管理对象的生命周期和相互依赖关系。 - **Spring 体系**:包括Core Container(核心容器)、Data Access/...

    NHibernate之旅

    3. **Transaction**:处理事务管理,确保数据的一致性和完整性。 4. **Query**:用于执行各种类型的查询,包括HQL(Hibernate Query Language)和Criteria API。 5. **Configuration**:配置NHibernate的行为,如...

    eapp-corp-quick-start-java_后台_

    1. **模块化设计**:eapp-corp-quick-start-java采用模块化的设计思想,将系统拆分为多个独立的模块,如用户管理、权限控制、数据处理等,每个模块都有清晰的职责划分,易于维护和扩展。这样的设计思路符合现代软件...

    JEECG_v3开发指南v3.3

    - **数据过滤现状分析**:分析了当前数据过滤中存在的问题及挑战。 - **查询条件SQL生成器**: - **实现原理**:阐述了查询条件SQL生成器的工作原理。 - **查询规则**:说明了如何定义查询条件以及遵循的规则。 -...

Global site tag (gtag.js) - Google Analytics