`
rustlingwind
  • 浏览: 20878 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

hibernate 多对多关系 一个很奇怪的问题

阅读更多
今天调了一下午程序,就是为了弄清为何我在保存视频的时候,除了update语句,莫名其妙地还执行了一句抓取视频所有标签的语句。并且这个语句非常雷,以前见过的无非就是两个表的联合查询,这条语句直接将视频表、标签表和视频标签的关系表 总共三个表做了关联查询。这个查询的效率自然不言而喻。而且查出来的结果集因为是三个表的笛卡尔积,也肯定很惊人。总之就是效率瓶颈了。

说了这么一大堆,其实我的程序很简单,一个视频类(Video),一个标签类(Tag),两个类是单向多对多的关系。因为同一个标签对应的视频可能很多很多,所以就没有必要在标签类中包含视频的set了。

@Entity
@Table(name="vid_video")
public class Video extends BaseEntity {

...

@ManyToMany(
        cascade ={CascadeType.PERSIST,CascadeType.MERGE},
        fetch=FetchType.LAZY
    )
    @JoinTable(
            name="vid_video_tag",
            joinColumns={@JoinColumn(name="video_id")},
            inverseJoinColumns={@JoinColumn(name="tag_id")}
    )
    @OrderBy("created")
    public Set<Tag> getTags() {
        return tags;
    }
   
    public void setTags(Set<Tag> tags) {
        this.tags = tags;
    }


}

@Entity
@Table(name="vid_tag")
public class Tag extends BaseEntity {

   ....
}

就是这么简单的两个类,我在保存视频(就是无非更新了一下视频的标题或描述而已)的时候,打开log一看,竟然有这么一条惊人的语句:


        select

video0_.id as id135_1_, video0_.browse_num as browse2_135_1_, video0_.created as created135_1_, video0_.description as descript4_135_1_, video0_.oppose_num as oppose5_135_1_, video0_.original_url as original6_135_1_, video0_.owner_displayname as owner7_135_1_, video0_.owner_id as owner8_135_1_, video0_.privacy_level as privacy9_135_1_, video0_.support_num as support10_135_1_, video0_.thum_url as thum11_135_1_, video0_.title as title135_1_, video0_.url as url135_1_,

tags1_.video_id as video1_3_, tag2_.id as tag2_3_, tag2_.id as id136_0_, tag2_.created as created136_0_, tag2_.name as name136_0_

from vid_video video0_

left outer join vid_video_tag tags1_ on video0_.id=tags1_.video_id

left outer join vid_tag tag2_ on tags1_.tag_id=tag2_.id

where video0_.id=?

order by tag2_.created asc


执行的程序如下:

VideoAction.java:

// 这个get方法会对video表发起一次查询,也如意料之中的并没有对video的tag集合进行关// 联查询,因为video中的tag集合是懒加载的。
Video p = videoManager.getVideo(video.getId());
               
                p.setTitle(video.getTitle());
                p.setDescription(video.getDescription());
                p.setPrivacyLevel(video.getPrivacyLevel());
  
// 在调用updateVideo()的时候,并没有只是执行update 语句,而是在update语句之前还向
// 数据库发起了一条查询语句,这个查询语句就是上面那堆让我头大三圈的东西!
             p = videoManager.updateVideo(p);

videoManager.getVideo() 无非就是:
getHibernateTemplate().get(id)
videoManager.updateVideo() 无非就是:
getHibernateTemplate().merge(object)

就这么简单的程序,为何会莫名其妙地在执行对video的update操作之前要先执行一个对video的标签集合的抓取操作呢?该集合明明是lazy的,奇怪啊,抓狂了。。。



1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics