15

ID列に大きく依存するデータベースを使用しています。ただし、すべてのアプリケーションをNHibernateに移行したので、NHibernateで推奨されているようにHiLoの使用を検討したいと思いました。これを行うための戦略、または注意すべき一般的な問題はありますか?

4

5 に答える 5

14

HiLo値を正しく作成するには、NHが使用するテーブルを設定する必要があります。Schema Creatorにマッピング定義に従ってテーブルを作成させ、データベース内のIDの現在の状態に従って値を設定します。

hiloによって生成される値は次のように計算されると思います(これを確認する必要があります)。

hilo-id = high-value * max_lo + low-value

高い値はデータベースに保存されますが、max_lowはマッピングファイルで定義され、低い値は実行時に計算されます。


NHibernateは、高い値を決定してインクリメントするために、独自の接続とトランザクションも必要とします。したがって、接続がアプリケーションによって提供されている場合は機能しません。

引き続き使用できますseqhilo。NHはデータベースシーケンスを使用して次の高い値を作成します。そのために個別の接続は必要ありません。これは、Oracleなどのシーケンスをサポートするデータベースでのみ使用できます。


修正:

その間、私はそれを自分で実装しなければなりませんでした(以前は、それは単なる理論でした:-)。それで、私は詳細を共有するために戻ってきます。

式は次のとおりです。

next_hi = (highest_id / (maxLow + 1)) + 1

next_hi更新する必要があるデータベースのフィールドです。highest_idデータベースで見つかった最高のIDです。maxLowマッピングファイルで指定した値です。なぜそれが1つ増えるのか分かりません。除算は、小数点以下を切り捨てる整数除算です。

于 2009-10-05T12:40:48.227 に答える
8

これが、以前は自動IDを使用していたhilosに既存のアプリケーションを移行することについての質問であり、移行する必要のある古いデータが含まれている場合は、これが最善の策です(ただし、試していない!-コメントを歓迎します!) :

  • 列タイプIDをbigintsに変更します
  • 現在任意のテーブルにある最大のID値を見つけます。
  • hiloソーステーブルの「next-high」値をIDで見つけた値よりも高い値に設定します

もちろん、これはID列の問題のみに対処し、アプリをNHibernateに移動する場合に変更する必要のあるスキーマ内の他の問題には対処しません。

于 2009-10-08T12:42:07.447 に答える
0

私は(SQLサーバー上で)hilo値を修正するためのスクリプト(Stephansの回答に基づく)を作成しました-それはあなたが次のようなhiloテーブルを持っていることを前提としています

CREATE TABLE [dbo].[HiloValues](
    [next_hi] [int] NULL,
    [Entity] [varchar](128) NOT NULL
)

また、テーブルのID列はすべてIDと呼ばれます。hilo値を生成するテーブル名でEntityテーブルを初期化します。スクリプトを実行すると、次のような一連の更新ステートメントが生成されます。

UPDATE hv 
SET next_hi = Transactions.ID/(10 + 1) + 1 
FROM HiloValues hv 
CROSS JOIN (SELECT ISNULL(Max(ID), 0) as id FROM Transactions) as Transactions
WHERE hv.entity = 'Transactions'

ここにあります

DECLARE @scripts TABLE(Script VARCHAR(MAX))
DECLARE @max_lo VARCHAR(MAX) = '10';

INSERT INTO @scripts
SELECT '
UPDATE hv 
SET next_hi = ' + Entity + '.ID/(' + @max_lo + ' + 1) + 1 
FROM HiloValues hv 
CROSS JOIN (SELECT ISNULL(Max(ID), 0) as id FROM ' + entity + ') as ' + entity + '
WHERE hv.entity = ''' + entity + '''' as script 
FROM HiloValues WHERE Entity IN (SELECT  name from sys.tables)



DECLARE curs CURSOR FOR SELECT * FROM @scripts
DECLARE @script VARCHAR(MAX)

OPEN curs 
FETCH NEXT FROM curs INTO @script

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @script --OR EXEC(@script)
    FETCH NEXT FROM curs INTO @script
END
CLOSE curs
DEALLOCATE curs
于 2012-03-01T11:24:58.253 に答える
0

これは、増分ジェネレーターからMultipleHiLoPerTableGeneratorへの最近の移行のサンプルです(たとえば、単一のテーブルを使用して、すべてのエンティティの高い値を格納します)。

私のアプリケーションはHibernate3+マッピングファイル(.hbm.xml)を使用しています。私のデータベースはMySQL(innoDB +自動インクリメントpk)です。

ステップ1:.hbmファイルのジェネレーター設定を置き換えます。交換 :

<generator class="increment" />

<generator class="org.hibernate.id.MultipleHiLoPerTableGenerator">
    <param name="table">hilo_values</param>
    <param name="primary_key_column">sequence_name</param>
    <param name="value_column">sequence_next_hi_value</param>
    <param name="max_lo">1000</param>
</generator>

ステップ2:高い値を格納するための新しいテーブルを作成します

CREATE TABLE IF NOT EXISTS `hilo_values` (
  `sequence_name` varchar(255) NOT NULL,
  `sequence_next_hi_value` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ステップ3:次のSQLを使用して、既存のデータに従って初期の高い値を入力します。ここではmax_lo、すべてのテーブルに同じ値が使用されていると想定しています。

INSERT INTO hilo_values SELECT TABLE_NAME,  ((AUTO_INCREMENT DIV (1000 + 1)) + 1) FROM information_schema.tables WHERE table_schema = 'yourdbname'
于 2013-04-16T15:06:49.293 に答える
0

これは、HiLo(Name、Value)テーブルに、現在のデータベース内のすべてのテーブルの次に大きい数値をすべて入力するスクリプト(MS SQL)です。

declare tables cursor for

    select
        Table_Schema,
        Table_Name
    from
        information_schema.tables
    where
        Table_Schema = 'dbo'
        and
        Table_Type = 'BASE TABLE'
        and
        Table_Name <> 'HiLo'
        and
        right (Table_Name, 1) <> '_'

declare @table_schema varchar(255)
declare @table_name varchar(255)

truncate table HiLo

open tables
fetch next from tables into @table_schema, @table_name

while (@@fetch_status = 0)
begin
    declare @sql as nvarchar(max)
    declare @max_id as int

    set @sql = 'select @max_id = max(Id) from [' + @table_schema + '].[' + @table_name + ']'
    exec sp_executesql @sql, N'@max_id int output', @max_id output

    declare @max_low as int
    set @max_low = 1000

    declare @next_high as int
    set @next_high = isnull (@max_id / @max_low + 1, 0)

    --select @table_name, @max_id, @next_high
    insert into HiLo (Name, Value) values (@table_schema + '.' + @table_name, @next_high)

    fetch next from tables into @table_schema, @table_name
end

close tables
deallocate tables

select * from HiLo
于 2013-06-26T10:43:35.280 に答える