解决数据量大的问题我觉得最主要的有两点:
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);
}
}
分享到:
相关推荐
10. **Spring Batch**:处理批量操作的模块,适用于大数据量的读写,如日志处理、数据迁移等任务。 11. **Spring Cloud**:在分布式系统中提供服务发现、配置中心、断路器、智能路由等功能,构建微服务架构。 这个...
5. **使用ORM(对象关系映射)**:如Hibernate或Entity Framework,它们可以自动处理SQL语句,降低注入风险。 6. **代码审计和更新**:定期检查代码中可能存在的SQL注入漏洞,并及时修复已知的安全问题。 7. **...
12. 大数问题的解决:大数运算在某些场景下是必须的,文中介绍了如何处理Java中的大数计算问题。 13. Excel Report:这是一个基于Java实现的轻量级Excel报表生成工具,适合快速生成和导出数据报表。 14. Spring与...
Spring通过DI解决了这一问题,使得对象间的依赖关系可以通过配置文件或注解来管理,极大地提高了代码的灵活性和可维护性。 其次,Spring的另一大特色是面向切面编程(Aspect-Oriented Programming,简称AOP)。AOP...
- **应用场景**:NHibernate特别适用于那些基于.NET平台并能够实现面向对象业务模型的应用,它可以极大地提高开发效率,尤其是在处理大量数据时。 #### 二、对象/关系映射(ORM) **对象-关系映射(ORM)**是随着...
**JSF_Hibernate_Spring构建WEB应用.pdf** 这份教程很可能讲解了如何将JSF与两个流行的Java开发框架——Hibernate(对象关系映射工具)和Spring(轻量级容器)——结合使用,构建复杂的Web应用程序。这涉及到数据...
模型(Model)负责处理数据,视图(View)负责展示数据,控制器(Controller)负责协调模型和视图之间的交互。RoubSite提供了一套易于理解的API,使得开发者可以轻松创建和管理这些组件。 ### 3. URL映射与路由 ...
- 第一代Struts(Struts 1)采用MVC设计模式,将业务逻辑与视图分离,极大地简化了Web应用的开发过程。 - 随着Web应用需求的不断增长和技术的发展,第一代Struts逐渐显露出一些不足之处,如强耦合性等。 - 为了...
- **Spring 初探**:Spring的核心在于依赖注入(DI)和面向切面编程(AOP),提供了一个轻量级的容器来管理对象的生命周期和相互依赖关系。 - **Spring 体系**:包括Core Container(核心容器)、Data Access/...
3. **Transaction**:处理事务管理,确保数据的一致性和完整性。 4. **Query**:用于执行各种类型的查询,包括HQL(Hibernate Query Language)和Criteria API。 5. **Configuration**:配置NHibernate的行为,如...
1. **模块化设计**:eapp-corp-quick-start-java采用模块化的设计思想,将系统拆分为多个独立的模块,如用户管理、权限控制、数据处理等,每个模块都有清晰的职责划分,易于维护和扩展。这样的设计思路符合现代软件...
- **数据过滤现状分析**:分析了当前数据过滤中存在的问题及挑战。 - **查询条件SQL生成器**: - **实现原理**:阐述了查询条件SQL生成器的工作原理。 - **查询规则**:说明了如何定义查询条件以及遵循的规则。 -...