2009-09-07 11 views

risposta

7

Se questa è una domanda sulla migrazione di un'applicazione esistente a hilos che in precedenza utilizzava id automatici e contiene vecchi dati che devono essere migrati ... questa sarebbe la mia migliore scommessa (non provatela però! Comments benvenuto!):

  • cambiare il vostro tipi di colonna ID per bigints
  • scoprire il valore più alto id attualmente in qualsiasi tavolo.
  • impostare il proprio 'next-alto' valore nella tabella di origine Hilo a un valore superiore a quello che si trova nelle ID

Se Naturalmente questo unici problemi indirizzi con la colonna di identità, non è niente altro nello schema che potrebbe essere necessario cambiare se stai spostando un'app su NHibernate.

+0

In realtà, non dovresti impostare il valore next-hi su un valore superiore a quello trovato negli ID, vedi la risposta di Stefan sotto per un buon approccio. – andreialecu

+0

@legenden - cura di spiegare perché no? – UpTheCreek

+1

@UpTheCreek: è troppo alto, perdi molti ID. Nel file di mappatura, si specifica quanti ID è possibile generare per un singolo valore in next-hi. next-hi è quindi sempre più piccolo di qualche fattore come gli id ​​generati. –

14

è necessario impostare la tabella utilizzata da NH per creare correttamente i valori di Hilo. Consenti a Schema Creator di creare la tabella in base alle definizioni di mapping, impostare i valori in base allo stato corrente degli ID nel database.

credo (è necessario verificare questo) che i valori generati da Hilo sono calcolate da:

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

Mentre il-alto valore viene memorizzato nel database, max_low definito nel file di mappatura e di scarso valore calcolato in fase di esecuzione.


Anche NHibernate necessita di una propria connessione e transazione per determinare e incrementare il valore elevato. Pertanto non funziona se la connessione è fornita dall'applicazione.

È ancora possibile utilizzare seqhilo, NH utilizza una sequenza di database per creare valori alti successivi e non ha bisogno di una connessione separata per farlo. Questo è disponibile solo su database che supportano sequenze, come Oracle.


Correzione:

Nel frattempo, ho dovuto implementare io stesso (prima, era solo teoria :-). Quindi torno a condividere i dettagli.

La formula è:

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

next_hi è il campo nel database è necessario aggiornare. highest_id è l'ID più alto trovato nel tuo database. maxLow è il valore specificato nel file di mapping. Nessuna idea perché è incrementata di uno. La divisione è una deviazione intera che tronca le cifre decimali.

+0

Qualora vi siano tavolo Hilo per entità tavolo? – mcintyre321

0

Ho scritto uno script (basata su Stefano risposta) per stabilire i valori per Hilo (su un server di SQL) - si presuppone che si dispone di una tabella di Hilo come

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

E colonne di identità della vostra tabella sono tutti chiamati ID. Inizia la tabella Entità con i nomi tabella per i quali vuoi generare i valori hilo. Esecuzione dello script genera una serie di istruzioni di aggiornamento come questo:

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' 

Qui è

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

Ecco un esempio da una recente migrazione dal incremento generatore al MultipleHiLoPerTableGenerator (ad es. una singola tabella è usata per memorizzare valori alti per ogni Entità).

La mia applicazione utilizza i file di mappatura di Hibernate 3 + (.hbm.xml). Il mio database è MySQL (innoDB + auto increment pk).

Fase 1: sostituire le impostazioni del generatore nei file .hbm. Sostituire:

<generator class="increment" /> 

Con

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

Fase 2: creare una nuova tabella per memorizzare i valori alti

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; 

Fase 3: popolare i valori iniziali elevati secondo a dati esistenti utilizzando il seguente pezzo di SQL. Presumo qui che lo stesso valore max_lo sia utilizzato per ogni tabella.

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

Ecco uno script (MS SQL) che riempirà tavolo per Hilo (nome, valore), con tutti i prossimi numeri alti per tutte le tabelle nel database corrente:

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