主キーに Oracle の SYS_GUID() を使用するように Hibernate を構成する
質問
Oracleのを使用するために休止状態になる方法を探しています SYS_GUID()
新しい行を挿入するときの関数。現在、私の DB テーブルには SYS_GUID()
デフォルトとして設定されているため、Hibernate が単に値を省略した SQL を生成した場合は機能するはずです。
すべて動作していますが、現在 system-uuid ジェネレーターを使用してコードで UUID/GUID を生成しています。
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "PRODUCT_ID", unique = true, nullable = false)
public String getId() {
return this.productId;
}
これは問題ありませんが、GUID がデータベースによって生成された方が連続的であり、パフォーマンスが向上する可能性があります。さらに、これを構成する方法を知りたいだけです。
設定にはアノテーションを使用していますが、XML 設定例も素晴らしいです。
以下にテーブル定義のサンプルを示します (重要な場合に備えて)。
CREATE TABLE SCHEMA_NAME.PRODUCT
(
PRODUCT_ID RAW(16) DEFAULT SYS_GUID() NOT NULL,
PRODUCT_CODE VARCHAR2(10 CHAR) NOT NULL,
PRODUCT_NAME VARCHAR2(30 CHAR) NOT NULL,
PRODUCT_DESC VARCHAR2(512 CHAR)
)
アップデート:
「guid」を使用する Mat の解決策は機能しました。生成された SQL は次のとおりです。
Hibernate:
select rawtohex(sys_guid())
from dual
Hibernate:
insert into PRODUCT
(PRODUCT_CODE, PRODUCT_DESC, LOB_ID, PRODUCT_NAME, PROVIDER_ID, PRODUCT_ID)
values (?, ?, ?, ?, ?, ?)
挿入で列のデフォルト値を使用することはできないようです。そのため、アプリケーションで生成された GUID とデータベースのラウンドトリップの間で選択することになります。
解決
「guid」ジェネレーターを使用できる場合があります。見る この郵便受け Hibernate フォーラムから。を使用してOracleのサポートを追加したようです SYS_GUID()
少し前ですが、 ドキュメンテーション 依然として SQL Server と MySQL のみをサポートしていると述べています。
JPA アノテーションはまだ使用していませんが、XML 構成を使用した例を次に示します。
<id name="PRODUCT_ID">
<generator class="guid" />
</id>
編集: 2 番目の質問に関しては、なぜ Hibernate が次のようなことができないのかを尋ねていると思います。
INSERT INTO PRODUCT (PRODUCT_ID, /* etc */)
SELECT SYSGUID(), /* etc */
その理由は、Hibernate がオブジェクトの ID を認識している必要があるためです。たとえば、次のシナリオを考えてみましょう。
- 新しい Product オブジェクトを作成して保存します。Oracle が ID を割り当てます。
- 製品を Hibernate セッションから切り離します。
- 後で再接続し、いくつかの変更を加えます。
- ここで、これらの変更を永続化したいと考えます。
ID がわからないと、Hibernate はこれを行うことができません。UPDATE ステートメントを発行するには ID が必要です。したがって、の実装は、 org.hibernate.id.GUIDGenerator
事前に ID を生成し、後で INSERT ステートメントでそれを再使用する必要があります。
これは Hibernate ができないのと同じ理由です 任意のバッチ処理 データベースで生成された ID (それをサポートするデータベースでの自動インクリメントを含む) を使用する場合。一度に多数のオブジェクトを挿入するときに優れたパフォーマンスを得るには、hilo ジェネレーターの 1 つ、または他の Hibernate 生成の ID メカニズムを使用することが唯一の方法です。
他のヒント
トピックスターターと同じタスクがあります。感謝をこめて @マット・ソルニット このような注釈を使用することを提案します。
@Id
@NotNull
@Column(name = "UUID")
@GenericGenerator(name = "db-uuid", strategy = "guid")
@GeneratedValue(generator = "db-uuid")
private String uuid;
public String getUuid() { return uuid; }
public void setUuid(String uuid) { this.uuid = uuid; }
strategy = "guid"
そして String
タイプはソリューションの重要な部分です。
新しいエンティティを永続化する前に、Hibernate は SQL クエリを発行します。
select rawtohex(sys_guid()) from dual
私のセットアップ:Oracle 11、Hibernate 4.3.4.Final、Spring 3.2.x。そしてフィールドは raw(16)
を使用する場合よりも効率的なストレージとより小さいインデックスサイズのためにテーブルに char(32)
.
使おうとすると java.util.UUID
IDフィールドタイプとして、新しいエンティティを永続化するとHibernateからエラーが発生します(設定しようとします) String
に入力します java.util.UUID
分野)。
私も使っています javax.xml.bind.DatatypeConverter
非 Hibernate クエリ (Spring JDBC ヘルパー) の場合、convert を渡す場合 byte[]
:
String query = "insert into TBL (UUID, COMPANY) values (:UUID, :COMPANY)";
MapSqlParameterSource parameters = new MapSqlParameterSource()
.addValue("COMPANY", repo.getCompany())
.addValue("UUID", DatatypeConverter.parseHexBinary(signal.getUuid()));
namedJdbcTemplate.update(query, parameters);
抽出用:
ResultSet rs;
sig.id = DatatypeConverter.printHexBinary(rs.getBytes("UUID"));
すべての Web コントローラーは次のようなコードを取得します。
025131763FB19522E050010A106D11E9
それなし {
, -
, }
chars (UUID の通常の表現は {a-b-c-d-x-y}
覚えていれば)。この表現はすでに URL エンコードされており、クリーンかつ安全です。実装する必要はありません PropertyEditor
または Convertor
のために String
タイプ:
@RequestMapping(value = {"/signal/edit/{id}.htm"}, method = RequestMethod.POST)
public String handleEditRequest(
@PathVariable("id") String id,
失敗した使用試行と比較する jaa.util.UUID
, 、ここで書く必要があります:
@Component
public static class UUIDPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(final String str) {
if (str == null || str.isEmpty()) {
setValue(null);
return;
}
setValue(UUID.fromString(str));
}
}
private @Autowired UUIDPropertyEditor juuidPE;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(UUIDPropertyEditor.class, juuidPE);
}
使用するには:
@PathVariable("id") UUID id,
ジェネレーターをネイティブに設定すればできると思います。Hibernate でそれを行う方法はよくわかりませんが、NHibernate では XML で次のようなことを行うことになります。
<id column="PRODUCT_ID">
<generator class="native"/>
</id>