您的位置:首页 > 其它

Hibernate检索策略学习之--批量加载

2007-11-29 18:12 357 查看
所谓批量加载,即把原本要发送的SQL分批统一发送,比如说原本要发送100条SQL,如果设置batch-size=3,则只需要发送100/3+1=34条,可以提高效率

批量加载分为延迟加载和立即加载,先说立即加在

首先建立测试数据库








CREATE TABLE certificate (


id varchar(100) NOT NULL default '',


description varchar(100) default '',


PRIMARY KEY (id)


);












CREATE TABLE student (


team_id varchar(100) default '',


id varchar(100) NOT NULL default '',


name varchar(20) default '',


cardId varchar(20) NOT NULL default '',


age int(11) default '0',


PRIMARY KEY (id)


);






CREATE TABLE team (


id varchar(100) NOT NULL default '',


teamName varchar(100) default '',


PRIMARY KEY (id)


);






INSERT INTO student VALUES


('5','1','spark','200211332',13),


('4','2','jerry','200233332',23),


('3','3','adidas','200231332',33),


('2','4','zhouxingchi','200231132',43),


('1','5','tomclus','200512345',53),


('1','6','tom','200511345',63);




INSERT INTO team VALUES


('5','team5'),


('4','team4'),


('3','team3'),


('2','team2'),


('1','team1');




INSERT INTO certificate VALUES


('1','card1'),


('2','card2'),


('3','card3'),


('4','card4'),


('5','card5'),


('6','card6');





建立POJO对象




package Search.immediately;






public class Certificate ............{


private String id;


private String description;


private Student stu;






public Student getStu() ............{


return stu;


}






public void setStu(Student stu) ............{


this.stu = stu;


}








public String getDescription() ............{


return description;


}






public void setDescription(String description) ............{


this.description = description;


}






public String getId() ............{


return id;


}






public void setId(String id) ............{


this.id = id;


}


}








package Search.immediately;




import java.util.HashSet;


import java.util.Set;








public class Team ............{


private String id;


private Set students=new HashSet();


private String teamName;


private Set tests;







public Set getTests() ............{


return tests;


}







public void setTests(Set tests) ............{


this.tests = tests;


}






public String getId() ............{


return id;


}






public void setId(String id) ............{


this.id = id;


}






public String getTeamName() ............{


return teamName;


}






public void setTeamName(String name) ............{


this.teamName = name;


}






public Set getStudents() ............{


return students;


}






public void setStudents(Set students) ............{


this.students = students;


}


}








package Search.immediately;






public class Certificate ............{


private String id;


private String description;


private Student stu;






public Student getStu() ............{


return stu;


}






public void setStu(Student stu) ............{


this.stu = stu;


}








public String getDescription() ............{


return description;


}






public void setDescription(String description) ............{


this.description = description;


}






public String getId() ............{


return id;


}






public void setId(String id) ............{


this.id = id;


}


}





HBM文件

student.hbm.xml




<?xml version="1.0" encoding="utf-8"?>


<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"


"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<!--


Mapping file autogenerated by MyEclipse - Hibernate Tools


-->


<hibernate-mapping package="Search.batch.immediately" >




<class name="Student" table="student" lazy="false">


<id name="id" column="id" unsaved-value="null">


<generator class="uuid.hex"></generator>


</id>




<property name="cardId" column="cardId"></property>


<property name="name" column="name"></property>


<property name="age" column="age"></property>


<!--为了设置student-certificate的延迟1对1,设置class的lazy="no-proxy"-->


<one-to-one name="cer"


class="Search.batch.immediately.Certificate"


constrained="true"


lazy="no-proxy"


outer-join="false"


cascade="all">


</one-to-one>





<many-to-one name="team"


column="team_id"


outer-join="false"


class="Search.batch.immediately.Team"></many-to-one>


</class>


</hibernate-mapping>





Certificate.hbm.xml




<?xml version="1.0" encoding="utf-8"?>


<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"


"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<!--


Mapping file autogenerated by MyEclipse - Hibernate Tools


-->


<hibernate-mapping package="Search.batch.immediately" >


<!--为了设置student-certificate的延迟1对1,设置class的lazy="true"-->


<class name="Certificate" table="certificate" lazy="true">


<id name="id" column="id">


<generator class="foreign">


<param name="property">stu</param>


</generator>


</id>






<property name="description" column="description"></property>


<one-to-one name="stu"


class="Search.batch.immediately.Student"


outer-join="false"


constrained="true">


</one-to-one>


</class>


</hibernate-mapping>





Team.hbm.xml




<?xml version="1.0" encoding="utf-8"?>


<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"


"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<!--


Mapping file autogenerated by MyEclipse - Hibernate Tools


-->


<hibernate-mapping package="Search.batch.immediately" >


<class name="Team" table="team" lazy="false">


<id name="id" column="id">


<generator class="uuid.hex"></generator>


</id>


<property name="teamName" column="teamName"></property>


<!--需要批量加载,设置batch-size="2"-->


<set name="students"


lazy="false"


inverse="true"


outer-join="false"


>


<key column="team_id"></key>


<one-to-many class="Search.batch.immediately.Student"/>


</set>


</class>


</hibernate-mapping>





测试代码:




package Search.batch.immediately;




import java.io.File;


import java.util.List;




import org.hibernate.Query;


import org.hibernate.Session;


import org.hibernate.SessionFactory;


import org.hibernate.cfg.Configuration;






public class Test ...{








public static void main(String[] args) ...{


Team team=null;


String filePath=System.getProperty("user.dir")+File.separator+"src/Search/batch/immediately"+File.separator+"hibernate.cfg.xml";


File file=new File(filePath);


SessionFactory sessionFactory=new Configuration().configure(file).buildSessionFactory();


Session session=sessionFactory.openSession();


Query query=session.createQuery("from Team t");


List resultList=query.list();






}





运行,结果如下:

Hibernate: select team0_.id as id2_, team0_.teamName as teamName2_ from team team0_

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=?

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=?

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=?

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=?

有5条查询student的SQL(本身有6个学生,但有两个学生属于一个team)
可以看到,这是典型的立即加在,取得team对象后,把team所包含的student取出,如果有100个学生,则会执行100个SQL,这是很没有效率的

我们修改Team的hbm文件,为其配置批量加载student的配置(1对多在set标签上配置,多对1在class标签上配置)




<?xml version="1.0" encoding="utf-8"?>


<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"


"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<!--


Mapping file autogenerated by MyEclipse - Hibernate Tools


-->


<hibernate-mapping package="Search.batch.immediately" >


<class name="Team" table="team" lazy="false">


<id name="id" column="id">


<generator class="uuid.hex"></generator>


</id>


<property name="teamName" column="teamName"></property>


<!--需要批量加载,设置batch-size="2"-->


<set name="students"


lazy="false"


inverse="true"


outer-join="false"


batch-size="2"


>


<key column="team_id"></key>


<one-to-many class="Search.batch.immediately.Student"/>


</set>


</class>


</hibernate-mapping>





再次运行测试程序,结果如下:

Hibernate: select team0_.id as id2_, team0_.teamName as teamName2_ from team team0_

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id in (?, ?)

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_,
students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id in (?, ?)

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=?

可以看到,查询student只用了3条SQL(5/batch-size+1=3),



如果team对student是延迟加载的,会使什么效果呢,会是这样,我们加载team1时候,由于batch-size=2,所以加载team1就同时批量加载了team2,同理,加载team3时候也就加载了team4,最后再加载team5, 而这些数据都已经在hibernate session的缓存中了

修改team.hbm.xml 配置好lazy="true"




<?xml version="1.0" encoding="utf-8"?>


<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"


"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<!--


Mapping file autogenerated by MyEclipse - Hibernate Tools


-->


<hibernate-mapping package="Search.batch.immediately" >


<class name="Team" table="team" lazy="false">


<id name="id" column="id">


<generator class="uuid.hex"></generator>


</id>


<property name="teamName" column="teamName"></property>


<!--需要批量加载,设置batch-size="2"-->


<set name="students"


lazy="true"


inverse="true"


outer-join="false"


batch-size="2"


>


<key column="team_id"></key>


<one-to-many class="Search.batch.immediately.Student"/>


</set>


</class>


</hibernate-mapping>





运行测试程序,结果如下:

Hibernate: select team0_.id as id2_, team0_.teamName as teamName2_ from team team0_

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id in (?, ?)
team1:2
team2:1

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id in (?, ?)
team3:1
team4:1

Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.cardId as cardId1_0_, students0_.name as name1_0_, students0_.age as age1_0_, students0_.team_id as team5_1_0_ from student students0_ where students0_.team_id=?
team5:1

其中可以砍到team2和team4的数据是批量加载来的,已经保存在缓存中,所以读取其students集合对象是,虽然是延迟加载,但不再会去发送SQ查询,而是再缓冲中查询
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: