摘要 写道
在上一篇《我和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的设置一般要靠经验和测试结果来决定。
分享到:
相关推荐
数据库连接池可以通过配置服务器容器的server.xml实现,也可以用中间件来完成相应的功能,这是一个用java实现的数据库连接池功能
【一线互联网大厂Java核心面试题库】Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等..
简单的gui界面 包含数据库驱动 连接数据库 查询 Jtable的使用和显示数据大家可以下载查看 如有问题请互相学习
1. 哪个项目能离开网络,数据库,操作系统来运行?所以生态圈的应用技术主要在这些知识点处。 2. Java组件,组件其实是一个应用程序块 但是它们不是完整的应用程序,不能单独运行。有如一辆汽车,车门是一个组件...
【Java面试+Java后端技术学习指南】:一份通向理想互联网公司的面试指南,包括 Java,技术面试必备基础知识、Leetcode、计算机操作系统、计算机网络、系统设计、分布式、数据库(MySQL、Redis)、Java 项目实战等 ...
源文件生成在执行注释处理或与元数据文件(例如数据库模式、协议格式)交互等操作时非常有用。通过生成代码,您无需编写样板文件,同时还可以保留元数据的单一事实来源。 例子 这是一个(无聊的)HelloWorld课程: ...
ext学习笔记一 小试iBatis RIA(Rich Internet Application)的现状和未来 Java应用中域名解析不过期的解决方法 Java编程那些事儿45—数组使用示例1 一步步熟悉OFBiz 用Java做客户端调用.NET写...
27_如何保证缓存与数据库双写时的数据一致性? 28_你能说说redis的并发竞争问题该如何解决吗? 29_你们公司生产环境的redis集群的部署架构是什么样的? 30_分布式缓存相关面试题的回答技巧总结 31_体验一下面试官...
awesome-java 就是 akullpp 发起维护的 Java 资源列表,内容包括:构建工具、数据库、框架、模板、安全、代码分析、日志、第三方库、书籍、Java 站点等等。伯乐在线已经把 awesome-java 资源列表翻成中文后发布于 ...
awesome -java就是akullpp发起维护的Java资源列表,内容包括:构建工具、数据库、框架、模板、安全、代码分析、日志、第三方库、书籍、Java站点等等。伯乐在线已经把awesome-java 资源列表翻成中文后发布于ImportNew...
学习Java建议还是多动手练习,很多时候你会发现想的和写出来运行的不是一回事儿,本节内容大家可以根据题目自己练习看看~ 1.使用MyBatis做模糊查询的时候,在日志中看到执行了sql语句,但是查询不到结果。 面对这样...
本资源包含了北航计算机复试面试题的完整版资料,涵盖了计算机科学和信息技术的多个领域,包括操作系统、计算机网络、数据结构与算法、数据库、软件测试、编译原理、计算机组成原理等。 操作系统部分: * 文件系统...
一开始图省事儿,我用的sqlite3当后端数据库,但单位要求在项目正式上线的时候用SQL Server,于是,记得django 1.9默认不支持微软那一套的我,就开始在网上搜啊搜,现是发现有人说只要装好一个名为pymssql的包,于是...
MyBatis SQL 映射器框架使得在面向对象的应用程序中使用关系数据库变得更加容易。MyBatis 使用 XML 描述符或注释将对象与存储过程或 SQL 语句结合起来。简单性是 MyBatis 数据映射器相对于对象关系映射工具的最大...
所有题解均由多种编程语言实现,包括但不限于:Java、Python、C++、Go、TypeScript、Rust,每日更新。欢迎Star 关注本项目,获取项目最新动态。 站点: Vercel: https: //doocs-leetcode.vercel.app GitHub 页面: ...
告诉我怎么回事儿 Android 翻译消息应用程序 读我 此应用程序旨在为革命性的消息翻译应用程序创建中等保真原型。 它的创建是为了展示使用名为 Parse 的后端创建用户名和密码的简便性。 它还能够将消息翻译成七种不同...