百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

JDBC Batch Updates(二) jdbc批量更新三种模式

yuyutoo 2024-10-28 20:21 2 浏览 0 评论

最近在看一本书《high performance java persistence》,做一下笔记

这章不会太长,也是拓展一下大家的知识。

java.sql.Statement: 执行SQL语句并获取执行结果集,记住喔,这个接口的实现类执行的静态SQL语句喔。

java.sql.PreparedStatement:如果你翻开JDK,里面指的是一个预编译的SQL语句,文绉绉的,其实就是动态传参的SQL语句。

java.sql.CallableStatement:执行存储过程的接口。

Batch updates,中文译过来就是批量更新。我们平时都是用框架去做这些东西,却对底层了解的很少,下面我就和大家介绍一下。

JDBC2.0引入指量更新。这里于多条的DML statements(DML 语句)可以组合在一个请求里面发送给数据库。

看一段代码:

statement.addBatch(
"INSERT INTO post (title, version, id) " + "VALUES ('Post no. 1', 0, 1)");
statement.addBatch(
"INSERT INTO post_comment (post_id, review, version, id) " + "VALUES (1, 'Post comment 1.1', 0, 1)");
int[] updateCounts = statement.executeBatch();

这里就要敲黑板了,是扩充你的知识面的时候。不同的数据库厂商实现的会有所差异的,下面我是根据书还有一些文章来给你解释一下:

首先是Oracle,对于Statement和CallableStatement,其实是没并没有真正的像我上面说的合成一个请求,其实是每一条语句独立执行并没有批量执行,所以性能上面并没有提升的。PrepareStatment是有能进行批量处理的,但是那个batch size你要注意了,官方提出是50-100最佳。原因就是如果批次太大会造成占用太大的内存,通常会导致系统性能下降。

书中原文:

Oracle

For Statement and CallableStatement, the Oracle JDBC Driver doesn’t actually support batching For anything but PreparedStatement, the driver ignores batching, and each statement is executed separately.

然后我又去了官方文档找了一下:http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraperf.htm#JJDBC28752

文档提及

The Oracle implementation of standard update batching does not implement true batching for generic statements and callable statements. Even though Oracle JDBC supports the use of standard batching for Statement and CallableStatement objects, you are unlikely to see performance improvement.

因为我说的不一定正确,书中也不一定正确,所以官方文档是最靠谱的。下面我解析其他数据库厂商的实现再不会贴英文了,但是我会将官方文档贴链接贴着,方便你去查证。

对于Mysql:

https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html

Mysql默认是没有将多条语句合成一个batch发送给数据库。但是为了达到batch,驱动提供了一个属性rewriteBatchedStatements,当设置为true的时候,你的批处理才会生效,不然你用框架傻傻的写代码,然后会发现怎么性能没上来,换个框架还是没有上来。其实在你jdbc.url拼接的时候加上rewriteBatchedStatements=true就大大的提升了性能了。我就在网上随便找一条sample

master.jdbc.url=jdbc:mysql://112.126.84.3:3306/platform?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true

但是这个参数也会带来一定副作用。但是根据官文我也不是很了解是什么意思,如果你知道,评论区留言一下让我知道。

Bulk Operations的操作性能会比batch update好,但是灵活性不如batch update.工作当中我也没涉及到这一块。

主键的生成通常都交给数据库,但是如果获取回生成的主键呢。

通过PrepareStatment有三种方式:

第一种:

PreparedStatement postStatement = connection.prepareStatement(
  "INSERT INTO post (title, version) VALUES (?, ?)",
  Statement.RETURN_GENERATED_KEYS
);

第二种:

PreparedStatement postStatement = connection.prepareStatement( 
  "INSERT INTO post (title, version) VALUES (?, ?)",
	new int[] {1}
);

第三种:

PreparedStatement postStatement = connection.prepareStatement( 
  "INSERT INTO post (title, version) VALUES (?, ?)",
	new String[] {"id"}
);

根据JDBC4.2的规范,每个driver都必须实现supportsGetGeneratedKeys()来说明是否支持获取主键。是不是觉得很有意思。平时写代码的时候根本没有注意这一块。但是这个对于Statment是强制性要求的,但是对于PrepareStatment是没有要求的。下图算是拓展知识吧。


序列,有一些数据库提供序列就是sequence来将主键的生成和数据插入进行分离。

下面是几种数据分别创表和获取序列的语法

创表:

#Oracle 12c 之前的创建表
CREATE SEQUENCE post_seq;
CREATE TABLE post (
id NUMBER(19,0) NOT NULL, title VARCHAR2(255 CHAR), version NUMBER(10,0) NOT NULL, PRIMARY KEY (id));
CREATE OR REPLACE TRIGGER post_identity BEFORE INSERT ON post
FOR EACH ROW
BEGIN
SELECT post_seq.NEXTVAL INTO :NEW.id
FROM dual;
end;

#Oracle 12c 之后

CREATE TABLE post (
id NUMBER(19,0) NOT NULL GENERATED ALWAYS AS IDENTITY, title VARCHAR2(255 CHAR),
version NUMBER(10,0) NOT NULL,
PRIMARY KEY (id));

SQL Server

CREATE TABLE post (
	id BIGINT IDENTITY NOT NULL, 
  title VARCHAR(255),
	version INT NOT NULL, 
  PRIMARY KEY (id));

PostgreSQL 9.5

CREATE TABLE post (
	id SERIAL NOT NULL, 
  title VARCHAR(255),
  version INT4 NOT NULL, 
  PRIMARY KEY (id)
);
#另外一种创表

CREATE TABLE post (
id INTEGER DEFAULT NEXTVAL('post_id_seq') NOT NULL, title VARCHAR(255),
version INT4 NOT NULL,
PRIMARY KEY (id));
);

MysSQL 5.7


CREATE TABLE post (
id BIGINT NOT NULL AUTO_INCREMENT,
title VARCHAR(255),
version INTEGER NOT NULL,
PRIMARY KEY (id));

获取序列:

#Oracle
SELECT post_seq.NEXTVAL FROM dual; 

#SQL Server
SELECT NEXT VALUE FOR post_seq; 

#PostgreSQL
SELECT NEXTVAL('post_seq');

可以看到PostgresSQL使用SERIAL,底层还是用序列实现。

下一篇我会聊一下Statement Caching 语句缓存。

相关推荐

如何在HTML中使用JavaScript:从基础到高级的全面指南!

“这里是云端源想IT,帮你...

推荐9个Github上热门的CSS开源框架

大家好,我是Echa。...

前端基础知识之“CSS是什么?”_前端css js

...

硬核!知网首篇被引过万的论文讲了啥?作者什么来头?

整理|袁小华近日,知网首篇被引量破万的中文论文及其作者备受关注。知网中心网站数据显示,截至2021年7月23日,由华南师范大学教授温忠麟等人发表在《心理学报》2004年05期上的学术论文“中介效应检验...

为什么我推荐使用JSX开发Vue3_为什么用vue不用jquery

在很长的一段时间中,Vue官方都以简单上手作为其推广的重点。这确实给Vue带来了非常大的用户量,尤其是最追求需求开发效率,往往不那么在意工程代码质量的国内中小企业中,Vue占据的份额极速增长...

【干货】一文详解html和css,前端开发需要哪些技术?
【干货】一文详解html和css,前端开发需要哪些技术?

网站开发简介...

2025-02-20 18:34 yuyutoo

分享几个css实用技巧_cssli

本篇将介绍几个css小技巧,目录如下:自定义引用标签的符号重置所有标签样式...

如何在浏览器中运行 .NET_怎么用浏览器运行代码

概述:...

前端-干货分享:更牛逼的CSS管理方法-层(CSS Layers)

使用CSS最困难的部分之一是处理CSS的权重值,它可以决定到底哪条规则会最终被应用,尤其是如果你想在Bootstrap这样的框架中覆盖其已有样式,更加显得麻烦。不过随着CSS层的引入,这一...

HTML 基础标签库_html标签基本结构
HTML 基础标签库_html标签基本结构

HTML标题HTML标题(Heading)是通过-...

2025-02-20 18:34 yuyutoo

前端css面试20道常见考题_高级前端css面试题

1.请解释一下CSS3的flexbox(弹性盒布局模型),以及适用场景?display:flex;在父元素设置,子元素受弹性盒影响,默认排成一行,如果超出一行,按比例压缩flex:1;子元素设置...

vue引入外部js文件并使用_vue3 引入外部js

要在Vue中引入外部的JavaScript文件,可以使用以下几种方法:1.使用``标签引入外部的JavaScript文件。在Vue的HTML模板中,可以直接使用``标签来引入外部的JavaScrip...

网页设计得懂css的规范_html+css网页设计

在初级的前端工作人员,刚入职的时候,可能在学习前端技术,写代码不是否那么的规范,而在工作中,命名的规范的尤为重要,它直接与你的代码质量挂钩。网上也受很多,但比较杂乱,在加上每年的命名都会发生一变化。...

Google在Chrome中引入HTML 5.1标记

虽然负责制定Web标准的WorldWideWebConsortium(W3C)尚未宣布HTML5正式推荐规格,而Google已经迁移到了HTML5.1。即将发布的Chrome38将引入H...

HTML DOM 引用( ) 对象_html中如何引用js

引用对象引用对象定义了一个同内联元素的HTML引用。标签定义短的引用。元素经常在引用的内容周围添加引号。HTML文档中的每一个标签,都会创建一个引用对象。...

取消回复欢迎 发表评论: