有几点需要注意的地方:
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);
}
}
}