一、hibernate中的query的两种查询,一种是我们经常写的sql的格式,另一种是hibernate 的查询语言就是hql
1、使用我们平时写的sql的方式:
(1)、
String hql = " select name from events where name =?";
Query query = session.createSQLQuery(hql);
query.setParameter(0, "whd");
List<String> list = query.list();
Iterator<String> it= list.iterator();
这里的查询sql语句和我们平时写的一样设置参数也没什么区别
String hql = " select id,name from events where name =?";
Query query = session.createSQLQuery(hql);
query.setParameter(0, "whd");
List<Object[]> list = query.list();
Iterator<Object[]> it= list.iterator();
while(it.hasNext()){
Object[] ob= it.next();
System.out.println(ob[0] +" "+ob[1]);
}
hibernate 中返回的数据是两个变量或多于两个的时候他是按照数组的格式返回的,顺序是按照查询sql中写的顺序来
上面两种方式都是我们平时看到的传递参数的方法,下面看一种hibernate 特有的传递参数的实例
String hql = " select id,name from events where id=:myid and name =:myname";
Query query = session.createSQLQuery(hql);
query.setParameter("myid", 1);
query.setParameter("myname","whd");
List<Object[]> list = query.list();
Iterator<Object[]> it= list.iterator();
while(it.hasNext()){
Object[] obj= it.next();
System.out.println(obj[0] +" "+obj[1]);
}
这里的两个参数传递如上,这种方式是hibernate 特有的。
上面的查询我们说和我们平时些的sql一样是因为他的查询字段,from 后面以及查询条件都是按照表字段来的,下面你会看到使用hql时的一些特殊区别!!!
2、使用hibernate 的hql 查询语言来查询
在使用hql时要注意他是面向对象的查询而不是面向数据库的查询,这也是hibernate 的一个特点吧,你不用管数据库中的属性字段你只需要对象就ok
(1)、使用hql查询
String hql = "from Event";
Query query = session.createQuery(hql);
List<Event> list = query.list();
Iterator<Event> it= list.iterator();
while(it.hasNext()){
Event event= it.next();
System.out.println(event.getId() +" "+event.getAge() +" "+event.getName());
}
注意:其中的Event是java中定义的一个bean, 和之前的相比session.createQuery()而不是createSQLQuery();
String hql = "select id,name from Event";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
Iterator<Object[]> it= list.iterator();
while(it.hasNext()){
Object[] event= it.next();
System.out.println(event[0]+" "+event[1]);
}
(3)、如果我们不想查询出来的是默认的Object[] 数组则我们要在写hql的时候要注意一下,这里将查询获取的结果集转化为map结果集
String hql = "select new map(id,name) from Event";
Query query = session.createQuery(hql);
List<Map> list = query.list();
Iterator<Map> it= list.iterator();
while(it.hasNext()){
Map map= it.next();
System.out.println(map.get("0") +" "+map.get("1"));
}
你是不是发现了我们这里有个new map() 其实这就是把我们的默认的Object[] 数组格式转变为 map 的格式。
但是你要注意map.get("key");这里的key是很特别的有木有发现,是的没错他就是字符串类型的"0","1"……有几个你就可以写到几
注意:这里的map是小写的不是大写的。
String hql = "select new list(id,name,age) from Event";
Query query = session.createQuery(hql);
List<List> list = query.list();
Iterator<List> it= list.iterator();
while(it.hasNext()){
List mylist= it.next();
System.out.println(mylist.get(0) +" "+mylist.get(1)+" "+mylist.get(2));
}
注意这里的list 也是小写,当然还能是set格式的或者自己定义的bean的格式,因为只要你查询出来了,hibernate 会按照你的定义给你组装成你想要的格式。
(5)、hql 条件查询,获取List<T>结果集
String hql = "from Event where id=:myid and name =:myname ";
Query query = session.createQuery(hql);
query.setParameter("myid", 1);
query.setParameter("myname", "whd");
List<Event> list = query.list();
Iterator<Event> it= list.iterator();
while(it.hasNext()){
Event event= it.next();
System.out.println(event.getId()+" "+event.getName()+" "+event.getAge());
}
----------------------------------------------------------------------------
String hql = "from Event where id=? and name =? ";
Query query = session.createQuery(hql);
query.setParameter(0, 1);
query.setParameter(1, "whd");
List<Event> list = query.list();
Iterator<Event> it= list.iterator();
while(it.hasNext()){
Event event= it.next();
System.out.println(event.getId()+" "+event.getName()+" "+event.getAge());
}
我们看到 hibernate 中两种传递参数的方式都可以使用但还是建议使用第一种,在hql中使用自定义名称的方式而在sql中使用第二种方式。
(6)、使用集合或者对象作为参数,查询获取list<T>集合结果
String hql = "from Event where name =:myname ";
Query query = session.createQuery(hql);
Map<String,String> map = new HashMap<String,String>();
map.put("myname", "whd2");
query.setProperties(map);
List<Event> list = query.list();
Iterator<Event> it= list.iterator();
while(it.hasNext()){
Event event= it.next();
System.out.println(event.getId()+" "+event.getName()+" "+event.getAge());
}
注意: 这里定义的map赋值时的key就是我们自定义的变量名称而value 就是条件值,如果使用自定义的bean 作为条件的话一样,bean中属性的名称和自定义的名称一样。
上面是两种查询方式的记录,下面看看query的保存数据
1、hql语句的保存
(1)、调用session的save() 方法进行保存
Event theEvent = new Event();
theEvent.setId(id);
theEvent.setName(name);
theEvent.setAge(age);
//添加
session.save(theEvent);
这种方法只能保存数据,如果这条数据id和数据中的主键的值重复则包异常。
(2)、session.saveOrUpdate 方法保存或更新数据
Event theEvent = new Event();
theEvent.setId(id);
theEvent.setName(name);
theEvent.setAge(age);
//保存或更新,hibernate是按照id走的,如果有则更新如果没有则添加,这个id如果有值就赋值没有就不用管,因为hibernate会自动生成并赋值。
session.saveOrUpdate(theEvent);
//所以说hibernate 的这个方法可以实现保存和更新的功能!
(3)、其实在正真的项目中使用saveOrUpdate() 方法绝对比save() 方法多
(4)、hibernate 中的批量添加
这个批量添加要好好说说,因为之前没使用过hibernate 只使用mybatis 但是在新项目中使用时有个批量添加网上找了半天也都是一样的,大体和下面这个差不多:
@Override
public void batchAdd(List<T> list) {
Session session= getSession();
Transaction tx= session.getTransaction();
for(int i=0;i<list.size();i++){
T unline= list.get(i);
session.save(unline);
if(i%25==0){
session.flush();
session.clear();
}
}
tx.commit();
session.close();
}
这就是写的一个批量添加方法,网上大多数也就是这样,那我们来分析一下这个批量添加到底批量添加了没有:
第一个获取了一个session,之后开启了事务,这两个我们都知道,是dao层必须的两个,下面就是循环调用session.save() 方法进行了保存,这时你说这个这么是批量添加
还不是一条一条的添加吗,注意hibernate是有缓存的其中一级缓存就是session级别,所以我们调用session.save() 方法保存的时候是将数据保存到了session 缓存中而不是一条条的
添加到了数据库中。那什么时候入库那,那就是session.flush() 方法的执行,在执行这个方法的时候就会把缓存中的数据保存到数据库其实这时才真正执行了数据的持久化。
那下面的session.clear() 方法时干什么用的那,这个是来清除session缓存的怕存了太多的缓存发生jvm内存溢出。
到这里我想你应该明白了这样写其实是实现了批量添加的。
2、sql语句的方式保存:
StringBuffer buffer=new StringBuffer(128);
buffer.append(" insert into events values(?,?,?)" );
String sql = buffer.toString();
Query query = session.createSQLQuery(sql);
query.setParameter(0, 4);
query.setParameter(1, "whd4");
query.setParameter(2, "24");
query.executeUpdate();
看到这个是不是很熟悉啊,对的hibernate是支持这种写法的。
到这里 查询和添加都搞定了,其实删除、修改和查询、添加相似就不在啰嗦了,接下来我们学习hibernate中的另一个增删该查:
3、hql方式的更新数据
(1)参数的传递方式:多参数的方式public int batchExecute(final String hql, final Object... values) {
return createQuery(hql, values).executeUpdate();
}
public Query createQuery(final String queryString, final Object... values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = getSession().createQuery(queryString);
if (values != null) {
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
}
return query;
}
不要被方法名称batchExecute给迷惑了,他不是批量执行,只是多个参数的更新
其中的参数hql一般都是: update User set name=? and address=?
而values 就是对应的姓名和地址即: "www","beijing";这样了,而下面的方法query.setParameter(i, values[i]);就是指定了索引数和值。
其中的User是java中定义的bean ,其实sql方式和hql的方式很像,区别在于一个面向对象,一个面向sql,也就是在from的地方一个是javabean 一个是数据库表名!
三、hibernate 中的Criterion
hibernate 提供的查询不仅有Query 而且有Criterion 下面我们来看看Criterion的使用
1、Criterion的查询 ------Restrictions
(1)、相等、排序
List list = session.createCriteria(Event.class).add(Restrictions.eq("name", "whd")).add(Restrictions.eq("id", 1)).addOrder(Order.desc("id")).list();
这里不经展示了Restrictions.eq() 而且还有Order来排序,order时就是要按那个字段排序的那个字段,下面还有一种排序之后会看到!
(2)、like、排序
List list = session.createCriteria(Event.class).add(Restrictions.like("name", "whd%")).addOrder(Order.desc("id")).list();
(3)、between and
List list = session.createCriteria(Event.class).add(Restrictions.between("id", 1, 100)).addOrder(Order.desc("id")).list();
(4)、in 集合的查询,可以使用collection 也可以使用数组格式
List lists=new ArrayList();
lists.add("whd");
lists.add("whd2");
lists.add("whd3");
这也就是in中的值
List list = session.createCriteria(Event.class).add(Restrictions.in("name",lists )).addOrder(Order.desc("id")).setMaxResults(2).list();
这里你看到了in 中有两个参数,一个就是Event中的属性字段 “name” 另一个就是一个集合lists 其中存放的就是指,这里的list也可以改为数组。
这里还要一个参数就是setMaxResults(2)这个方法,这个方法的作用就是获取前几条。
2、Criterion的查询 ------Property.forName()
(1)、使用Property.forName()来实现 between 方法
List list = session.createCriteria(Event.class).add(Property.forName("id").between(1, 100)).list();
其中的id就是Event 这个bean中的属性
(2)、Property.forName()相等条件的判断
List list = session.createCriteria(Event.class).add(Property.forName("name").eq("whd")).list();
(3)、Property.forName()中in的使用
List<String> mlist= new ArrayList<String>();
mlist.add("whd");
mlist.add("whd2");
mlist.add("whd3");
List list = session.createCriteria(Event.class).add(Property.forName("name").in(mlist)).addOrder(Property.forName("id").asc()).setMaxResults(2).list();
这里使用了in来查询,还是用了Property.forName("id").asc()实现了排序规则。
3、唯一性查询
(1)、uniqueResult 唯一性查询,如果有多个则会报异常
Event event = (Event)session.createCriteria(Event.class).add(Property.forName("name").eq("whd")).uniqueResult();
(2)、唯一性查询
Query query=session.createQuery("from Event where name =:myname");
query.setParameter("myname", "whd");
Event event=(Event) query.uniqueResult();
4、指定查询返回的列名称,这里你可以指定返回的是一本bean 或某列或多个列,注意:addEntity、addScalar 都是SQLQuery类的方法
(1)、addEntity 返回的是实例
SQLQuery query= session.createSQLQuery("select * from events");
//这里就限制了返回的类型,这里的话返回的就是Event实例
query.addEntity(Event.class);
List list= query.list();
Iterator it= list.iterator();
while(it.hasNext()){
Event event= (Event)it.next();
System.out.println(event.getId() +" "+event.getName());
}
(2)、使用addScalar来添加列的名称
SQLQuery query= session.createSQLQuery("select * from events");
// 这里就限制了返回的列,如果是单个可以直接转变为列的数据类型
query.addScalar("name");
List list= query.list();
Iterator it= list.iterator();
while(it.hasNext()){
String event= (String)it.next();
System.out.println(event);
}
(3)、使用addScalar来添加列的名称(多个)
SQLQuery query= session.createSQLQuery("select * from events");
// 这里指定了那几列在后面的结果中获取数据的时候就只能获取这么多不然会报outOfBountException
query.addScalar("id");
query.addScalar("name");
List list= query.list();
Iterator it= list.iterator();
while(it.hasNext()){
Object[] obj=(Object[])it.next();
//这里注意如果数组索引数大于限制的列数则会报异常
System.out.println(obj[0] +" "+obj[1]);
}
ok 到这里hibernate 的简单查询实例以及方式都弄明白了,但是上面有些写法会导致查询速度缓慢以及消耗大量内存,就比如上面的查询,吧所有列都查询出来了
才从所有列中组装需要的列,很浪费资源啊!!!!
四、hibernate中的count()函数查询
1、使用sql语句来实现count(id)/count(*) SQLQuery query= session.createSQLQuery("select count(id) from events");
int count = ((Number)query.uniqueResult()).intValue();
其中events就是表名,而Number是因为hibernate 升级为3.2的原因,也就是为了兼容!
2、使用hql语句来实现count(id) /count(*)
Query query= session.createQuery("select count(*) from Event");
int count= ((Number)query.uniqueResult()).intValue();
其中的Event 是javabean ,这个bean对应的也就是events这个表。
这个count(*) 查询刚开始的时候使用过普通查询那种方式,都不行再获取值的时候报异常,报这个异常的原因就是数据类型的转化问题!!!
ok到这里常用到的查询都ok了,下一篇我们学学更复杂点的……