数据库的自增字段代码生成器——解决不同数据库自增字段的差异机制
2010-11-22 10:58
281 查看
数据库的ID自增字段代码生成器——解决不同数据库自增字段的差异机制
问题:
在设计数据库字段时,有时需要一个int型的id主键,让它能自动递增,每次插入一条数据,它都能够自动增1或者规定的自增数n。对于特定的数据库,要实现这个很简单,比如mysql是用auto_increment,Sql Server是用identity。但是如果在代码中使用和特定数据库有关的特性,那么代码就不能移植,比如把数据库从mysql换成sql server,那么代码就要更改,就不能实现移植扩展。
解决思路:
既然要实现代码的移植扩展,就不能使用和数据库相关的特性,那该怎么办呢?这就是本篇要介绍的ID生成器。
思路是这样的:在数据库中另外建立一张表ID_Main,其包含两个字段:一个字段是要实现ID自增的所属表名(table_name),另一个字段是该表中自增字段对应的现在最大的记录值(id_max)。假设现在要在数据表(user_info)中插入一条数据时,先使表ID_Main中对应字段table_name为的user_info的id_max的值加1,然后再取出该值,就是自动增1后的值。以后每次要插入一条记录,都会先使ID_Main表中对应的id值加1,再返回,其也就是保持了id的自增。
表ID_Main的设计如下:
/*==============================================================*/
/* Table: ID_Main */
/*==============================================================*/
create table ID_Main (
TABLE_NAME VARCHAR2(20) not null,
ID_MAX NUMBER(10) not null,
constraint PK_ ID_Main primary key (TABLE_NAME)
);
comment on table ID_Main is '用于维护各个表中的记录条数';
以下就是代码层,以Java分析为例:
其中的DbUtility类是连接数据库操作的封装类,其代码详细参见《分页技术原理与实现(二)》。代码使用了connection的事务操作,保证事务的一致性,也就是当ID_MAX的值自增1时,应该在相应的表中插入一条记录,以保证自增值一致。如果出错,这应该回滚事务。
通过以上分析与代码示例,就简单的实现了一个IDGenerator即ID生成器,它与数据库的特性隔离,实现了代码层的移植性。
问题:
在设计数据库字段时,有时需要一个int型的id主键,让它能自动递增,每次插入一条数据,它都能够自动增1或者规定的自增数n。对于特定的数据库,要实现这个很简单,比如mysql是用auto_increment,Sql Server是用identity。但是如果在代码中使用和特定数据库有关的特性,那么代码就不能移植,比如把数据库从mysql换成sql server,那么代码就要更改,就不能实现移植扩展。
解决思路:
既然要实现代码的移植扩展,就不能使用和数据库相关的特性,那该怎么办呢?这就是本篇要介绍的ID生成器。
思路是这样的:在数据库中另外建立一张表ID_Main,其包含两个字段:一个字段是要实现ID自增的所属表名(table_name),另一个字段是该表中自增字段对应的现在最大的记录值(id_max)。假设现在要在数据表(user_info)中插入一条数据时,先使表ID_Main中对应字段table_name为的user_info的id_max的值加1,然后再取出该值,就是自动增1后的值。以后每次要插入一条记录,都会先使ID_Main表中对应的id值加1,再返回,其也就是保持了id的自增。
表ID_Main的设计如下:
/*==============================================================*/
/* Table: ID_Main */
/*==============================================================*/
create table ID_Main (
TABLE_NAME VARCHAR2(20) not null,
ID_MAX NUMBER(10) not null,
constraint PK_ ID_Main primary key (TABLE_NAME)
);
comment on table ID_Main is '用于维护各个表中的记录条数';
以下就是代码层,以Java分析为例:
import java.sql.ResultSet; import java.sql.SQLException; import kane.DbUtility; //ID生成器实体类 public class IDGenerator { // 使用单例模式 private static IDGenerator instance = null; private IDGenerator() { } public static synchronized IDGenerator getInstance() { if (instance == null) { instance = new IDGenerator(); } return instance; } // 通过主键维护表ID_Main来获取表中的记录数 public int getTotal(Connection conn, String tableName) throws SQLException { int i = 0; PreparedStatement pstmt = null; ResultSet rs = null; try { String sql = "select ID_MAX from ID_Main where table_name = ?"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, tableName); rs = pstmt.executeQuery(); if (rs.next()) { i = rs.getInt(1); } } catch (SQLException e) { e.printStackTrace(); throw e; } finally { DbUtility.closeResultSet(rs); DbUtility.closePreparedStatement(pstmt); } return i; } // 将主键维护表ID_Main中的记录数加1,然后再返回该值 public int getNextID(String tableName) { int total = 0; Connection conn = null; PreparedStatement pstmt = null; try { conn = DbUtility.getConnection(); String sql = "update ID_Main set ID_MAX = ID_MAX +1 where table_name=?"; // 开启事务 conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql); pstmt.setString(1, tableName); pstmt.executeUpdate(); total = getTotal(conn, tableName); // 执行事务 conn.commit(); } catch (SQLException e) { e.printStackTrace(); // 事务回滚 try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { DbUtility.closePreparedStatement(pstmt); DbUtility.closeConnection(conn); } return total; } }
其中的DbUtility类是连接数据库操作的封装类,其代码详细参见《分页技术原理与实现(二)》。代码使用了connection的事务操作,保证事务的一致性,也就是当ID_MAX的值自增1时,应该在相应的表中插入一条记录,以保证自增值一致。如果出错,这应该回滚事务。
通过以上分析与代码示例,就简单的实现了一个IDGenerator即ID生成器,它与数据库的特性隔离,实现了代码层的移植性。
相关文章推荐
- 数据库的自增字段代码生成器——解决不同数据库自增字段的差异机制
- mybatis(四)——mybatis解决数据库表字段名与实体类属性名不同的冲突
- Mybatis中解决数据库字段名与实体类属性名不同的问题
- sql语句简单解决同个字段不同标识的具体意义
- atitit.提升稳定性---hibernate 添加重试retry 机制解决数据库连接关闭
- Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题
- Delphi字段类型和不同数据库对应.txt
- 在Mybatis中,解决数据库字段名与java实体类属性名不一致的三种方式
- 数据库中,连接有哪些不同类型?请说明这些类型之间的差异,以及为何在某些情形下,某种连接会比较好。
- sql2005 数据库还原,备份集中的数据库备份与现有的数据库不同,解决办法
- 数据库text类型字段作为查询条件的终极解决办法
- 数据库价格字段人民币符号在VS中的解决方法
- C#中解决插入数据库的某个字段类型为datetime 为空
- sql2008备份集中的数据库备份与现有的xxx数据库不同解决方法
- sql2008“备份集中的数据库备份与现有的xx数据库不同”解决方法(转)
- [转]Hibernate不能自动建表解决办法及Hibernate不同数据库的连接及SQL方言
- SQL Server 2005“备份集中的数据库备份与现有的数据库不同”解决方法 详细出处参考:http://www.jb51.net/article/19233.htm
- hibernate的ID生成机制【针对不同的数据库】
- 四、数据库表中的字段名与实体类属性名不相同,可用resultMap解决
- C#中解决插入数据库的某个字段类型为datetime 为空