由于设计上的需要,所以不得不自己生成流水号。
思路:使用一个表记载流水,每次取的同时增加1,所以下一个用户取的时候就是新的流水号了。不过必须在一个事务中实现,否则可能会有问题的。
设计表 create table Sequence(id int,sequenceid int) id的意思是用于不同的流水号,sequenceid 是存储的流水号值。
insert into Sequence(id,sequence) values (10,1)
设计类
public class TableKeyGenerator extends TableGenerator {
/**
* The column parameter
*/
public static final String COLUMN = "column";
/**
* The table parameter
*/
public static final String TABLE = "table";
/**
* The key column name
*/
public static final String KEY_COLUMN_NAME = "key_column";
/**
* The key value
*/
public static final String KEY_VALUE = "key_value";
private static final Log log = LogFactory.getLog(TableGenerator.class);
private String keyColumnName;
private String keyValue;
private String tableName;
private String columnName;
private String query;
private String update;
public void configure(Type type, Properties params, Dialect dialect) {
this.keyColumnName = PropertiesHelper.getString(KEY_COLUMN_NAME,
params, "");
this.keyValue = PropertiesHelper.getString(KEY_VALUE, params, "");
this.tableName = PropertiesHelper.getString(TABLE, params,
"hibernate_unique_key");
this.columnName = PropertiesHelper.getString(COLUMN, params, "next_hi");
String schemaName = params.getProperty(SCHEMA);
if (schemaName != null && tableName.indexOf(StringHelper.DOT) < 0)
tableName = schemaName + '.' + tableName;
query = "select " + columnName + " from " + tableName;
if (keyColumnName != null && keyColumnName.trim().length() > 0)
query += " where " + keyColumnName + "=" + keyValue;
if (dialect.supportsForUpdate())
query += " for update";
update = "update " + tableName + " set " + columnName + " = ? where "
+ columnName + " = ?";
if (keyColumnName != null && keyColumnName.trim().length() > 0)
update += " and " + keyColumnName + " = " + keyValue;
}
public synchronized Serializable generate(SessionImplementor session, Object object)
throws SQLException, HibernateException {
// This has to be done using a different connection to the
// containing transaction because the new hi value must
// remain valid even if the containing transaction rolls
// back
Connection conn = session.getBatcher().openConnection();
int result;
int rows;
try {
do {
// The loop ensures atomicity of the
// select + update even for no transaction
// or read committed isolation level
PreparedStatement qps = conn.prepareStatement(query);
try {
ResultSet rs = qps.executeQuery();
if ( !rs.next() ) {
String err = "could not read a hi value - you need to populate the table: " + tableName;
log.error(err);
throw new IdentifierGenerationException(err);
}
result = rs.getInt(1);
rs.close();
}
catch (SQLException sqle) {
log.error("could not read a hi value", sqle);
throw sqle;
}
finally {
qps.close();
}
PreparedStatement ups = conn.prepareStatement(update);
try {
ups.setInt( 1, result + 1 );
ups.setInt( 2, result );
rows = ups.executeUpdate();
}
catch (SQLException sqle) {
log.error("could not update hi value in: " + tableName, sqle);
throw sqle;
}
finally {
ups.close();
}
}
while (rows==0);
conn.commit();
return new Integer(result);
}
finally {
session.getBatcher().closeConnection(conn);
}
}
}
table.hbm.xml
<id name="articleid" column="ArticleID" type="java.lang.Integer">
<generator class="com.hc.util.TableKeyGenerator">
<param name="table">Sequence</param>
<param name="column">sequenceid</param>
<param name="key_column">id</param>
<param name="key_value">10</param>
</generator>
</id>