加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Hibernate 查询1+N问题分析

发布时间:2021-11-24 17:14:21 所属栏目:PHP教程 来源:互联网
导读:1、1+N简单来说就是,Person和Phone是一对多关系,现在我看看所有手机的信息,对于其属于哪个人不感兴趣,但把lazy设为false(lazy=false),这样就会发出1(查询手机的sql)+N(和所有查询的这些手机相关的Person的查询sql),这样会造成很大的性能开销。 首先

1、1+N简单来说就是,Person和Phone是一对多关系,现在我看看所有手机的信息,对于其属于哪个人不感兴趣,但把lazy设为false(lazy=false),这样就会发出1(查询手机的sql)+N(和所有查询的这些手机相关的Person的查询sql),这样会造成很大的性能开销。
 
首先列一下会产生1+N问题的代码
 
Person:
 
[java]
private int id;  
private String name;  
private int age;  
Person.hbm.xml按照常规配置即可
Phone:
 
[java]
private int id;  
private String type;  
private String description;  
private Person person;  //关联一个用户  
Phone.hbm.xml:
[html]
<hibernate-mapping>  
    <class name="com.akwolf.n_1.Phone" table="PHONE">  
        <id name="id" type="int">  
            <column name="ID" />  
            <generator class="native" />  
        </id>  
        <property name="type" type="java.lang.String">  
            <column name="TYPE" />  
        </property>  
        <property name="description" type="java.lang.String">  
            <column name="DESCRIPTION" />  
        </property>  
        <!-- lazy=false -->  
        <many-to-one name="person" class="com.akwolf.n_1.Person" fetch="join" lazy="false">  
            <column name="PERSON_ID" />  
        </many-to-one>  
    </class>  
</hibernate-mapping>  
为了使效果明显一点,假定一个手机对应一个不同的用户,现在想数据库中添加一些数据:
 
[java]
@Test  
public void testSave1() {  
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();  
    session.beginTransaction();  
    Person person;  
    Phone phone;  
  
    for (int i = 0; i < 10; i++) {  
        person = new Person(0, "zhangsan" + i, 21 + i);  
  
        phone = new Phone(0, "glay" + i, "Android智能手机", person);  
        session.save(person);  
        session.save(phone);  
    }  
    session.getTransaction().commit();  
}  
 
进行一下下面的查询会看到,控制台输出大量的sql
[java]
@Test  
public void testQuery1() {  
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();  
    session.beginTransaction();  
    List<Phone> list = (List<Phone>) session.createQuery("from Phone")  
            .list();  
    for (Phone phone : list) {  
        System.out.println(phone.getId()); //对关联的Person并不感兴趣   
        // System.out.println(phone.getId()+"---"+phone.getPerson().getName());   
    }  
    session.getTransaction().commit();  
}  
解决方案
 
1、还是在Phone.hbm.xml中把对于Person关联的映射属性不进行lazy属性的设置,默认为lazy加载
 
[html]
<hibernate-mapping>  
    <class name="com.akwolf.n_1.Phone" table="PHONE">  
        <id name="id" type="int">  
            <column name="ID" />  
            <generator class="native" />  
        </id>  
        <property name="type" type="java.lang.String">  
            <column name="TYPE" />  
        </property>  
        <property name="description" type="java.lang.String">  
            <column name="DESCRIPTION" />  
        </property>  
        <!-- lazy=true -->  
        <many-to-one name="person" class="com.akwolf.n_1.Person" fetch="join">  
            <column name="PERSON_ID" />  
        </many-to-one>  
    </class>  
</hibernate-mapping>  
2、在lazy=false的情况下,在hql中使用join fetch进行查询(session.createCriteria就是采用连接查询的方式),如:
[java]
@Test  
public void testQuery2() {  
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();  
    session.beginTransaction();  
    List<Phone> list = (List<Phone>) session.createQuery(  
            "from Phone p left join fetch p.person per").list();  
    for (Phone phone : list) {  
        // System.out.println(phone.getId());   
        System.out.println(phone.getId() + "---"  
                + phone.getPerson().getName());  
    }  
    session.getTransaction().commit();  
}  
3、对于在Person中设置batch-size应该不算是一种解决方案,对于海量的数据,设置的一些batch-size对于大体来说是无关痛痒的。
ok,这就是小弟看视频对于1+N问题的一点理解,有理解更为深刻的大虾不吝赐教。。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读