我有User一Log堂课(我不能改变):
User
Log
class User { private long id; private String name; private Set<Log> accessLogs; private Set<Log> actionLogs; } class Log { private String what; private Date when; }
可能的映射如下所示:
<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>
这可以正常工作并映射到以下数据库表:
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 | +---------+---------------+---------------------+
我的问题是,在hibernate状态下如何将这两个集合(accessLogs和actionLogs)映射到同一表中,从而为日志生成以下架构:
accessLogs
actionLogs
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 | +---------+---------------+---------------------+--------+
编辑 :我想保留Java代码并按原样设置语义。我正在寻找诸如鉴别器,公式或hibernateAPI扩展之类的东西,这些东西可以解决此问题而无需接触Java代码。可能有些事情(虚构的hibernate配置如下):
<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 :我还没有完整的解决方案。我确信可以做到这一点,可能是通过扩展一些hibernateAPI来实现的。
正如Maurizio所写,您需要使用where属性来仅检索属于每个集合的行。
where
要使用附加列 插入 行,您需要在内添加以下元素<set>:
<set>
<sql-insert> insert into user_logs(user_id, what, [when], type) values(?, ?, ?, 'access') </sql-insert>
从本质上讲,这告诉Hibernate使用该特定SQL而不是生成它。请注意,我必须手动转义该when列。
when
奖励:向数据库中添加额外的列,请使用以下命令(关闭之后<class>)
<class>
<database-object> <create>alter table user_logs add type char(6)</create> <drop></drop> </database-object>
有趣的一点:我使用 NHibernate 编写并测试了此代码,但是它是直接移植的,因此它应该完全一样。