java 并发 主键_高并发数据库自增主键分析

在一般情况下,在新增领域对象后,都需要获取对应的主键值。使用应用层来维护主键,在一定程度上有利于程序性能的优化和应用移植性的提高。在采用数据库自增主键的方案里,如果JDBC驱动不能绑定新增记录对应的主键,就需要手工执行查询语句以获取对应的主键值,对于高并发的系统,这很容易返回错误的主键。通过带缓存的DataFieldMaxValueIncrementer,可以一次获取批量的主键值,供多次插入领域对象时使用,它的执行性能是很高的。

我们经常使用数据的自增字段作为表主键,也即主键值不在应用层产生,而是在新增记录时,由数据库产生。这样,应用层在保存对象前并不知道对象主键值,而必须在保存数据后才能从数据库中返回主键值。在很多情况下,我们需要获取新对象持久化后的主键值。在Hibernate等ORM框架,新对象持久化后,Hibernate会自动将主键值绑定到对象上,给程序的开发带来了很多方便。

在JDBC 3.0规范中,当新增记录时,允许将数据库自动产生的主键值绑定到Statement或PreparedStatement中。

使用Statement时,可以通过以下方法绑定主键值:int executeUpdate(String sql, int autoGeneratedKeys)

也可以通过Connection创建绑定自增值的PreparedStatement: PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)

当autoGeneratedKeys参数设置为Statement.RETURN_GENERATED_KEYS值时即可绑定数据库产生的主键值,设置为Statement.NO_GENERATED_KEYS时,不绑定主键值。下面的代码演示了Statement绑定并获取数据库产生的主键值的过程:

Statement stmt = conn.createStatement();

String sql = "INSERT INTO t_topic(topic_title,user_id) VALUES(‘测试主题’,’123’)";

stmt.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS); // ①指定绑定表自增主键值

ResultSet rs = stmt.getGeneratedKeys();

if( rs.next() ) {

intkey = rs.getInt(); // ②获取对应的表自增主键值

}

Spring利用这一技术,提供了一个可以返回新增记录对应主键值的方法: int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder) ,其中第二个参数类型org.springframework.jdbc.support.KeyHolder,它是一个回调接口,Spring使用它保存新增记录对应的主键,该接口的接口方法描述如下:

Number getKey() throws InvalidDataAccessApiUsageException;

当仅插入一行数据,主键不是复合键且是数字类型时,通过该方法可以直接返回新的主键值。如果是复合主键,或者有多个主键返回时,该方法抛出 InvalidDataAccessApiUsageException。该方法是最常用的方法,因为一般情况下,我们一次仅插入一条数据并且主键字段类型为数字类型;

如果是复合主键,则列名和列值构成Map中的一个Entry。如果返回的是多个主键,则抛出InvalidDataAccessApiUsageException异常;

Map getKeys() throws InvalidDataAccessApiUsageException;

如果返回多个主键,即PreparedStatement新增了多条记录,则每一个主键对应一个Map,多个Map构成一个List。

List getKeyList():

Spring为KeyHolder接口指代了一个通用的实现类GeneratedKeyHolder,该类返回新增记录时的自增长主键值。假设我们希望在新增论坛板块对象后,希望将主键值加载到对象中,则可以按以下代码进行调整:

public voidaddForum(final Forum forum) {

final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";

KeyHolder keyHolder = newGeneratedKeyHolder(); // ①创建一个主键执有者

getJdbcTemplate().update(newPreparedStatementCreator() {

public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {

PreparedStatement ps = conn.prepareStatement(sql);

ps.setString(1, forum.getForumName());

ps.setString(2, forum.getForumDesc());

returnps;

}

}, keyHolder);

forum.setForumId(keyHolder.getKey().intValue()); // ②从主键执有者中获取主键

}

这样,在调用addForum(Forum forum)新增forum领域对象后,forum将拥有对应的主键值,方便后继的使用。在JDBC 3.0之前的版本中,PreparedStatement不能绑定主键,如果采用表自增键(如MySQL的auto increment或SQLServer的identity)将给获取正确的主键值带来挑战——因为你必须在插入数据后,马上执行另一条获取新增主键的查询语句。下面给出了不同数据库获取最新自增主键值的查询语句:

posted on 2011-09-25 14:27 jadmin 阅读(902) 评论(0)  编辑  收藏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单实例数据库和多实例数据库

java持续学习中,暂时说说工作上学到的知识 单实例数据库模式 单实例模式下,一个数据库只能通过一个实例进行访问 RAC(Real Application Clusters)集群模式下,共享数据库文件,一个数据库生成多个相同的实例被用户访问。

java list 从0开始_Java从零开始学二十一(集合List接口)

package com.pb.demo1;import java.util.LinkedList;import java.util.List;public class PersonLinkedListTest {public static void main(String[] args) {/** 创建多个Person对象并赋值*/Person p1 new Person("张三",21);Person p2 new Person("李四"…

[Swift]LeetCode482. 密钥格式化 | License Key Formatting

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)➤GitHub地址&a…

oracle用户相关操作

我们主要学习数据库的一些基本操作,比如如何在数据库创建用户,授权,删除用户,回收权限,为用户加锁或者解锁等一些常用的操作。 首先,我们要知道数据库中创建用户的语句怎么写,看下面: 1.创建用户…

java显示时间_Java如何显示日期和时间?

在Java中,如何显示当前日期和时间?此示例显示如何使用Formatter类的fmt.format()方法和Calendar类的Calendar.getInstance()方法来显示当前日期和时间。package com.yiibai;import java.text.SimpleDateFormat;import java.util.Calendar;import java.ut…

小程序返回上一页并传参

点击返回上一页事件: returnPre:function(e){let pages getCurrentPages();let prevPage pages[pages.length - 2];prevPage.setData({discount: e.currentTarget.dataset.discount,})wx.navigateBack({delta: 1,})} 其中getCurrentPages() 函数用于获取当前页面栈…

Oracle数据库操作

一、Oracle数据库操作 1、创建数据库 create database databasename 2、删除数据库 drop database dbname 3、备份数据库 • 完全备份 exp demo/demoorcl buffer1024 filed:\back.dmp fully demo:用户名、密码 buffer: 缓存大小 file: 具体的备份文件地址…

java监听器原理_java监听器原理

import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JComboBox; public class ComBoxDemo extends JFrame { JComboBox computer; //主类别下拉框 JComboBox fittings; //配件下拉框 public ComBoxDemo() {…

Django的各种初识

1,django项目的各个文件的介绍 1.1>项目的根目录:是各个子文件的根目录,在各个文件相互导入文件的时候使用 1.2>配置文件:为django的各个文件配置相关的各种默认配置 1.3>路径和函数的对应关系:是当form表单提交数据的时候和有关于网址的东西都会来urls来查找向对应的…

IIS介绍

IIS7及以上版本提供的请求-处理架构包括以下内容: • Windows Process Activation Service(WAS)可以让站点支持更多协议,不仅仅是HTTP和HTTPS • 可以通过增加或移除模块来自定义Web服务器引擎 • 集成IIS和ASP.NET请求-处理管线 IIS中的组件 IIS包含多个…

mysql 三级联动_c#+Mysql 实现三级联动

注明:此文章是转载而来,只是稍稍改了一点。。。1、实现语言,c#,mysql,其中要引入mysq.dll需要建立三个表----对应关系2、Web.cofig3、demo.cx文件:private string conn WebConfigurationManager.ConnectionStrings["Conn&qu…

Linux卸载MariaDB

CentOS7.5 安装MySQL8.0.12 安装前:  先卸载 CentOS7.5默认安装的MariaDB,配置文件在/etc/my.cnf rpm -qa | grep mariadb 找到 使用 yum remove mariadb-libs-5.5.56-2.el7.x86_64 再次查找 rpm -qa | grep mariadb 同时,配置文件在/etc/my.cnf 也已经…

win10安装iis(亲测,工作需要)

• 点击“Windows”键进入“开始”菜单,点击“所有应用”,在所有应用菜单里点击“Windows系统”里的“控制面板” • 在控制面板对话框里点击“程序” • 在“程序”对话框里点击“启用或关闭Windows功能” • 在“Windows功能”对话框里选中“Interne…

视频展示

作业要求:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2189 视频链接:http://v.youku.com/v_show/id_XMzg2Mzg1NzE0OA.html 视频播放截图及介绍: 1.成语考试中: 2.少年面对成语难得直挠头: 3.父亲发现孩子…

java学习(36):数组排序

/3使用Eclipse编写控制台应用程,接收老师输入的某个学生本学期的5此Java成绩考核, 并存储在5个长度的int类型数组中,对数组中的成绩进行从大到小排序,最后依次变量数组中的元素输出到控制台,如下示例: 源成…

java 8 io_Java IO8:IO简单总结

字节流、字符流继承关系前几篇文章讲解了字节流、字符流的使用,不过Java提供给用户的流类远不止此,限于篇幅原因,没办法一一讲解,而且也没有必要一一讲解,就像我在写博客的时候多次提到的,有问题的时候学会…

PHP实现高并发下的秒杀功能–Laravel

namespace App\Http\Controllers\SecKill; use App\Http\Controllers\Controller;use Exception;use Illuminate\Support\Facades\DB;use Illuminate\Support\Facades\Redis; class SecKillController extends Controller{ /** * 往redis的隊列中添加庫存(用於測試的…

vuex的个人理解

看官方文档看的一脸懵逼,后来看到了一篇比较容易理解的博文,大概写下自己的理解 一、vuex是什么 是基于vue的状态管理模式,一般用于解决大型项目中子组件向父组件传递数据的问题 二、基本概念 1、state 需要使用store的数据存储在state里&…

java验证码的代码_java实用验证码的实现代码

本文为大家分享了java实用验证码的实现代码,供大家参考,具体内容如下1、ValidCodepackage validImg;import java.awt.Color;import java.io.IOException;import java.util.Random;import javax.servlet.ServletException;import javax.servlet.http.Http…

java学习(37):二维数组

/4 利用嵌套循环完成以下二维数组的遍历,体会二维数组或多维数组元素的遍历方法及每个维数数组元素的下标特点。/ import java.util.Scanner; public class test06 { public static void main(String[] args){ Scanner in new Scanner(System.in); System.out.print…