日期:2014-05-16  浏览次数:20574 次

实现兼容各种数据库表字段的主键id自增

在数据库操作中,插入数据库信息的时候往往需要使其数据库的中的表字段的主键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) {}
	}