hibernate 连接查询方式之案例分析

Hibernate效率分析:

连接查询:

说明:在使用hibernate的时候,如果是一个双向的一对多的关联映射,如:(环境)

publicclassStudent{

privateintid;

privateStringname;

privateTheClassincludeClass;

}

publicclassTheClass{

privateintid;

privateStringname;

privateSet<Student>stuList;

}

在数据库中的表student中有一个字段theclassid(但是并没有建立数据库外键关联)

下面是hibernate映射文件:

<classname="TheClass"table="class">

<idname="id"column="classid"></id>

<propertyname="name"></property>

<setname="stuList"cascade="all"inverse="true">

<keycolumn="theclassid"/>

<one-to-manyclass="Student"/>

</set>

</class>

<classname="Student"table="student">

<idname="id"column="studentid">

</id>

<propertyname="name"></property>

<many-to-onename="includeClass"column="theclassid"fetch="join"lazy="false"/>

</class>

这是双向的。单向也是一样。这里面使用的是set而非list。(建议使用set而非list)

1.使用原生sql进行查询

使用原生Sql可以直接通过一条sql语句将全部的字段查询出来,然后自己根据需要进行组装。查询速度会较快,只是组装会比较费时。

2.使用hql进行查询

Hql查询:在我们一对多关联映射的时候如果想查询一的那一方。如果我们希望将与其关联的child都查出来的话。我们可以在配置set的地方添加一个lazy=”false”,这样的话在查询的时候会自动的将其child查询出来。只不过他查询的方式是,先发出一条sql语句将全部的一的那一方的记录查出来。然后遍历该list。根据关联的字段再发一条sql语句将与该一条记录关联的子记录都查询出来。这样就需要共发出1+n条sql语句。解决它的方式中有一种就是使用连接查询。

连接查询即使用join(还有fetch)来进行查询。

例如我们想把class查出来并且想把所有与他关联的student查询出来,一共有几种方法:

1.普通的左外连接:

SessionFactorysessionFactory=HibernateUtil.getSessionFactory();

Sessionsession=sessionFactory.openSession();

session.beginTransaction();

Queryquery=session.createQuery("fromTheClasstleftjoint.stuList");

Listlist=query.list();

System.out.println(list.size());

for(Iteratorit=list.iterator();it.hasNext();)

{

Object[]arr=(Object[])it.next();

System.out.println(arr.length);

for(inti=0;i<arr.length;i++)

{

if(arr[i]==null)

{

System.out.println(i+"--isnull");

continue;

}

System.out.println(arr[i].getClass().getName());

if(i==0)

{

TheClasstempClass=(TheClass)arr[i];

System.out.println(((TheClass)arr[i]).getName());

SettheSet=tempClass.getStuList();

if(theSet!=null&&theSet.size()>0)

{

Iteratorit2=theSet.iterator();

while(it2.hasNext())

{

StudenttempStu=(Student)it2.next();

System.out.println(tempStu.getName());

}

}

}

else

{

System.out.println(((Student)arr[i]).getName());

}

}

}

session.getTransaction().commit();

session.close();

这里使用这种查询方式的时候得到的list里面的每一项是一个Object的数组。其中arr[0]是TheClass对象。Arr[1]是与改TheClass的关联的Student对象。如果与一个TheClass关联的Student一共有五个。那么这个list中会有5个该TheClass对象。他们的arr【1】是与之关联的五个Student。如果一个student也没有。那么会只有一个THeClass对象。且他的arr[1]是null。我们可以自己手动解析该list。然后可以得到我们想要的数据结构。而如果我们通过我们拿到的TheClass对象来获取其中的theStuSet的时候。他里面在此刻并没有值,而当我们一去获取并访问他的时候他也会根据当前的theClass对象发出一条sql语句来查询与之关联的student对象并且组装到这个成员变量中去。

但是这种情况会有所改变:如果我们查询多的一方,然后使用这种方式的话,他会帮助我们把与之相关联的TheClass对象放到Student里面的includeClass成员变量。这时我们可以通过这个直接访问。虽然如此,但是查询得到的list也是object[]。他的结果和上面是一样的。

2.使用添加fetch的join查询:

Queryquery=session.createQuery("fromTheClasstleftjoinfetcht.stuListasc");

Listlist=query.list();

System.out.println(list.size());

for(Iteratorit=list.iterator();it.hasNext();)

{

TheClasstheClass=(TheClass)it.next();

System.out.println(theClass.getName());

Set<Student>stuSet=theClass.getStuList();

if(stuSet!=null&&stuSet.size()>0)

{

Iteratorit2=stuSet.iterator();

while(it2.hasNext())

{

Studentstu=(Student)it2.next();

System.out.println(stu.getName());

}

}else

{

System.out.println("isnull");

}

}

fromTheClasstleftjoinfetcht.stuListasc。这里我们在leftjoin后面添加了一个fetch。这样的话查询得到的list就和上面的不一样了。而是一个TheClass对象的List。所以我们可以直接遍历他,然后访问其中的theStuSet。这就是因为hibernate容器帮我们将join查询出来的数据组装到TheClass的成员变量中去了。

相关推荐