2010-11-05 11 views
11

Tengo un User una clase Log (que no puedo cambiar):mapeo de múltiples sistemas en una mesa en hibernación

class User { 
    private long id; 
    private String name; 
    private Set<Log> accessLogs; 
    private Set<Log> actionLogs; 
} 

class Log { 
    private String what; 
    private Date when; 
} 

Una posible asignación se verá así:

<class name="com.example.User" table="users"> 
    <id name="id" access="field"> 
     <generator class="native" /> 
    </id> 

    <property name="name" length="256" /> 

    <set name="accessLogs" table="user_access_logs" cascade="all-delete-orphan" order-by="`when`"> 
     <key column="user_id" /> 
     <composite-element class="com.example.Log"> 
      <property name="what" length="512" /> 
      <property name="when" column="`when`" /> 
     </composite-element> 
    </set> 

    <set name="actionLogs" table="user_action_logs" cascade="all-delete-orphan" order-by="`when`"> 
     <key column="user_id" /> 
     <composite-element class="com.example.Log"> 
      <property name="what" length="512" /> 
      <property name="when" column="`when`" /> 
     </composite-element> 
    </set> 

</class> 

Este funciona bien y se asigna en las siguientes tablas de la base de datos:

users 
+----+------+ 
| id | name | 
+----+------+ 
| 1 | john | 
| 2 | bill | 
| 3 | nick | 
+----+------+ 

user_access_logs 
+---------+------------+---------------------+ 
| user_id | what  | when    | 
+---------+------------+---------------------+ 
|  1 | logged in | 2010-09-21 11:25:03 | 
|  1 | logged out | 2010-09-21 11:38:24 | 
|  1 | logged in | 2010-09-22 10:19:39 | 
|  2 | logged in | 2010-09-22 11:03:18 | 
|  1 | logged out | 2010-09-22 11:48:16 | 
|  2 | logged in | 2010-09-26 12:45:18 | 
+---------+------------+---------------------+ 

user_action_logs 
+---------+---------------+---------------------+ 
| user_id | what   | when    | 
+---------+---------------+---------------------+ 
|  1 | edit profile | 2010-09-21 11:28:13 | 
|  1 | post comment | 2010-09-21 11:30:40 | 
|  1 | edit profile | 2010-09-21 11:31:17 | 
|  1 | submit link | 2010-09-22 10:21:02 | 
|  2 | submit review | 2010-09-22 11:10:22 | 
|  2 | submit link | 2010-09-22 11:11:39 | 
+---------+---------------+---------------------+ 

Mi pregunta es h ow es posible en hibernación para asignar esos 2 juegos (accessLogs y actionLogs) en la misma tabla que produce el siguiente esquema para los registros:

user_logs 
+---------+---------------+---------------------+--------+ 
| user_id | what   | when    | type | 
+---------+---------------+---------------------+--------+ 
|  1 | logged in  | 2010-09-21 11:25:03 | access | 
|  1 | edit profile | 2010-09-21 11:28:13 | action | 
|  1 | post comment | 2010-09-21 11:30:40 | action | 
|  1 | edit profile | 2010-09-21 11:31:17 | action | 
|  1 | logged out | 2010-09-21 11:38:24 | access | 
|  1 | logged in  | 2010-09-22 10:19:39 | access | 
|  1 | submit link | 2010-09-22 10:21:02 | action | 
|  2 | logged in  | 2010-09-22 11:03:18 | access | 
|  2 | submit review | 2010-09-22 11:10:22 | action | 
|  2 | submit link | 2010-09-22 11:11:39 | action | 
|  1 | logged out | 2010-09-22 11:48:16 | access | 
|  2 | logged in  | 2010-09-26 12:45:18 | access | 
+---------+---------------+---------------------+--------+ 

Editar: Quiero conservar el código Java y Set semántica es. Estoy buscando algo así como un discriminador, una fórmula o una extensión de API de hibernación que resolverá esto sin tocar el código de Java. Tal vez algo en la línea (imaginaria configuración de hibernación sigue):

<set name="accessLogs" table="user_logs" ... formula="type='access'"> 
    <key column="user_id" /> 
    <composite-element class="Log"> 
     ... 
    </composite-element> 
</set> 

<set name="actionLogs" table="user_logs" ... formula="type='action'"> 
    <key column="user_id" /> 
    <composite-element class="Log"> 
     ... 
    </composite-element> 
</set> 

Edit2: No he conseguido una solución completa para esto todavía. Estoy seguro de que se puede hacer, posiblemente ampliando alguna API de hibernación.

Respuesta

5

Como escribió Maurizio, es necesario utilizar el atributo where para recuperar sólo las filas que pertenecen a cada colección.

Para inserción filas utilizando la columna adicional, es necesario añadir el siguiente elemento en el interior del <set>:

<sql-insert> 
    insert into user_logs(user_id, what, [when], type) 
    values(?, ?, ?, 'access') 
</sql-insert> 

que le dice a Hibernate esencialmente de usar que SQL específica en lugar de generarla. Tenga en cuenta que tuve que escapar manualmente de la columna when.

Bonus: para agregar la columna adicional a la base de datos, utilice el siguiente (después de cerrar la <class>)

<database-object> 
    <create>alter table user_logs add type char(6)</create> 
    <drop></drop> 
</database-object> 

poco interesante: he escrito y probado esto utilizando NHibernate, pero fue portado directamente, por lo tanto, debería funcionar exactamente igual.

+0

Eso es exactamente de lo que estaba hablando. Mega gracias! – cherouvim

1

¿Por qué no funciona simplemente combinar las listas en una lista? Ambas listas son de la misma clase.

EDITAR - Si desea conservar 2 listas, cree una tercera lista que sea la combinación, y solo persista eso. Deberá controlar el acceso a los descriptores de acceso de las dos listas, para que sepa cuándo actualizar el tercero, pero no debería ser demasiado difícil.

+0

Me gustaría resolver esto solo cambiando el código de mapeo de hibernación. – cherouvim

+0

@cherouvim si tiene 2 juegos, necesita asignar los conjuntos. Si quieres un juego, debes cambiar tu código. – hvgotcodes

+0

Necesito 2 juegos y puedo asignarlos, pero los quiero mapeados en una sola tabla. – cherouvim

11

¿trató de conjunto de mapas de esta manera:

<set name="accessLogs" table="user_logs" where="type='access'">  
+0

Gracias, eso rocas. Ahora solo tengo que encontrar una forma de inyectar "acceso" a una columna de tipo que no existe en mi modelo. – cherouvim

+1

+1 Esto es lo que hice en una situación similar, y está funcionando bien. – oksayt

+0

Sí, pero no puedo distinguir entre registros de acceso y acción, ya que la tabla user_logs solo tiene 'user_id',' what', 'when'. – cherouvim

Cuestiones relacionadas