实现兼容各种数据库表字段的主键id自增
2012-08-14 10:02
323 查看
在数据库操作中,插入数据库信息的时候往往需要使其数据库的中的表字段的主键id能够自增,虽然有的数据库的表字段可也直接在设计的时候就写成自增,比如mysql,但是有的数据库却在实现表字段的自增上却不是很好使,而且各种数据库的实现方式可能不同,所以问了简单统一的管理,方便数据库的移植,而不需要改变SQL创建语句,所以可以单独的创建一个表,专门用于管理数据库表字段主键id的自增,该表(t_table_id)可以按下面这样设计:有一个表名字段table_name(存放需要自增id的表名称),一个是当前对应表的主键id的值value。
创建上面的表之后,然后想该表中插入对应的要进行自增表字段主键id的表的信息。比如:insert into t_table_id table_name,value values('t_client',1);这个语句为表t_client设置主键id冲1开始自增。
其实简单的这样设计了还并不能实现自增,还需要编写代码来进行实现,下面就通过编写java代码来进行实现:
package org.ml.drp.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* id生成器
* @author MuLing
*
*/
public class IdGenerator {
/**
* 根据表名生成该表的序列
* @param tableName
* @return 返回生成的序列
*/
public static int generate(String tableName) {
//使用数据库的悲观锁for update
String sql = "select value from t_table_id where table_name=? for update";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int value = 0;
try {
conn = DbUtil.getConnection();
//开始事务
DbUtil.beginTransaction(conn);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, tableName);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new RuntimeException();
}
value = rs.getInt("value");
value++; //自加
modifyValueField(conn, tableName, value);//修改对应序列字段的值
//提交事务
DbUtil.commitTransaction(conn);
}catch(Exception e) {
e.printStackTrace();
//回滚事务
DbUtil.rollbackTransaction(conn);
throw new RuntimeException();
}finally {
DbUtil.close(rs);
DbUtil.close(pstmt);
DbUtil.resetConnection(conn); //重置Connection的状态
DbUtil.close(conn);
}
return value;
}
/**
* 根据表名更新序列字段的值
* @param conn
* @param tableName
* @param value
*/
private static void modifyValueField(Connection conn, String tableName, int value)
throws SQLException {
String sql = "update t_table_id set value=? where table_name=?";
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, value);
pstmt.setString(2, tableName);
pstmt.executeUpdate();
}finally {
DbUtil.close(pstmt);
}
}
public static void main(String[] args) {
int retValue = IdGenerator.generate("t_client");
System.out.println(retValue);
}
}
另外附加下面的数据库工具类(DbUtil.java)中的几个方法实现:
public static void resetConnection(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false);
}else {
conn.setAutoCommit(true);
}
}
}catch(SQLException e) {}
}
public static void beginTransaction(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false); //手动提交
}
}
}catch(SQLException e) {}
}
public static void commitTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.commit();
}
}
}catch(SQLException e) {}
}
public static void rollbackTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.rollback();
}
}
}catch(SQLException e) {}
}
创建上面的表之后,然后想该表中插入对应的要进行自增表字段主键id的表的信息。比如:insert into t_table_id table_name,value values('t_client',1);这个语句为表t_client设置主键id冲1开始自增。
其实简单的这样设计了还并不能实现自增,还需要编写代码来进行实现,下面就通过编写java代码来进行实现:
package org.ml.drp.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* id生成器
* @author MuLing
*
*/
public class IdGenerator {
/**
* 根据表名生成该表的序列
* @param tableName
* @return 返回生成的序列
*/
public static int generate(String tableName) {
//使用数据库的悲观锁for update
String sql = "select value from t_table_id where table_name=? for update";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int value = 0;
try {
conn = DbUtil.getConnection();
//开始事务
DbUtil.beginTransaction(conn);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, tableName);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new RuntimeException();
}
value = rs.getInt("value");
value++; //自加
modifyValueField(conn, tableName, value);//修改对应序列字段的值
//提交事务
DbUtil.commitTransaction(conn);
}catch(Exception e) {
e.printStackTrace();
//回滚事务
DbUtil.rollbackTransaction(conn);
throw new RuntimeException();
}finally {
DbUtil.close(rs);
DbUtil.close(pstmt);
DbUtil.resetConnection(conn); //重置Connection的状态
DbUtil.close(conn);
}
return value;
}
/**
* 根据表名更新序列字段的值
* @param conn
* @param tableName
* @param value
*/
private static void modifyValueField(Connection conn, String tableName, int value)
throws SQLException {
String sql = "update t_table_id set value=? where table_name=?";
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, value);
pstmt.setString(2, tableName);
pstmt.executeUpdate();
}finally {
DbUtil.close(pstmt);
}
}
public static void main(String[] args) {
int retValue = IdGenerator.generate("t_client");
System.out.println(retValue);
}
}
另外附加下面的数据库工具类(DbUtil.java)中的几个方法实现:
public static void resetConnection(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false);
}else {
conn.setAutoCommit(true);
}
}
}catch(SQLException e) {}
}
public static void beginTransaction(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false); //手动提交
}
}
}catch(SQLException e) {}
}
public static void commitTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.commit();
}
}
}catch(SQLException e) {}
}
public static void rollbackTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.rollback();
}
}
}catch(SQLException e) {}
}
相关文章推荐
- java拼接字符,数据库字符和数字拼接的字符串作为字段,如ID,主键
- 各种数据库自动增长主键Id的sql调用命令
- mysql数据库单表只有一个主键自增id字段,ibatis实现id自增
- oracle 实现表中某个字段的自动增加(相当于有些数据库的自增列)
- JS实现兼容各种浏览器的高级拖动方法完整实例【测试可用】
- 一个通用的单元测试框架的思考和设计07-实现篇-自动管理测试数据-如何为自增长主键id赋值
- JavaWeb一个完整的Servlet上传Excel表格使用poi解析至数据库实现(兼容2003,2007)。
- T-SQL语句实现清空数据库数据的代码,保留原有表形式和各种约束
- elasticsearch指定其他字段为主键_id字段
- Asp.Net和LinQ中,把数据库字段转入变量的各种格式转换!(转换示例)
- 用注解的方式实现Mybatis插入数据时返回自增的主键Id
- 数据库中使用自增量字段与Guid字段作主键的性能对比
- DropDownList实现呈现文字,隐藏Id(数据库)
- 一个javabean轻松实现对数据库的各种操作
- Sqlserver获取所有数据库名,表信息,字段信息,主键信息,以及表结构等。
- MyBatis获取数据库自生成的主键Id详解及实例代码
- 如何实现一个与数据库表字段松耦合的j2ee应用
- myBatis配置实现数据库字段下划线映射到java对象的驼峰式命名属性
- JSP中如何取得MSSQL数据库表中自动增长的ID主键值?
- [导入]数据库中字段为NULL,业务逻辑层中如何实现判断是否为NULL