大家早上好,我想问你一个关于Hibernate如何处理内部对象引用的问题,以及连续获取这些实体时的JOIN查询。
我有一组按以下方式组织的实体:
Entity.java
@Entity
@Table(name = "EVENT")
public class Event extends CommonEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne(optional = false)
@JoinColumn(name = "TIME_SLOT_ID")
private TimeSlot timeSlot;
@ManyToOne(optional = false)
@JoinColumn(name = "ROOM_ID")
private Room room;
@ManyToOne(optional = false)
@JoinColumn(name = "TRACK_ID")
private Track track;
(...)
Room.java
@Entity
@Table(name = "ROOM")
public class Room extends CommonEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne(optional = false)
@Fetch(value = FetchMode.JOIN)
@JoinColumn(name = "VENUE_ID")
private Venue venue;
@NotEmpty
@Column(name = "NAME", nullable = false, length = 30)
private String name;
(...)
Venue.java
@Entity
@Table(name = "VENUE")
public class Venue extends CommonEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@NotEmpty
@Column(name = "NAME", nullable = false, length = 60)
private String name;
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "VENUE_TYPE_ID")
private VenueType venueType;
(...)
VenueType.java
@Entity
@Table(name = "VENUE_TYPE")
public class VenueType extends CommonEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@NotEmpty
@Column(name = "NAME", nullable = false, length = 30)
private String name;
(...)
正如大家们所看到的,我试图在大多数地方使用@Fetch
来避免N + 1 problem
,并检查了SO上的其他问题。生成的查询总是这样:
Hibernate:
select
this_.id as id1_0_6_,
this_.DESCRIPTION as DESCRIPT2_0_6_,
this_.EVENT_TYPE_ID as EVENT_TY6_0_6_,
this_.MINIMUM_SIZE as MINIMUM_3_0_6_,
this_.NAME as NAME4_0_6_,
this_.ROOM_ID as ROOM_ID7_0_6_,
this_.TAGS as TAGS5_0_6_,
this_.TIME_SLOT_ID as TIME_SLO8_0_6_,
this_.TRACK_ID as TRACK_ID9_0_6_,
eventtype2_.id as id1_1_0_,
eventtype2_.NAME as NAME2_1_0_,
room3_.id as id1_2_1_,
room3_.NAME as NAME2_2_1_,
room3_.SIZE as SIZE3_2_1_,
room3_.VENUE_ID as VENUE_ID4_2_1_,
roomfacili4_.ROOM_ID as ROOM_ID1_2_8_,
roomfacili5_.id as ROOM_FAC2_4_8_,
roomfacili5_.id as id1_3_2_,
roomfacili5_.AMOUNT as AMOUNT2_3_2_,
roomfacili5_.NAME as NAME3_3_2_,
roomfacili5_.SERIAL_ID as SERIAL_I4_3_2_,
venue6_.id as id1_10_3_,
venue6_.ADDRESS as ADDRESS2_10_3_,
venue6_.COUNTRY as COUNTRY3_10_3_,
venue6_.NAME as NAME4_10_3_,
venue6_.POSTCODE as POSTCODE5_10_3_,
venue6_.TOWN as TOWN6_10_3_,
venue6_.VENUE_TYPE_ID as VENUE_TY7_10_3_,
timeslot7_.id as id1_5_4_,
timeslot7_.ENDING_DATE as ENDING_D2_5_4_,
timeslot7_.STARTING_DATE as STARTING3_5_4_,
track8_.id as id1_6_5_,
track8_.DESCRIPTION as DESCRIPT2_6_5_,
track8_.NAME as NAME3_6_5_
from
EVENT this_
inner join
EVENT_TYPE eventtype2_
on this_.EVENT_TYPE_ID=eventtype2_.id
inner join
ROOM room3_
on this_.ROOM_ID=room3_.id
left outer join
ROOM_ROOM_FACILITY roomfacili4_
on room3_.id=roomfacili4_.ROOM_ID
left outer join
ROOM_FACILITY roomfacili5_
on roomfacili4_.ROOM_FACILITY_ID=roomfacili5_.id
left outer join
VENUE venue6_
on room3_.VENUE_ID=venue6_.id
inner join
TIME_SLOT timeslot7_
on this_.TIME_SLOT_ID=timeslot7_.id
inner join
TRACK track8_
on this_.TRACK_ID=track8_.id
with,取决于我留下@Fetch
注释的位置,有时甚至对VenueType
实体进行第二次查询。在访问/event
URL时,仍然会导致Spring构建VenueType页面而不是Event页面。
真正的问题是当我尝试从数据库中获取我的实体事件(访问/event
URL)时,我想在屏幕上显示结果。但是,由于多次查询,Spring打开了另一组页面(同样来自VenueType
的JSP文件,因为稍后查询过)。
如果我将任何引用的对象更改为Lazy抓取(例如Event
中的“room”属性),则会加载Lazy-fetched对象JSP(在此示例中为Room
JSP文件)。
感谢任何帮助。感谢您的关注。
编辑:在这种情况下,我使用Criteria API创建查询,而不是直接的JPQL / HQL。