2009-09-07 5 views

Respuesta

7

Si se trata de migrar una aplicación existente a hilos que usaba previamente identificadores automáticos, y tiene datos antiguos que deben migrarse ... entonces esta sería mi mejor opción (aunque no lo intenté). los comentarios de bienvenida):

  • cambiar sus identificadores de tipos de columna a bigints
  • enteran de más alto valor id actualmente en cualquier mesa.
  • fijar el valor de 'próxima alto' en la tabla de origen hilo a un valor más alto que se encuentran en las identificaciones

Si supuesto, esto sólo soluciona problemas con la columna de identidad, no nada más en su esquema que podría necesitar cambiar si está moviendo una aplicación a NHibernate.

+0

En realidad, no debe establecer el siguiente valor de hi a un valor superior al que se encuentra en los ID, consulte la respuesta de Stefan a continuación para obtener un buen enfoque. – andreialecu

+0

@legenden: cuidado para explicar por qué no? – UpTheCreek

+1

@UpTheCreek: es demasiado alto, pierdes muchos identificadores. En el archivo de mapeo, usted especifica cuántos identificadores puede generar para un solo valor en next-hi. next-hi es, por lo tanto, siempre más pequeño por algún factor que los identificadores generados. –

14

Necesita configurar la tabla utilizada por NH para crear valores HiLo correctamente. Deje que Schema Creator cree la tabla de acuerdo con sus definiciones de mapeo, establezca los valores de acuerdo con el estado actual de los identificadores en su base de datos.

creo (que necesita para verificar esto) que valores generados por hilo se calculan por:

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

Mientras que el alto valor se almacena en la base de datos, max_low definido en el archivo de asignación y de bajo valor calculado en tiempo de ejecución.


NHibernate también necesita su propia conexión y transacción para determinar e incrementar el valor alto. Por lo tanto, no funciona si la conexión proporciona la conexión.

Puede seguir usando seqhilo, NH usa una secuencia de base de datos para crear los siguientes valores altos y no necesita una conexión separada para hacerlo. Esto solo está disponible en bases de datos que admiten secuencias, como Oracle.


Corrección:

Mientras tanto, he tenido que aplicar yo mismo (antes, era sólo teoría :-). Entonces vuelvo a compartir los detalles.

La fórmula es:

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

next_hi es el campo en la base de datos tiene que actualizar. highest_id es la ID más alta que se encuentra en su base de datos. maxLow es el valor que especificó en el archivo de asignación. No idea por qué se incrementa en uno. La división es una definición entera que trunca los decimales.

+0

En caso de tener una mesa de hilo por entidad ¿mesa? – mcintyre321

0

Escribí un guión (basado de respuesta Esteban) para la fijación de los valores de Hilo (en el servidor SQL) - que se supone que tiene una tabla de hilo como

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

Y las columnas de identidad de su mesa están llamados ID. Inicie la tabla Entidad con los nombres de tabla para los que desea generar los valores del hilo. Al ejecutar el script generará una serie de instrucciones de actualización como éste:

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' 

Aquí es

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

Este es un ejemplo de una reciente migración del generador incremento para el MultipleHiLoPerTableGenerator (por ejemplo, una sola tabla se usa para almacenar valores altos para cada Entidad).

Mi aplicación utiliza archivos de mapeo Hibernate 3+ (.hbm.xml). Mi base de datos es MySQL (innoDB + auto incremento pk).

Paso 1: reemplace las configuraciones de su generador en sus archivos .hbm. Reemplazar:

<generator class="increment" /> 

Por

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

Paso 2: crear una nueva tabla para almacenar los valores altos

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; 

Paso 3: rellenar los valores altos iniciales de acuerdo a los datos existentes usando la siguiente pieza de SQL. Supongo que aquí se usa el mismo valor max_lo para cada tabla.

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

Aquí es una secuencia de comandos (MS SQL) que llenará la tabla Hilo (Nombre, Valor) con todos los números altos próximos para todas las tablas de base de datos actual:

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