1.我们知道oracle 中有sequence做代理主键(自动增长)数据库实现 每次调用INSERT 都需要
BIZASSISTANT.OFSMSLOG_SEQ.NEXTVAL 这样的调用。数据库一旦更换OFSMSLOG_SEQ没有及时同步过去或者重新生成的序列和原有数据ID主键冲突等问题会发生。
先将sequence 生成让代码实现,这样代码移植后就不会出现上面问题了
代码如下
SequenceManager.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/***********************************************************************
*
* SequenceManager.java
* @copyright Copyright: 2009-2012
* @creator 周辉<br/>
* @create-time Jul 16, 2009 11:12:09 AM
* @revision $Id: *
***********************************************************************/
public class SequenceManager {
private static final String CREATE_ID =
"INSERT INTO ofID (id, idType) VALUES (1, ?)";
private static final String LOAD_ID =
"SELECT id FROM ofID WHERE idType=?";
private static final String UPDATE_ID =
"UPDATE ofID SET id=? WHERE idType=? AND id=?";
// Statically startup a sequence manager for each of the sequence counters.
private static Map<Integer, SequenceManager> managers = new ConcurrentHashMap<Integer, SequenceManager>();
/**
* Returns the next ID of the specified type.
*
* @param type the type of unique ID.
* @return the next unique ID of the specified type.
*/
public static long nextID(int type) {
if (managers.containsKey(type)) {
return managers.get(type).nextUniqueID();
}
else {
// Verify type is valid from the db, if so create an instance for the type
// And return the next unique id
SequenceManager manager = new SequenceManager(type, 1);
return manager.nextUniqueID();
}
}
/**
* Used to set the blocksize of a given SequenceManager. If no SequenceManager has
* been registered for the type, the type is verified as valid and then a new
* sequence manager is created.
*
* @param type the type of unique id.
* @param blockSize how many blocks of ids we should.
*/
public static void setBlockSize(int type, int blockSize) {
if (managers.containsKey(type)) {
managers.get(type).blockSize = blockSize;
}
else {
new SequenceManager(type, blockSize);
}
}
private int type;
private long currentID;
private long maxID;
private int blockSize;
/**
* Creates a new DbSequenceManager.
*
* @param seqType the type of sequence.
* @param size the number of id's to "checkout" at a time.
*/
public SequenceManager(int seqType, int size) {
managers.put(seqType, this);
this.type = seqType;
this.blockSize = size;
currentID = 0l;
maxID = 0l;
}
/**
* Returns the next available unique ID. Essentially this provides for the functionality of an
* auto-increment database field.
*/
public synchronized long nextUniqueID() {
if (!(currentID < maxID)) {
// Get next block -- make 5 attempts at maximum.
getNextBlock(5);
}
long id = currentID;
currentID++;
return id;
}
/**
* Performs a lookup to get the next available ID block. The algorithm is as follows:
* <ol>
* <li> Select currentID from appropriate db row.
* <li> Increment id returned from db.
* <li> Update db row with new id where id=old_id.
* <li> If update fails another process checked out the block first; go back to step 1.
* Otherwise, done.
* </ol>
*/
private void getNextBlock(int count) {
if (count == 0) {
return;
}
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
boolean success = false;
try {
con = DbConnectionManager.getTransactionConnection();
// Get the current ID from the database.
pstmt = con.prepareStatement(LOAD_ID);
pstmt.setInt(1, type);
ResultSet rs = pstmt.executeQuery();
long currentID = 1;
if (!rs.next()) {
rs.close();
pstmt.close();
createNewID(con, type);
}
else {
currentID = rs.getLong(1);
rs.close();
pstmt.close();
}
// Increment the id to define our block.
long newID = currentID + blockSize;
// The WHERE clause includes the last value of the id. This ensures
// that an update will occur only if nobody else has performed an
// update first.
pstmt = con.prepareStatement(UPDATE_ID);
pstmt.setLong(1, newID);
pstmt.setInt(2, type);
pstmt.setLong(3, currentID);
// Check to see if the row was affected. If not, some other process
// already changed the original id that we read. Therefore, this
// round failed and we'll have to try again.
success = pstmt.executeUpdate() == 1;
if (success) {
this.currentID = currentID;
this.maxID = newID;
}
}
catch (SQLException e) {
abortTransaction = true;
}
finally {
try {
if (pstmt != null) {
pstmt.close();
}
}
catch (Exception e) {
}
DbConnectionManager.closeTransactionConnection(con, abortTransaction);
}
if (!success) {
// Call this method again, but sleep briefly to try to avoid thread contention.
try {
Thread.sleep(75);
}
catch (InterruptedException ie) {
// Ignore.
}
getNextBlock(count - 1);
}
}
private void createNewID(Connection con, int type) throws SQLException {
// create new ID row
PreparedStatement pstmt = null;
try {
pstmt = con.prepareStatement(CREATE_ID);
pstmt.setInt(1, type);
pstmt.execute();
}
finally {
DbConnectionManager.closeStatement(pstmt);
}
}
}
其中DbConnectionManager是一个数据库连接的代码,这里就不贴上了
主要是介绍具体代码的实现
分享到:
相关推荐
Oracle 数据库主键自动生成 在 Oracle 数据库中,主键自动生成是指在插入数据时自动生成唯一的主...Oracle 数据库主键自动生成可以通过序列和触发器来实现,简化了数据录入和维护工作,并提高了数据的一致性和安全性。
这种方法是采用 GUID,当然我是推荐主键还是字符型的,但值由 GUID 生成,GUID 是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的 GUID 值导到一起时,也不会发生重复。...
Oracle数据库在设计和管理大型数据系统时扮演着关键角色,其中序列(Sequence)是一种非常重要的对象,用于生成唯一的整数序列,通常用作表的主键。本篇将深入探讨Oracle数据库表序列ID自增生成器及其相关知识点。 ...
3. **`sequence`**:与JPA的`GenerationType.SEQUENCE`相同,使用数据库序列。 4. **`hilo`**:HiLo算法,通过高位和低位值组合生成主键,减少对数据库的访问。 5. **`assigned`**:主键由应用程序指定,Hibernate...
总结来说,电信报表系统的数据库设计涉及多个层面,包括合理规划表结构、序列生成唯一标识、保持数据完整性和性能优化。理解这些概念和技术对于管理和维护这样的系统至关重要。通过持续监控和优化,可以确保报表系统...
高并发分布式系统中生成全局唯一Id汇总 数据在分片时,典型的是分库分表,就有一个全局ID生成的问题。 单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求: 1 不能有单点故障。 2 以时间为...
在数据库设计中,主键的设计至关重要,它不仅关系到数据的唯一性,还影响着数据检索效率以及系统的整体性能。本文将根据提供的描述和部分内文,深入探讨数据库主键设计的原则与策略。 #### 二、主键设计原则概述 ...
本文主要探讨了在使用Java Persistence API (JPA) 和 Hibernate 框架时,如何处理主键的生成,特别是针对不同数据库系统的序列(sequence)机制。 首先,序列是一种在数据库中用于生成有序整数的机制,常被用作主键...
这种策略在数据库级别生成主键,常见于MySQL和SQL Server。当一个新对象被保存时,数据库会自动为该对象分配一个唯一的ID。在Hibernate中,通过`@GeneratedValue(strategy = GenerationType.IDENTITY)`来指定。 2....
seqhilo与hilo类似,也是基于Hi/Lo算法,但使用数据库序列来获取Hi值,适用于支持序列的数据库如Oracle。它的优势在于可以更好地处理多进程并发,但不适用于所有数据库。 5. **identity**策略: 这种策略依赖于...
seqhilo策略与hilo类似,但它使用数据库序列而非单独的表。首先,你需要在数据库中创建一个序列,然后Hibernate会使用这个序列来生成主键。这种方式同样跨数据库,但在Oracle、PostgreSQL等支持序列的数据库中更为...
这些注解包括但不限于`@Entity`(标记一个类作为数据库表的映射)、`@Table`(指定表名)、`@Column`(指定字段与列的对应关系)、`@Id`(标识主键)、`@GeneratedValue`(定义主键生成策略)等。通过使用这些注解,...
在描述中提到了“自动生成主键”,MyBatis Generator提供了多种主键生成策略,如Identity(自动增长主键)、Sequence(序列主键)和UUID等。选择合适的策略可以确保主键的唯一性和生成方式符合数据库的特性。 4. ...
在Java编程中,生成数据库表序列号通常涉及到数据库序列(Sequence)的概念,这是数据库系统用于自动为表生成唯一标识符的一种机制。Oracle、PostgreSQL等数据库支持序列,而MySQL等数据库可能通过自增主键来实现...
在Ibatis中,只需在Mapper XML文件中的`<insert>`标签中设置`useGeneratedKeys="true"`和`keyProperty="id"`,就可以让数据库自动生成主键。 4. **雪花算法(Snowflake Algorithm)**: 在分布式环境下,为了保证...
2. **SEQUENCE**:使用数据库序列生成主键,适用于支持序列的数据库,如Oracle。 3. **TABLE**:通过数据库表生成主键,适用于不支持序列的数据库,如MySQL。 4. **UUID**:生成全局唯一的UUID字符串作为主键。 5. *...
Hibernate作为一款流行的Java持久层框架,提供了多种自动生成主键的方法,以适应不同场景的需求。本文将深入探讨Hibernate中自动生成主键的几种常见策略及其应用场景。 ### 1. UUID.hex UUID(Universally Unique ...
GUID 主键是一种比较好的主键,采用 GUID 生成,GUID 是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的 GUID 值导到一起时,也不会重复。 主键的设计是非常重要的,我们需要...
在IT行业中,数据库是存储和管理数据的核心组件,而Java Bean和DAO(Data Access Object)则是Java编程中用于数据操作的重要概念。本知识点主要聚焦于如何自动根据数据库中的表结构生成对应的Java Bean类和DAO类,以...