2009-09-07 3 views

Antwort

7

Wenn es sich um eine Frage über die Migration einer bestehenden Anwendung auf Hilos handelt, die zuvor Auto-IDs verwendet hat und alte Daten darin enthalten sind, die migriert werden müssen, dann wäre dies meine beste Wette (nicht ausprobiert!) willkommen Kommentare):

  • Ihre Spaltentypen IDs bigints ändern
  • derzeit höchsten ID-Wert in einer Tabelle herausfinden.
  • Stellen Sie Ihren ‚nächste hohen‘ Wert in der Tabelle hilo Quelle auf einen höheren Wert, als Sie in dem IDs gefunden

Wenn Dies ist natürlich nur Adressen Probleme mit der Identitätsspalte, nicht irgendetwas anderes in Ihrem Schema, das muss möglicherweise geändert werden, wenn Sie eine App in NHibernate verschieben.

+0

Eigentlich sollte der Wert next-hi nicht höher als der Wert in den IDs gesetzt werden, siehe Stefan's Antwort unten für einen guten Ansatz. – andreialecu

+0

@legenden - warum nicht erklären? – UpTheCreek

+1

@UpTheCreek: Es ist zu hoch, Sie verlieren viele IDs. In der Mapping-Datei geben Sie an, wie viele IDs Sie für einen einzelnen Wert in next-hi generieren können. next-hi ist daher immer etwas kleiner als die generierten ids. –

14

Sie müssen die Tabelle einrichten, die von NH verwendet wird, um HiLo-Werte korrekt zu erstellen. Lassen Sie Schema Creator die Tabelle gemäß Ihren Zuordnungsdefinitionen erstellen, legen Sie die Werte entsprechend dem aktuellen Status der IDs in Ihrer Datenbank fest.

Ich glaube, (Sie müssen dies überprüfen), die von hilo erzeugten Werten werden berechnet durch:

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

Während der High-Wert in der Datenbank gespeichert ist, max_low in der Mapping-Datei definiert und von geringen Wert zur Laufzeit berechnet.


NHibernate benötigt auch eine eigene Verbindung und Transaktion, um den hohen Wert zu ermitteln und zu erhöhen. Daher funktioniert es nicht, wenn die Verbindung von der Anwendung bereitgestellt wird.

Sie können weiterhin seqhilo verwenden, NH verwendet eine Datenbanksequenz, um die nächsten hohen Werte zu erstellen, und benötigt dazu keine separate Verbindung. Dies ist nur für Datenbanken verfügbar, die Sequenzen wie Oracle unterstützen.


Korrektur:

Inzwischen habe ich es selbst zu implementieren hatte (vor, es war nur Theorie :-). Also komme ich zurück, um die Details zu teilen.

Die Formel lautet:

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

next_hi das Feld in der Datenbank Sie aktualisieren müssen. highest_id ist die höchste ID in Ihrer Datenbank. maxLow ist der Wert, den Sie in der Zuordnungsdatei angegeben haben. Keine Idee, warum es um eins erhöht wird. Die Division ist eine Integer-Division, die die Dezimalstellen abschneidet.

+0

Sollten Sie eine hilo Tabelle pro Einheit haben Tabelle? – mcintyre321

0

schrieb ich ein Drehbuch (basierend Antwort Stephans) für hilo Werte Festsetzung (auf SQL Server) - es wird davon ausgegangen, dass Sie eine hilo Tisch haben wie

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

Und Ihre Tabelle Identität Spalten werden alle ID genannt. Initiieren Sie die Entitätstabelle mit den Tabellennamen, für die Sie die Hilo-Werte generieren möchten.

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' 

es hier

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 
0

Hier ist ein Beispiel aus einer aktuellen Migration vom Generator zum MultipleHiLoPerTableGenerator Zuwachs ist: das Skript ausführen, wird eine Reihe von Update-Anweisungen wie diese erzeugt (ZB eine einzelne Tabelle wird verwendet, um hohe Werte für jede Entitäten zu speichern).

Meine Anwendung verwendet Hibernate 3 + Mapping-Dateien (.hbm.xml). Meine Datenbank ist MySQL (innoDB + auto increment pk).

Schritt 1: Ersetzen Sie Ihre Generatoreinstellungen in Ihren .hbm-Dateien. Ersetzen :

<generator class="increment" /> 

von

<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> 

Schritt 2: Erstellen einer neuen Tabelle, die die hohen Werte speichern

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; 

Schritt 3: die anfängliche hohe Werte bevöl nach zu bestehenden Daten mit dem folgenden Stück SQL. Ich gehe hier davon aus, dass für jede Tabelle der gleiche max_lo Wert verwendet wird.

INSERT INTO hilo_values SELECT TABLE_NAME, ((AUTO_INCREMENT DIV (1000 + 1)) + 1) FROM information_schema.tables WHERE table_schema = 'yourdbname' 
0

Hier ist ein Skript (MS SQL), die HiLo (Name, Wert) Tabelle in der aktuellen Datenbank für alle Tabellen mit allen nächsten hohen Zahlen füllt:

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 
Verwandte Themen