我有一个
eventchangelog
表和一个 user
表,我正在尝试根据用户名列将 User
对象映射到 eventChangeLog 条目。 user 表将 username 作为唯一字段,但出于业务原因,我无法在 eventchangelog.createdby 和 user.username 之间添加外键约束。
问题
我只想将用户名存储在 eventchangelog 中,但希望 Hibernate 在获取 EventChangeLog 条目时加载整个 User 对象(名字、姓氏、用户名等)。但是,除非我在 HQL 查询中使用构造函数,否则我在将 User 映射到我的 EventChangeLog 类时遇到问题。
这是我正在处理的内容: EventChangeLog 类
@NoArgsConstructor
@Getter
@Setter
public class EventChangeLog {
private long id;
private Event event;
private String createdByUsername;
private User createdBy;
// Constructor initializes all fields except `id`
}
EventChangeLog Hibernate 映射
<hibernate-mapping>
<class name="org.event.EventChangeLog" table="eventchangelog">
<id name="id" column="eventchangelogid">
<generator class="sequence">
<param name="sequence_name">eventchangelog_sequence</param>
</generator>
</id>
<many-to-one name="event" class="org.event.Event"
column="eventid" foreign-key="fk_eventchangelog_eventid" not-null="true"/>
<property name="createdByUsername" column="createdby" type="string"/>
<many-to-one name="createdBy" class="org.event.User" insert="false" update="false" property-ref="username">
<column name="createdby"/>
</many-to-one>
</class>
</hibernate-mapping>
用户类别
@NoArgsConstructor
@Getter
@Setter
public class User {
private String username;
private String surname;
private String firstName;
}
用户休眠映射
<hibernate-mapping>
<class name="org.event.User" lazy="false" table="userinfo">
<property name="username" column="username" not-null="true" unique="true"/>
<property name="surname" not-null="false" length="160"/>
<property name="firstName" not-null="false" length="160"/>
</class>
</hibernate-mapping>
尝试查询
When I use this HQL query with a constructor, it maps everything correctly:
String hql = """
select new org.event.EventChangeLog(
ecl.event,
ecl.createdByUsername,
ecl.createdBy
)
from EventChangeLog ecl
join ecl.event e
left join ecl.createdBy
where e.uid = :eventUid
""";
但是,如果我使用以下查询(应直接映射到 EventChangeLog),则不会映射 User 对象 (createdBy):
String hql = """
select ecl
from EventChangeLog ecl
join ecl.event e
left join ecl.createdBy
where e.uid = :eventUid
""";
我尝试过的事情
如何配置 Hibernate 以使用
User
列将 EventChangeLog
对象映射到 username
,而不在 HQL 查询中使用构造函数?
在 HQL 查询中,您可以使用自定义结果转换器在 EventChangeLog 上手动设置 User 对象,而不是依赖 Hibernate 自动映射 User 对象。即使没有外键约束,这种方法也允许您检索所需的字段并映射它们(通过设置 ResultTransformer)。
以下是如何执行此操作的示例:
Query query = session.createQuery("""
select ecl.id, ecl.event, ecl.createdByUsername, u
from EventChangeLog ecl
join ecl.event e
left join User u on ecl.createdByUsername = u.username
where e.uid = :eventUid
""");
query.setParameter("eventUid", eventUid);
query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<EventChangeLog> results = query.list();
如果您想更改所选数据,您可以有一个匹配的 DTO 类并调用:
query.setResultTransformer(new AliasToBeanResultTransformer(EventChangeLogDTO.class));
此方法显式获取 EventChangeLog 字段和关联的 User,然后在 EventChangeLog 上手动设置 User 对象。