Pregunta

Tengo un User una clase Log (que no puede modificar):

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>

Esto funciona bien y mapas en las siguientes tablas de 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 ¿cómo 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 que es. Busco algo así como un discriminador, una fórmula o una extensión de la API de hibernación, que va a resolver esto sin tocar el código 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 tengo una solución completa para esto todavía. Estoy seguro de que se puede hacer, posiblemente, extendiendo parte del API de hibernación.

¿Fue útil?

Solución

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

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

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

Bono: para agregar la columna adicional a la base de datos, utilice la 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: me escribió y probado esta utilizando NHibernate , pero fue portado directamente, por lo que debería funcionar exactamente el mismo

.

Otros consejos

¿Se intenta asignar conjunto de esta manera:

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

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

EDITAR - Si desea conservar tener 2 listas, a continuación, crear una tercera lista que es la combinación, y sólo persisten eso. Usted tiene que controlar el acceso a métodos de acceso de las dos listas, para que sepa cuándo actualizar el tercero, pero no debe ser demasiado duro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top