`
lettoo
  • 浏览: 34325 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
博客专栏
58ccff5b-5ca6-387a-9c99-a277f31a9e51
我和Java数据库操作的那...
浏览量:9315
社区版块
存档分类
最新评论

我和JAVA数据库操作的那些事儿(2)

阅读更多
摘要 写道
上一篇提到的几个问题,在本篇有具体的代码。本篇后半段主要是说批处理,以及如何确定批处理的batchSize。
本博客所有源代码都可以通过Git来checkout,地址是这里:https://github.com/lettoo/LettooJava
 

    在上一篇《我和JAVA数据库操作的那些事儿(1) 》中,采用纯JDBC编程我经历过的一些问题,主要有:

  • 连接重复创建
  • 资源需要注意释放
  • sql和代码在一起
  • 重复性的创建Statement, ResultSet代码多

 

    根据以前的做法,基本上都有一些解决方法

  • 把连接放在一个对象里,并不每次都重复创建
  • 用try{}finally{}调用写的工具类方法来关闭资源并释放
  • 把sql移到配置文件中,并通过PreparedStatement来setString, setInt等方法来给sql传参
  • 写一些函数来封装重复的代码

    上次已经写过了部门表的增删除改查并进行了对上面几个问题的解决,如下:

package cn.lettoo.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DepartmentDB {

	// 增
	public void addDepartment(Connection conn, Department dept)
	        throws SQLException {
		PreparedStatement stmt = null;
		try {
			// SqlParser读取sql.xml文件
			String sql = SqlParser.getInstance().getSql("Department.insert");
			stmt = conn.prepareStatement(sql);
			stmt.setInt(1, dept.getId());
			stmt.setString(2, dept.getName());
			stmt.setString(3, dept.getDescription());
			stmt.execute();
		} finally {
			DBUtil.close(stmt);
			DBUtil.close(conn);
		}
	}

	// 删
	public void deleteDepartment(Connection conn, Department dept)
	        throws SQLException {
		PreparedStatement stmt = null;
		try {
			String sql = SqlParser.getInstance().getSql("Department.delete");
			stmt = conn.prepareStatement(sql);
			stmt.setInt(1, dept.getId());
			stmt.execute();
		} finally {
			DBUtil.close(stmt);
			DBUtil.close(conn);
		}
	}

	// 改
	public void updateDepartment(Connection conn, Department dept)
	        throws SQLException {
		PreparedStatement stmt = null;
		try {
			String sql = SqlParser.getInstance().getSql("Department.update");
			stmt = conn.prepareStatement(sql);
			stmt.setString(1, dept.getName());
			stmt.setString(2, dept.getDescription());
			stmt.setInt(3, dept.getId());
			stmt.execute();
		} finally {
			DBUtil.close(stmt);
			DBUtil.close(conn);
		}
	}

	// 查
	public List<Department> selectDepartment(Connection conn, int id)
	        throws SQLException {
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			String sql = SqlParser.getInstance().getSql("Department.select");
			stmt = conn.prepareStatement(sql);
			stmt.setInt(1, id);
			rs = stmt.executeQuery();
			List<Department> deptList = new ArrayList<Department>();

			while (rs.next()) {
				Department dept = new Department();
				dept.setId(rs.getInt("ID"));
				dept.setName(rs.getString("NAME"));
				dept.setDescription(rs.getString("DESCRIPTION"));
				deptList.add(dept);
			}

			return deptList;
		} finally {
			DBUtil.close(rs);
			DBUtil.close(stmt);
			DBUtil.close(conn);
		}
	}
}

    sql语句放在sql.xml里,定义如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<!DOCTYPE sql_template>
<sqltemplate xmlns="cn.lettoo">
	<sql name="Department.insert">
		<content><![CDATA[
		INSERT INTO DEPARTMENT(ID, NAME, DESCRIPTION) VALUES (?, ?, ?)
		]]></content>
	</sql>

	<sql name="Department.delete">
		<content><![CDATA[
		DELETE FROM DEPARTMENT WHERE ID = ?
		]]></content>
	</sql>

	<sql name="Department.update">
		<content><![CDATA[
		UPDATE DEPARTMENT SET NAME = ?, DESCRIPTION = ? WHERE ID = ?
		]]></content>
	</sql>

	<sql name="Department.select">
		<content><![CDATA[
		SELECT ID, NAME, DESCRIPTION FROM DEPARTMENT WHERE ID = ?
		]]></content>
	</sql>

</sqltemplate>

 

 

    时间一长,基本上就顺手了,也不觉得有什么。接下来,我们还需要实现

  • 批处理提交

    接下来,我们看看批处理。假如我有很多的Employee需要提交到数据库,如果一条条的提交,性能肯定是比较差的,这时就需要批处理。

package cn.lettoo.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

public class EmployeeDB {

	public void addEmployees(Connection conn, List<Employee> empList, int batchSize)
	        throws SQLException {
		long bt = System.currentTimeMillis();
		PreparedStatement stmt = null;
		try {
			String sql = SqlParser.getInstance().getSql("Employee.insert");
			stmt = conn.prepareStatement(sql);
			int count = 0;
			for (Employee emp : empList) {
				stmt.setInt(1, emp.getId());
				stmt.setString(2, emp.getName());
				stmt.setInt(3, emp.getDepartment().getId());
				stmt.setString(4, emp.getDescription());
				stmt.addBatch();
				
				count++;				
				if (count % batchSize == 0) {
					stmt.executeBatch();
				}
			}
			
			stmt.executeBatch();

		} finally {
			long et = System.currentTimeMillis();
			System.out.println(String.format("用时%dms", et-bt));
			DBUtil.close(stmt);
			DBUtil.close(conn);
		}
	}
}

通过stmt.addBatch()和stmt.executeBatch()来往批处理增加和提交一批。我做个测试,针对1000个 Employee数据,分别使用5条,10条,50条,100条来批处理一次,查看时间如下:

运行时间
5条:用时22740ms
10条:用时16109ms
50条:用时9314ms
100条:用时8723ms

 

    可以看到,不同的batchCount对于性能是不一样的。一般来说,批处理的性能和不同的数据库相关,和批处理的条数也相关,并不是batchSize 越大越好。batchSize的设置一般要靠经验和测试结果来决定。

 

分享到:
评论
2 楼 a_nuo 2011-10-26  
楼主写的东西确实很实在
巩固一下基础
1 楼 java_lyvee 2011-10-26  
支持下楼主,觉得楼主写的东西不浮夸,很实在

相关推荐

    数据库连接池的实现java

    数据库连接池可以通过配置服务器容器的server.xml实现,也可以用中间件来完成相应的功能,这是一个用java实现的数据库连接池功能

    「Java面试那些事儿」所涉及的面试题目及相应代码.zip

    【一线互联网大厂Java核心面试题库】Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等..

    Java gui简单程序

    简单的gui界面 包含数据库驱动 连接数据库 查询 Jtable的使用和显示数据大家可以下载查看 如有问题请互相学习

    说说Java生态圈的那些事儿

    1. 哪个项目能离开网络,数据库,操作系统来运行?所以生态圈的应用技术主要在这些知识点处。  2. Java组件,组件其实是一个应用程序块 但是它们不是完整的应用程序,不能单独运行。有如一辆汽车,车门是一个组件...

    【Java面试+Java后端技术学习指南】

    【Java面试+Java后端技术学习指南】:一份通向理想互联网公司的面试指南,包括 Java,技术面试必备基础知识、Leetcode、计算机操作系统、计算机网络、系统设计、分布式、数据库(MySQL、Redis)、Java 项目实战等 ...

    开源! 用于生成 .java 源文件的 Java API

    源文件生成在执行注释处理或与元数据文件(例如数据库模式、协议格式)交互等操作时非常有用。通过生成代码,您无需编写样板文件,同时还可以保留元数据的单一事实来源。 例子 这是一个(无聊的)HelloWorld课程: ...

    java文集

    ext学习笔记一 小试iBatis RIA(Rich Internet Application)的现状和未来 Java应用中域名解析不过期的解决方法 Java编程那些事儿45—数组使用示例1 一步步熟悉OFBiz 用Java做客户端调用.NET写...

    2021互联网大厂Java架构师面试题突击视频教程

    27_如何保证缓存与数据库双写时的数据一致性? 28_你能说说redis的并发竞争问题该如何解决吗? 29_你们公司生产环境的redis集群的部署架构是什么样的? 30_分布式缓存相关面试题的回答技巧总结 31_体验一下面试官...

    Java资源大全中文版,包括开发库、开发工具、网站、博客、微信、微博等,由伯乐在线持续更新

    awesome-java 就是 akullpp 发起维护的 Java 资源列表,内容包括:构建工具、数据库、框架、模板、安全、代码分析、日志、第三方库、书籍、Java 站点等等。伯乐在线已经把 awesome-java 资源列表翻成中文后发布于 ...

    免费开源!!Java资源大全中文版,包括开发库、开发工具、网站、博客、微信、微博等

    awesome -java就是akullpp发起维护的Java资源列表,内容包括:构建工具、数据库、框架、模板、安全、代码分析、日志、第三方库、书籍、Java站点等等。伯乐在线已经把awesome-java 资源列表翻成中文后发布于ImportNew...

    Java经典面试题整理及答案详解(三)

    学习Java建议还是多动手练习,很多时候你会发现想的和写出来运行的不是一回事儿,本节内容大家可以根据题目自己练习看看~ 1.使用MyBatis做模糊查询的时候,在日志中看到执行了sql语句,但是查询不到结果。 面对这样...

    北航计算机复试面试题(完整版)资料.doc

    本资源包含了北航计算机复试面试题的完整版资料,涵盖了计算机科学和信息技术的多个领域,包括操作系统、计算机网络、数据结构与算法、数据库、软件测试、编译原理、计算机组成原理等。 操作系统部分: * 文件系统...

    让Django支持Sql Server作后端数据库的方法

    一开始图省事儿,我用的sqlite3当后端数据库,但单位要求在项目正式上线的时候用SQL Server,于是,记得django 1.9默认不支持微软那一套的我,就开始在网上搜啊搜,现是发现有人说只要装好一个名为pymssql的包,于是...

    免费开源!!Java 的 MyBatis SQL 映射器框架

    MyBatis SQL 映射器框架使得在面向对象的应用程序中使用关系数据库变得更加容易。MyBatis 使用 XML 描述符或注释将对象与存储过程或 SQL 语句结合起来。简单性是 MyBatis 数据映射器相对于对象关系映射工具的最大...

    任何编程语言的 LeetCode 解决方案

    所有题解均由多种编程语言实现,包括但不限于:Java、Python、C++、Go、TypeScript、Rust,每日更新。欢迎Star 关注本项目,获取项目最新动态。 站点: Vercel: https: //doocs-leetcode.vercel.app GitHub 页面: ...

    TellMeAboutIt:Android 翻译消息应用程序

    告诉我怎么回事儿 Android 翻译消息应用程序 读我 此应用程序旨在为革命性的消息翻译应用程序创建中等保真原型。 它的创建是为了展示使用名为 Parse 的后端创建用户名和密码的简便性。 它还能够将消息翻译成七种不同...

Global site tag (gtag.js) - Google Analytics