Hibernate提供的查询方式有以下几种:
1.OID查询方式
通过get()和load()方法加载指定OID的对象;
2.HQL查询方式
HQL操作的是持久化的对象,而不是数据库
--通过Query接口使用HQL语言进行查询
查询整个类即所有字段的属性,叫做实体查询,仅查询某几个字段的值,持久化的仅仅是查询到的字段,叫做属性查询,同时查询超过两个属性的时候,结果集的泛型是Object[]数组,按照查询的顺序,数组的每一个元素就是一个字段的值,当实体查询联合查询两个以上的实体类,即多表查询的时候,结果集的泛型也是数组,每个数组的元素就是一个实体类;
如果确定结果是单一的对象,就用uniquerResult()方法
--实体的更新和删除:
--子查询 在hibernate中,子查询语句只能放在where之后,不能像sql中那样,可以放在任何地方
--连接查询(outer可以省略)
3.QBC查询方式(Query By Criteria)
--使用Criteria等的接口和类进行查询,criteria查询又叫做对象查询,criteria本身只是查询容器
4.本地SQL查询方式
--使用原生sql语言进行查询
5.对象导航查询方式
--通过已经加载的对象,导航到其关联对象
6.命名查询(类似mybatis)
写在配置文件<class/>的标记下面
Query query = session.getNamedQuery("login");
或者写在<class/>上面,格式同方法一,但是java代码调用时需要指定(包+类+配置名)
Query query = session.getNamedQuery("com.entity.User.login");
7.定制sql 可以自己定制sql语句实现create、delete、update
写在配置文件的<class/>的标记上,标签为<sql-insert></sql-insert>、<sql-update></sql-update>、<sql-delete></sql-delete>
同理,可以设置update="false",在调用session.save();session.delete();session.upload()方法的时候,会执行定制的sql语句,而不是hibernate封装的语句
1.OID查询方式
通过get()和load()方法加载指定OID的对象;
例如:
session.get(User.class,1);
后面的数字为数据库中对应的ID
get和load的区别是,load支持类级别的懒加载,而get不支持,同时load支持缓存还有一点,load返回的是一个代理对象,当查询为空的时候,get返回的是null,而load则会报异常HubernateException2.HQL查询方式
HQL操作的是持久化的对象,而不是数据库
--通过Query接口使用HQL语言进行查询
查询整个类即所有字段的属性,叫做实体查询,仅查询某几个字段的值,持久化的仅仅是查询到的字段,叫做属性查询,同时查询超过两个属性的时候,结果集的泛型是Object[]数组,按照查询的顺序,数组的每一个元素就是一个字段的值,当实体查询联合查询两个以上的实体类,即多表查询的时候,结果集的泛型也是数组,每个数组的元素就是一个实体类;
例如:
Query query = session.createQuery(" from User where id=:id");
Query query = session.createQuery(" select u.id,u.name from User u");
query.setInteger("id",1);
query.setFirstResult((pageNo-1)*pageSize);
query.setMaxResults(pageSize);
别名User u / User as u,as可有可无
注意,hql语句中,要用对应的实体类和类属性名代替表明和字段名,因为hibernate是实现ORM(对象关系映射)的框架,它操作的是持久化的对象,而不是数据库,
List<User> list = query.list();
Iterator iter = query.iterator();
User user = query.uniqueResult()
list和iterator效果相同,都是取得结果集,区别是,iterator先查询出来所有符合的id,等调用数据的时候,调用一条数据,就去缓存中寻找该条数据,如果存在,则直接将缓存中的数据读出来,如果不存在,就执行一条sql语句,查询出对应的值; 一般情况都使用list,如果对象包含大量数据,或者要加载的大部分数据都在缓存中已经存在的时候,就使用iterator
如果确定结果是单一的对象,就用uniquerResult()方法
--实体的更新和删除:
此处的hql语句和sql语句一样,只是表名和字段名都要相应的替换为实体类,
Query query = session.createQuery(hql);
query.executeUpdate();
String hql =" delete from User where id = 1";
String hql =" update User set name='张三' where id = 1";
--分组查询,一般使用的聚合函数(统计函数),avg()、sum()、min()、max()、count()等等
String hql = " select count(*) from User";
需要注意的是,hibernate中的统计函数,avg的返回值是Double型的,min和max返回的是Integer型的,而count和sum返回的都是Long型的,Long型无法强转成Integer型,如果确实想要用Integer型返回值,可以将查询结果强转为Number型,--子查询 在hibernate中,子查询语句只能放在where之后,不能像sql中那样,可以放在任何地方
--连接查询(outer可以省略)
inner join
String hql =" from Street s inner join s.district";//sql1999
String hql = " from Street s,District d where s.district=d";sql1992
left outer join
String hql = " from Street s left join s.district";//左边对象所有数据都会读出来,不管右边对象有没有与之对应的值
String hql = " from Street s,District d where s.district=d(+)";//同上,可以理解为右边对象值少,需要+null来与之对应
3.QBC查询方式(Query By Criteria)
--使用Criteria等的接口和类进行查询,criteria查询又叫做对象查询,criteria本身只是查询容器
例如:
Criteria criteria = session.createCriteria(User.class);
Criteria crieteia = session.createCriteria("com.entity.User");
//criteria也可以分页,也有.list()和.uniqueResult()方法,用法和query一样,但是criteria设置参数的方法和query不一样,
criteria.add(Restrictions.sqlRestriction(" name like '%a%' and age=23"));
criteria.add(Example.create(user));//user为一个实例化的对象,它的被赋值的属性将作为参数加入查询
criteria.add(Restrictions.eq("isAdmin", 2));//等价于
criteria.add(Restrictions.ge("age", 23));//大于
criteria.add(Restrictions.le("id", 6));//小于
criteria.add(Restrictions.or(Restrictions.eq("isAdmin", 1), Restrictions.between("age", 24, 33)));
criteria.addOrder(Order.desc("age"));//排序
criteria.setProjection(Projections.avg("age"));//分组查询,聚合函数
criteria.setProjection(Projections.projectionList().add(Projections.count("id")).add(Projections.sum("age")).add(Projections.max("age")));//多个聚合函数
4.本地SQL查询方式
--使用原生sql语言进行查询
例如:
Query query = session.createSQLQuery(" select u.* from HOUSE_USERS u").addEntity("u",User.class);
Query query = session.createSQLQuery(" select {d.*},{s.*} from HOUSE_District d,HOUSE_Street s where d.id=s.DISTRICT_ID").addEntity("d",District.class).addEntity("s",Street.class);
List<Object[]> list = query.list();
Object[] obj = list.get(0);
District district = obj[0];
Street street = obj[1];
需要注意的是,对多个表进行综合查询的时候,如果两个表有某些字段的名字一样,则查询的结果会将该字段第二次出现的字段名称自动重命名,查询后封装数据的时候,会将第一个字段名字的值封装到两个对象之中,解决这种办法,就是在sql语句中对这两个对象查询的字段分别用花括号括住,如上这是hibernate提供的方法,数据库中并不支持这种查询
5.对象导航查询方式
--通过已经加载的对象,导航到其关联对象
6.命名查询(类似mybatis)
写在配置文件<class/>的标记下面
Query query = session.getNamedQuery("login");
<query name="login">
<![CDATA[from User where name=:name and password=:password]]>
</query>
<sql-query name="findUser">
<![CDATA[select u.* from HOUSE_USERS u]]>
<return alias="u" class="com.entity.User"></return>
</sql-query>
使用原生sql查询,必须把表所有的列写全才可以,否则会出现‘列名无效'的错误 ,除非你使用return-scalar来设置字段类型
或者写在<class/>上面,格式同方法一,但是java代码调用时需要指定(包+类+配置名)
Query query = session.getNamedQuery("com.entity.User.login");
7.定制sql 可以自己定制sql语句实现create、delete、update
写在配置文件的<class/>的标记上,标签为<sql-insert></sql-insert>、<sql-update></sql-update>、<sql-delete></sql-delete>
<sql-insert>
insert into HOUSE_USERS (name,password,username,isAdmin,age,id) values(?,?,?,?,?,?)
</sql-insert>
如果某一个字段不想参与对应操作,可以在该字段对应的配置属性<property insert="false"></property>中设置insert="false"就可以不用加该属性;
同理,可以设置update="false",在调用session.save();session.delete();session.upload()方法的时候,会执行定制的sql语句,而不是hibernate封装的语句