hibernate基本查询
1)新建HibernateUtil类,用于封装创建Session的方法。如下:每个用户会对应一个Session,但是SessionFactory是共享的。
public class HibernateUtil {
private static SessionFactory sf;
static{//不用每次都加载配置信息,所以放static块中,否则每次都加载会耗费资源
Configuration conf=new Configuration();//加载主配置hibernate.cfg.xml
conf.configure("/hibernate.cfg.xml");
sf=conf.buildSessionFactory();//获取SessionFactory }
public static Session getSession(){//获取Session
Session session =sf.openSession(); return session; } }
2)基本的增删改查
/** get方法执行查询,按主键当条件查询,如何判断是主键,是根据写的描述文件来定,get方法就是findById,就是按主键去查,需指定:操作哪个类和id(主键)条件值即可,其他条件查询做不了 */
public Cost findById(int id) {
//Session session=HibernateUtil.getSession();
Cost cost=(Cost)session.get(Cost.class,id);
return cost;
}
save方法执行增加操作
注意1:获取事务并开启,增删改要注意,查询可以不管事务,因为没对数据库进行修改;
注意2:主键值根据hbm.xml中的<generator>定义生成,执行后,会先获取序列值,再去做insert操作。
即先:select COST_SEQ_CHANG.nextval from dual; 然后:insert into ……
public void save(Cost cost) {
//Session session=HibernateUtil.getSession();
Transaction tx=session.beginTransaction();//打开事务
session.save(cost);
session.close();//释放
}
delete方法执行删除操作,由于Hibernate以“对象”为单位进行数据库操作,所以这里要传进去一个对象,
虽然是个对象,但还是按主键做条件删除,只要把主键值设置上就行,其他非主键值不用管。也可先通过id查再删
public void delete(int id) {
//Session session=HibernateUtil.getSession();
Transaction tx=session.beginTransaction();
Cost cost=new Cost();
cost.setId(id);
session.delete(cost);
tx.commit();
session.close();
}
/** update方法执行修改操作, */
public void update(Cost cost) {
//Session session=HibernateUtil.getSession();
Transaction tx=session.beginTransaction();
session.update(cost);//将cost对象更新到数据库
tx.commit();
session.close();
}
3)通过Query做特殊查询
/** 通过Query做特殊查询、分页 */
public List<Cost> findAll(int page, int rowsPerPage) throws DAOException {
Session session=HibernateUtil.getSession();//分页查询
Transaction tx=session.beginTransaction();
String hql="from Cost";
Query query=session.createQuery(hql);
int start=(page-1)*rowsPerPage;//设置分页查询参数
query.setFirstResult(start);//设置抓取记录的起点,从0开始(第一条“记录”)
query.setMaxResults(rowsPerPage);//设置抓取多少条记录
List list=query.list();//按分页参数查询
tx.commit();
return list;
}
/**通过load做延迟加载查询
public Cost findById(Integer id) throws DAOException {
Session session=HibernateUtil.getSession();
Transaction tx=session.beginTransaction();
Cost cost=(Cost)session.load(Cost.class,id);
tx.commit();
String name=cost.getName();
return cost;
}
/**在hql语句中添加查询条件做单条记录的查询
public Cost findByName(String name) throws DAOException {
//select * from COST_CHANG where NAME=?
String hql="from Cost where name=?";
Session session=HibernateUtil.getSession();
Transaction tx=session.beginTransaction();
Query query=session.createQuery(hql);
query.setString(0, name);//注意Hibernate赋值从0开始,即第一个问号
Cost cost=(Cost)query.uniqueResult();//适用于只有一行查询结果返回
//如果返回记录为多条,则会报错,多条用query.list();
tx.commit();
return cost;
}
/**查询数据的总页数
public int getTotalPages(int rowsPerPage) throws DAOException {
//select count(*) from COST_CHANG
String hql="select count(*) from Cost";//类名
Session session=HibernateUtil.getSession();
Transaction tx=session.beginTransaction();
Query query=session.createQuery(hql);
Object obj=query.uniqueResult();
int totalRows=Integer.parseInt(obj.toString());
tx.commit();
session.close();
if(totalRows%rowsPerPage==0){
return totalRows/rowsPerPage;
}else {
return (totalRows/rowsPerPage)+1;
}
}
4)HQL查询典型案例
public void test1(){//查询所有账务账号信息
String hql="from Account";
Session session=HibernateUtil.getSession();
Query query=session.createQuery(hql);
List<Account> list=query.list();//如果查询出多条结果
for(Account a:list){
System.out.println(a.getId()+" "+a.getRealName()+" "+a.getIdcardNo());
}
session.close();
}
@Test //SQL:select * from ACCOUNT_CHANG where REAL_NAME like ?
public void test2() {//按真名模糊查询
//多个条件也可继续加 and XX=? or XX=?
String hql="from Account where realName like ?";//方式一
//String hql="from Account where realName like :n";//方式二
Session session=HibernateUtil.getSession();
Query query=session.createQuery(hql);
query.setString(0, "zhang%");//方式一:设置查询参数,从0开始表示第一个?
//query.setString("n", "zhang%");//方式二:给:n赋值,就不用数问号是第几个了
//zhang_表示以zhang开头的两个字名字
List<Account> list=query.list();//如果查询出多条结果
for(Account a:list){
System.out.println(a.getId()+" "+a.getRealName()+" "+a.getIdcardNo());
}
session.close();
}
@Test //SQL:select ID,REAL_NAME,IDCARD_NO from ACCOUNT_CHANG
public void test3(){//查询部分字段方式一
String hql="select id,realName,idcardNo from Account";
Session session=HibernateUtil.getSession();
Query query=session.createQuery(hql);
/**部分查询,默认采用Object[]封装一行记录的字段值,数组的大小、顺序和写的HQL属性的个数、顺序一致!
注意事项:只要是单独列出的属性,则返回的就是Object数组!*/
List<Object[]> list=query.list();
for(Object[] objs:list){//若写成原实体Account则报错类型转换异常
System.out.println(objs[0]+" "+objs[1]+" "+objs[2]);
}
session.close();
}
@Test //SQL:select ID,REAL_NAME,IDCARD_NO from ACCOUNT_CHANG
public void test4(){//查询部分字段方式二
String hql="select new Account(id,realName,idcardNo) from Account";
/** 为了支持它,需要在Account实体中加构造方法,无参的也加上(否则影响其他地方的使用)。或者写个新的实体类也可以。 */
Session session=HibernateUtil.getSession();
Query query=session.createQuery(hql);
//部分查询,采用指定的Account的构造方法封装一行记录的字段值
List<Account> list=query.list();
for(Account a:list){//注意:显示其他属性将会是初始值
System.out.println(a.getId()+" "+a.getRealName()+" "+a.getIdcardNo());
}
session.close();
}
step5:其他测试
在Account.hbm.xml中添加HQL语句
<class name="org.tarena.entity.Account" table="ACCOUNT_CHANG" ></class>
<!-- 和class是平级的!一个query标签写一个HQL语句 -->
<query name="findAll"><!-- 起个名字 -->
<![CDATA[from Account]]><!--怕特殊符号影响语句,放CDATA段中作为纯文本-->
</query>
@Test
public void test5(){//将HQL定义到hbm.xml中
Session session=HibernateUtil.getSession();
//session.getNamedQuery()方法,会去hbm.xml中找HQL语句
Query query=session.getNamedQuery("findAll");
List<Account> list=query.list();//如果查询出多条结果
for(Account a:list){
System.out.println(a.getId()+" "+a.getRealName()+" "+a.getIdcardNo());
}
session.close();
}
public void test7(){//对象关联查询
String hql="";//只要是单独列出的属性则返回的就是object数组!
//hql +="select s.id,s.osUsername,s.unixHost,a.realName,a.idcardNo ";/** 方式一 */
//hql +="from Service s join s.account a ";//不能写on子句,多对一
//hql +="from Account a join a.services s ";//或反过来,一对多
/** 方式二:一定要有“属性”才能"."点出来,若属性是集合、数组,则它们里面没有其他属性,不能“.”出来 */
hql +="select s.id,s.osUsername,s.unixHost, s.account.realName,s.account.idcardNo ";
hql +="from Service s";
//因为不能写on子句,再加上Service中有account属性,所以关联属性写s.account
Session session=HibernateUtil.getSession();
Query query=session.createQuery(hql);
List<Object[]> list=query.list();
for(Object[] objs:list){
System.out.println(objs[0]+" "+objs[1]+" "+objs[2]+" "+objs[3]+" "+objs[4]);
}
session.close();
}
5)Criteria查询
public void test3(){//追加两个条件
Session session=HibernateUtil.getSession();
Criteria c=session.createCriteria(Account.class);
//c.add(Restrictions.like("realName", "zhang%"));
c.add(//当条件多时,就比较麻烦了
Restrictions.and( Restrictions.like("realName", "zhang%"),
Restrictions.eq("idcardNo", "410381194302256528")) );
c.addOrder(Order.desc("id"));//追加排序 List<Account> list=c.list();
for(Account a:list){
System.out.println(a.getId()+" "+a.getRealName()+" "+a.getIdcardNo()); }
session.close();
}
6)Native SQL原生SQL查询
1)基本使用:
SQLQuery query=session.createSQLQuery(sql);
List<Object[]> list=query.list();//默认封装成Object数组
注意事项:一些特殊的函数Hibernate无法执行需使用原生SQL,极其复杂的操作也可用原生SQL。
2)案例:创建TestSQLQuery类,用于测试原生SQL查询(同样借助以前的实体和映射)
@Test
public void test1(){//没有用到映射文件
String sql="select * from ACCOUNT_CHANG";
Session session=HibernateUtil.getSession();
SQLQuery query=session.createSQLQuery(sql);
query.setFirstResult(0);//分页查询 query.setMaxResults(5);
List<Object[]> list=query.list();
for(Object[] objs:list){ System.out.println(objs[0]+" "+objs[1]+" "+objs[2]); }
session.close(); }
@Test
public void test2(){//改变test1中的封装类型
String sql="select * from ACCOUNT_CHANG";
Session session=HibernateUtil.getSession();
SQLQuery query=session.createSQLQuery(sql);
/** 改变封装类型,利用该类型映射(映射描述将起作用),封装一条记录(全字段的,部分字段不行) */
query.addEntity(Account.class); List<Account> list=query.list();
for(Account a:list){ System.out.println(a.getId()+" "+a.getRealName()); }
session.close();