我剛創建了一個自定義hibernate ID生成器,因爲我不是休眠專家,所以我想對我的代碼獲得一些反饋。生成的ID是select max(id) from table
,+1。下面的Hibernate自定義ID生成器代碼是否正確?
public class MaxIdGenerator implements IdentifierGenerator, Configurable {
private Type identifierType;
private String tableName;
private String columnName;
@Override
public void configure(Type type, Properties params, Dialect dialect) {
identifierType = type;
tableName = (String) params.getProperty("target_table");
columnName = (String) params.getProperty("target_column");
}
@Override
public synchronized Serializable generate(SessionImplementor session,
Object object) {
return generateHolder(session).makeValue();
}
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
Connection connection = session.connection();
try {
IntegralDataTypeHolder value = IdentifierGeneratorHelper
.getIntegralDataTypeHolder(identifierType
.getReturnedClass());
String sql = "select max(" + columnName + ") from " + tableName;
PreparedStatement qps = connection.prepareStatement(sql);
try {
ResultSet rs = qps.executeQuery();
if (rs.next())
value.initialize(rs, 1);
else
value.initialize(1);
rs.close();
} finally {
qps.close();
}
return value.copy().increment();
} catch (SQLException e) {
throw new IdentifierGenerationException(
"Can't select max id value", e);
}
}
}
我想知道:
- 我怎樣才能讓這個多事務安全? (即如果兩個併發事務插入數據,我怎麼能安全地假定我不會最終擁有兩次相同的ID?) - 我想這裏唯一的解決方案是防止兩個併發的hibernate事務同時運行如果他們使用相同的發生器,這可能嗎?
- 如果代碼可以改進:我覺得不對勁不必使用硬編碼,
"target_column"
,等...
爲了保證1點),我可以根據需要回退到上插入同步我的java客戶端代碼。
請不要評論我爲什麼使用這種類型的生成器的原因:遺留代碼仍將數據插入到同一數據庫並使用此機制...並且無法修改。是的,我知道,它很糟糕。