我们在用到hibernate框架的时候经常和Hql语言打交道,这是把面向对象贯彻到骨髓的设计。我们通过实例来展示它的强大用处。
下图是数据库中的数据:
新建了一个实体类UserEntity.java:
@Entity
@Table(name = "user_tbl")
public class UserEntity {
private int id;
private String name;
private String password;
private int age;
private int sex;
public UserEntity(){
}
public UserEntity(String name, int age) {
this.name = name;
this.age = age;
}
@Id
@Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(name = "age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Column(name = "sex",columnDefinition = "tinyint")
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
1.查询单个对象,比如我们可以根据ID来查,用ID来确保唯一的数据,但是这里我们使用getFirstResult(index).setMaxResult(1).uniqueResult()来查,下面是相关代码:
StringBuffer infoHql = new StringBuffer("from UserEntity");
//只能查唯一的数据集,如果数据库中有两条数据,可以通过setFirstResult(0)[从0开始]查唯一的那条数据
UserEntity user = (UserEntity)sessionFactory.getCurrentSession().createQuery(infoHql.toString())
.setFirstResult(0).setMaxResults(1).uniqueResult();
我们可以发现getFirstResult(index)里面的index就是一个索引值,它是从0开始的。返回的结果我们用JSON格式化后可以看到:
{"age":12,"id":1,"name":"yang","password":"123","sex":0}
2.比如我们想查表中特定的字段,比如user_tbl,我只想查name,age,sex的话,我们可以通过下面的查到
StringBuffer infoHql = new StringBuffer("select name,age,sex from UserEntity");
List<Object> objs = sessionFactory.getCurrentSession().createQuery(infoHql.toString()).list();
Iterator<Object> iter = objs.iterator();
while(iter.hasNext()){
Object[] o = (Object[])iter.next();
logger.info("name:"+o[0]);
logger.info("age:"+o[1]);
logger.info("sex:"+o[2]);
}
我们可以看到返回的结果是一个Object数组组成的链表。这种往往不是我们想要的结果,我们想封装结果怎么办? 我们新建一个对象UserModel,然后以这种格式返回
StringBuffer infoHql = new StringBuffer("select new com.rey.entities.UserModel(u.name,u.age) from UserEntity as u");
List<UserEntity> users = sessionFactory.getCurrentSession().createQuery(infoHql.toString()).list();
返回的结果我们可以看到:
[{"age":12,"name":"yang"},{"age":18,"name":"eng"},{"age":20,"name":"oo"}]
3.如果我们查数据库中单个列的话,我们通过createQuery(hql).list() 是可以返回相应的数据的,比如我们可以看到下面的例子:
StringBuffer idsHql = new StringBuffer("select id from UserEntity");
List<Integer> ids = sessionFactory.getCurrentSession().createQuery(idsHql.toString()).list();
上面的ids将返回id组成的List,这时候HQL查询就可以识别出查询出来的结果是什么类型的数据了。这点我们需要注意。
当然我们也可以使用Criteria查询来做上面的业务逻辑,代码如下:
Criteria criteria= sessionFactory.getCurrentSession().createCriteria(UserEntity.class);
criteria.setProjection(Projections.projectionList().add(Projections.id().as("id"))
.add(Projections.property("name").as("name")))
.setResultTransformer(new AliasToBeanResultTransformer(UserEntity.class));
List<UserEntity> list = criteria.list();
可以将结果转换为UserEntity对象来做处理,用JSON做返回的结果集,输出结果为:
[{"age":0,"id":1,"name":"yang","sex":0},
{"age":0,"id":2,"name":"deng","sex":0},
{"age":0,"id":3,"name":"li","sex":0},
{"age":0,"id":4,"name":"wei","sex":0}]
4.有时候我们在用HQL进行查询的时候经常会用ID来查相关联的两个实体类,这样就可以用cross 查询来连接。
from ViewPointEntity as v,UserEntity as u where v.id= 21 and v.userId = u.id
然后通过对象数组的形式拿取相应的实体类
Object[] o = (Object[]) sessionFactory.getCurrentSession().createQuery(viewHql.toString()).uniqueResult();
ViewPointEntity viewPoint = (ViewPointEntity) o[0];
UserEntity friendUserEntity = (UserEntity) o[1];
拿到实体类我们就可以返回前端想要的数据了。网上说根据ID来一个个查询的速率比这个快,这个有待测试~~
5.在hql中我们经常遇到in关键字在数据库中不能排序的问题,解决方案是连接查询就可以根据条件表来关联数据。
这里我们查用户id为52的用户收藏的观点,但是我们收藏的观点是无序的,所以我们连接观点表根据观点表中的发布时间降序排列
select * from viewpoint_tbl as v left join
collect_tbl as c on v.id = c.src_id where c.src_type=1 and c.user_id = 52
order by c.reg_time desc
上面我们用到了原生的SQL查询,在session查询的时候要用到createSQLQuery()方法来查询
6.有时候我们使用原生的SQL语句对三种不同情况的数据进行统计,比如下面的例子SQL,
select condition1,condition2,condition3 from (xxx) as condition1,(xxx) as condition2,(xxx) as condition3
然后我们使用createSQLQuery方法进行查询,我们想分别得到condition1,condition2,condition3的值,我们可以将查询的结果转换为Map<String,Object>结构
Map<String,Object> map = (Map<String,Object>)createSQLQuery(hql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).uniqueResult()
然后根据map.get(condition1) 就可以拿到相应的结果了。
上面的例子是转成Map来提取的,其实也可以不用转成Map,直接用Object[]对象就可以
List<Object[]> newsestList = session.createSQLQuery(newsestHql.toString()).setFirstResult((page - 1) * maxNum).setMaxResults(maxNum).list();
然后遍历上面的newsestList对象就可以了。
if(newsestList!= null && newsestList.size()>0){
for(Object[] obj : newsestList){
int condition1= Integer.parseInt(obj[1].toString());}}