有幾點需要注意的地方:
1
//OK Query query=session.createQuery("from Special");
//ERROR Query query=session.createQuery("select * from Special");select *不能使用
Query query=session.createQuery("select spec from Special spec");//OK
List<Special> ls=query.list();
2 hibernate下標從0開始 jdbc從1
3 指定參數名稱 用 :name格式,
Query query=session.createQuery("from Student where name like :name and sex=:sex");
query.setParameter("name","%2%");
query.setParameter("sex","女");
List<Student> ls=query.list();
4 使用uniqueResult進行唯一的查詢 返回值爲Object 可以強轉爲long
Query query=session.createQuery("select count(*) from Student where name like :name and sex=:sex");
query.setParameter("name","%2%");
query.setParameter("sex","女");
Long ls=(Long)query.uniqueResult();
5 基於投影的查詢 通過在列表中存儲一個對象數組
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu.sex,count(*) from Student stu group by stu.sex");
List<Object[]> ls=query.list();
for (Object[] objects : ls)
{
System.out.println(objects[0]+" "+objects[1]);
}
6 基於導航的查詢 表之間的連接用笛卡爾積 cross join 使用效率低 但是方便 可以直接寫 stu.classroom.name=?
Query query=session.createQuery("select stu from Student stu where stu.name like ? and stu.classroom.name=?");
List<Student> ls=query.setParameter(0,"%張%").setParameter(1,"軟件1班").list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
7可以使用in類來設置基於列表的查詢 此處查詢要使用別名進行查詢
特別注意 使用的in查詢必須在其他查詢之後
Query query=session.createQuery("select stu from Student stu where stu.name like ? and stu.classroom.id in(:clas)");
List<Student> ls=query.setParameter(0,"%張%").setParameterList("clas",new Integer[]{1,3}).list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
8使用setFirstResult和setMaxResult可以完成分頁的offset和pageSize的設置
Query query=session.createQuery("select stu from Student stu where stu.classroom.id in(:clas)");
List<Student> ls=query.setParameterList("clas",new Integer[]{1,3})
.setFirstResult(0).setMaxResults(2).list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
9可以使用is null 查詢 外鍵爲空的對象 使用關聯對象爲空判斷
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where stu.classroom is null");
List<Student> ls=query.list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
10使用對象的導航可以完成連接,但是基於cross join(笛卡爾積),
效率不高 可以直接使用join{left join ,inner join(=join),right join}
Query query=session.createQuery("select stu.id,stu.name,stu.sex,cla.name,spe.name from"
+ " Student stu left join stu.classroom cla left join cla.special spe");
List<Object[]> ls=query.list();
for (Object[] stu : ls)
{
System.out.print(stu[0]+","+stu[1]+","+stu[2]+","+stu[3]+","+stu[4]+"\n");
}
11 構造一個新的傳輸對象
*1 直接使用new XXObject來新建一個傳輸對象來接住查詢的東西
* 2 注意一定要加上XXObject的完整包名
* 3 這裏使用New 要加入相應的構造方法
* 4 記得使用as
Query query=session.createQuery("select new com.itany.model."
+ "StudentDto(stu.id as sid,stu.name as sname,stu.sex as sex,cla.name as cname,spe.name as specname) "
+ "from Student stu left join stu.classroom cla left join cla.special spe");
List<StudentDto> ls=query.list();
for (StudentDto stu : ls)
{
System.out.print(stu.getSid()+","+stu.getSname()+","+stu.getSex()+","+stu.getCname()+","+stu.getSpecname()+"\n");
}
廢話不說,直接上代碼:
涉及到幾個表的關係:專業表--班級表--學生表 都是多對一的關係
下面是xml文件配置,annotation有關的配置 會單獨開篇文章說明:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.itany.model">
<class name="Student" table="t_stu">
<!-- <cache usage="read-only" /> -->
<id name="id">
<generator class="native"></generator>
</id>
<!-- 注意:version 一定要加在ID後面 property前面 -->
<version name="version" />
<property name="name" />
<property name="sex" />
<many-to-one name="classroom" column="cid" fetch="join" />
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.itany.model">
<!-- 注意:多對一時候 從多端懶加載一對象(目的是爲了全部加載多端對象)
在一端加batch-size=3 表示3個一端對象對應的所有多端對象全部加載 比如3個班的所有學生加載 減少發出的SQL
同理: 一對多時候 從一端延遲加載多端對象 在一端set中batch-size="3"表示3個一端對象對應的所有多端對象全部延遲加載-->
<class name="Classroom" table="t_cla" batch-size="3">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name" />
<property name="grade" />
<!-- 表示一次加載2個classroom的所有學生 -->
<set name="students" inverse="true" lazy="extra" fetch="subselect" batch-size="2">
<key column="cid" />
<one-to-many class="Student"/>
</set>
<many-to-one name="special" column="spec_id" fetch="join"/>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.itany.model">
<class name="Special" table="t_spec">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name" />
<property name="type" />
<set name="clas" inverse="true" lazy="extra">
<key column="spec_id" />
<one-to-many class="Classroom" />
</set>
</class>
</hibernate-mapping>
下面使用幾個junit的測試用例說明:
public class TestHQL
{
@SuppressWarnings("unchecked")
@Test
public void test01()
{
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
trans=session.beginTransaction();
//OK Query query=session.createQuery("from Special");
//ERROR Query query=session.createQuery("select * from Special");select *不能使用
Query query=session.createQuery("select spec from Special spec");//OK
List<Special> ls=query.list();
for (Special special : ls)
{
System.out.println(special.getName());
}
trans.commit();
}
catch (HibernateException e)
{
e.printStackTrace();
if(null!=session)
trans.rollback();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test02()
{
//hibernate下標從0開始 jdbc從1
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("from Student where name like ?");//name like '%1%'可能引起SQL注入
query.setParameter(0,"%1%");
List<Student> ls=query.list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test03()
{
/*
* 指定參數名稱
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("from Student where name like :name and sex=:sex");
query.setParameter("name","%2%");
query.setParameter("sex","女");
List<Student> ls=query.list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test04()
{
/*
* 使用uniqueResult進行唯一的查詢
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select count(*) from Student where name like :name and sex=:sex");
query.setParameter("name","%2%");
query.setParameter("sex","女");
Long ls=(Long)query.uniqueResult();
System.out.println(ls);
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test05()
{
/*
* 使用uniqueResult進行唯一的查詢
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where id=:id");
query.setParameter("id",1);
Student ls=(Student)query.uniqueResult();
System.out.println(ls.getName());
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test06()
{
/*
* 基於投影的查詢 通過在列表中存儲一個對象數組
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu.sex,count(*) from Student stu group by stu.sex");
List<Object[]> ls=query.list();
for (Object[] objects : ls)
{
System.out.println(objects[0]+" "+objects[1]);
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test07()
{
/*
* 普通查詢
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where cid=?");
List<Student> ls=query.setParameter(0, 1).list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test08()
{
/*
* 基於導航的查詢 表之間的連接用笛卡爾積 cross join 使用效率低 但是方便 可以直接寫
* stu.classroom.name=?
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where stu.name like ? and stu.classroom.name=?");
List<Student> ls=query.setParameter(0,"%張%").setParameter(1,"軟件1班").list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test09()
{
/*
* 可以使用in類來設置基於列表的查詢 此處查詢要使用別名進行查詢
* 特別注意 使用的in查詢必須在其他查詢之後
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where stu.name like ? and stu.classroom.id in(:clas)");
List<Student> ls=query.setParameter(0,"%張%").setParameterList("clas",new Integer[]{1,3}).list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test10()
{
/*
* 使用setFirstResult和setMaxResult可以完成分頁的offset和pageSize的設置
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where stu.classroom.id in(:clas)");
List<Student> ls=query.setParameterList("clas",new Integer[]{1,3})
.setFirstResult(0).setMaxResults(2).list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test11()
{
/*
* 可以使用is null 查詢 外鍵爲空的對象 使用關聯對象爲空判斷
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu from Student stu where stu.classroom is null");
List<Student> ls=query.list();
for (Student stu : ls)
{
System.out.println(stu.getName());
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test12()
{
/*
* 使用對象的導航可以完成連接,但是基於cross join(笛卡爾積),
* 效率不高 可以直接使用join{left join ,inner join(=join),right join}
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select stu.id,stu.name,stu.sex,cla.name,spe.name from"
+ " Student stu left join stu.classroom cla left join cla.special spe");
List<Object[]> ls=query.list();
for (Object[] stu : ls)
{
System.out.print(stu[0]+","+stu[1]+","+stu[2]+","+stu[3]+","+stu[4]+"\n");
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test13()
{
/*
* 1 直接使用new XXObject來新建一個傳輸對象來接住查詢的東西
* 2 注意一定要加上XXObject的完整包名
* 3 這裏使用New 要加入相應的構造方法
* 4 記得使用as
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select new com.itany.model."
+ "StudentDto(stu.id as sid,stu.name as sname,stu.sex as sex,cla.name as cname,spe.name as specname) "
+ "from Student stu left join stu.classroom cla left join cla.special spe");
List<StudentDto> ls=query.list();
for (StudentDto stu : ls)
{
System.out.print(stu.getSid()+","+stu.getSname()+","+stu.getSex()+","+stu.getCname()+","+stu.getSpecname()+"\n");
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test14()
{
/*
* 統計不同專業的人數>3的(注意對專業需要進行外連接)
* 可以寫一個連接 一下子連接2張表 中間隔了一個classroom
* Student stu right join stu.classroom.special spe
*
* 注意是 count(stu.id)
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select spe.name,count(stu.id) from "
+ "Student stu right join stu.classroom.special spe group by spe having count(stu.id)>3");
List<Object[]> ls=query.list();
for (Object[] stu : ls)
{
System.out.print(stu[0]+","+stu[1]+"\n");
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
@Test
public void test15()
{
/*
* 統計不同專業不同性別的人數(注意對專業需要進行外連接)
* 可以寫一個連接 一下子連接2張表 中間隔了一個classroom
* Student stu right join stu.classroom.special spe
*
* 注意是 count(stu.id)
*/
Session session=null;
Transaction trans=null;
try
{
session=HibernateUtil.openSession();
Query query=session.createQuery("select spe.name,stu.sex,count(stu.id) from "
+ "Student stu right join stu.classroom.special spe group by spe.id,stu.sex");
List<Object[]> ls=query.list();
for (Object[] stu : ls)
{
System.out.print(stu[0]+","+stu[1]+","+stu[2]+"\n");
}
}
catch (HibernateException e)
{
e.printStackTrace();
}
finally
{
if(null!=session)
HibernateUtil.closeSession(session);
}
}
}