カスタムの休止状態 ID ジェネレーターを作成しました。休止状態の専門家ではないので、自分のコードに関するフィードバックが欲しいです。生成された ID はselect max(id) from table
、+1 です。
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);
}
}
}
知りたい:
- このマルチトランザクションセーフを作成するにはどうすればよいですか? (つまり、2 つの同時トランザクションがデータを挿入する場合、同じ ID が 2 度存在しないと安全に仮定するにはどうすればよいでしょうか?) -- ここでの唯一の解決策は、2 つの同時休止状態トランザクションが同時に実行されるのを防ぐことだと思います。彼らが同じジェネレーターを使用している場合、これは可能ですか?
- コードを改善できる場合:ハードコードされた 、などを使用する必要
"select"
があるとは思えません"target_column"
...
ポイント 1) を保証するために、必要に応じて、Java クライアント コードの挿入を同期する際にフォールバックできます。
私がこの種のジェネレーターを使用している理由についてコメントしないでください: レガシー コードは依然として同じデータベースにデータを挿入し、このメカニズムを使用しています...そして変更することはできません。そして、はい、私は知っています、それはひどいです。