Hibernate - 解决多个查询问题

时间:2016-06-14 10:30:29

标签: java mysql spring hibernate

大家早上好,我想问你一个关于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。

0 个答案:

没有答案