根据主键进行检索
类名 对象 = session.get(类名.class,主键(Long));
类名 对象 = session.load(类名.class,主键(Long));
Hibernate根据一个已经查询到的对象,获取其关联的对象的一种查询方式
LinkMan linkMan = session.get(LinkMan.class,1L);
Customer customer = linMan.getCustomer();
Hibernate的查询语言,是一种面向对象的方式的查询语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询方式
格式: from 类名(可以全名,也可以不全名,只要映射配置好) 别名
Query query = session.createQuery("from Customer c");
List<Customer> list = query.list();
默认升序
格式: from 类名 order by 属性名 排序规则
Query query = session.createQuery("from Customer order by cust_id");
List<Customer> list = query.list();
Query query = session.createQuery("from Customer where cust_name = ? ");
//从0开始
query.setParameter(0,"1张三");
List<Customer> list = query.list();
Query query = session.createQuery("from Customer where cust_name = :aaa ");
query.setParameter("aaa","1张三");
查询对象的某个属性
List<Object> list = session.createQuery("select c.cust_name from Customer c").list();
for (Object obj:list){
System.out.println(obj);
}
查询某些属性
List<Object[]> list = session.createQuery("select c.cust_name,c.cust_source from Customer c").list();
for (Object[] objs:list){
System.out.println(Arrays.toString(objs));
}
将查询的某些属性装入对象中
前提:需要在对象中为需要查询的属性添加构造方法,注意别把无参构造弄没了
List<Customer> list = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list();
for (Customer customer:list){
System.out.println(customer);
}
List<Object[]> list = session.createQuery("select cust_source,count(*) from Customer group by cust_source having count(*) >= 2").list();
for (Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
Query query = session.createQuery("from LinkMan");
//从0开始
query.setFirstResult(0);
query.setMaxResults(10);
List<LinkMan> list = query.list();
for (LinkMan linkMan:list){
System.out.println(linkMan);
}
sql语句的函数在HQL中都可以使用
//uniqueResult获取唯一结果
Object object = session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(object);
原sql语句:
显示内连接:
select * from cst_customer c inner join cst_linkman l on c.cust_id = l.lkm_cust_id;
HQL的内连接:
List<Object[]> list = session.createQuery("from Customer c inner join c.linkMans").list();
for (Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
HQL的普通内连接查询接收到的对象是一个数组,我们可以使用迫切内连接将查询对象封装到对象中去
List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();
for (Customer customer:list){
System.out.println(customer);
}
条件查询,是一种更加面向对象化的查询方式
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer:list){
System.out.println(customer);
}
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.setFirstResult(0);
criteria.setMaxResults(10);
List<LinkMan> list = criteria.list();
for (LinkMan linkMan:list){
System.out.println(linkMan);
}
Criteria criteria = session.createCriteria(Customer.class);
criteria.addOrder(Order.desc("cust_id"));
List<Customer> list = criteria.list();
for (Customer customer:list){
System.out.println(customer);
}
Criteria criteria = session.createCriteria(Customer.class);
/**
* = eq
* > gt
* >= ge
* < lt
* <= le
* <> ne
* like
* in
* and(默认是并列的)
* or
*/
criteria.add(Restrictions.eq("cust_source","江苏"));
criteria.add(Restrictions.or(Restrictions.like("cust_name","1张%")));
List<Customer> list = criteria.list();
for (Customer customer:list){
System.out.println(customer);
}
Criteria criteria = session.createCriteria(Customer.class);
//count(*)
criteria.setProjection(Projections.rowCount());
Object o = criteria.uniqueResult();
System.out.println(o);
适用于sql条件比较多的项目,离线条件查询一般写在web层,拼接条件,然后传给service,调用dao,省去dao需要拼接许多sql的麻烦
//这下面两行代码写在web层,然后将DetachedCriteria对象传给service,调用dao
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
detachedCriteria.add(Restrictions.like("cust_name","1张%"));
//Dao代码
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
//绑定session
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
List<Customer> list = criteria.list();
for (Customer customer:list){
System.out.println(customer);
}
通过使用基本sql语句查询
SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
List<Object[]> list = sqlQuery.list();
for (Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
将查询结果封装到对象中
SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
sqlQuery.addEntity(Customer.class);
List<Customer> list = sqlQuery.list();
for (Customer customer:list){
System.out.println(customer);
}
延迟加载(懒加载):执行该行代码时,不会发送语句去查询,在真正使用这个对象的属性时才会去发送sql语句进行查询
类级别的延迟加载
指的是通过load方法查询某个对象多的时候,是否采用延迟
可以在需要查询的对象的映射配置的class标签上配置lazy属性,默认值为true,如果为false,则load方法的效果会与get方法一样
<class name="com.hibernate.pojo.Customer" table="cst_customer" lazy="false">
关联级别的延迟加载(重点:抓取策略往往会和关联级别的延迟加载一起使用,优化sql语句)
指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用了延迟加载
例如:
Customer customer = session.get(Customer.class, 1L);
customer.getLinkMans();//通过客户获取关联对象联系人,联系人对象是否采用了延迟加载,称为关联级别的延迟
概述:通过一个对象抓取到关联对象需要发送的sql语句,sql语句如何发送,发成什么样的格式通过策略进行配置,可以通过set或者many to one 标签上的fetch属性和lazy属性进行设置
默认设置fetch=“select” lazy=“true”
//查询1号客户
Customer customer = session.get(Customer.class, 1L);//发送一条根据客户id查询客户信息的sql,不关联查询联系人
//查询1号客户每个联系人的信息
for (LinkMan linkMan:customer.getLinkMans()){//发送一条根据客户id查询联系人的sql
System.out.println(linkMan.getLkm_name());
}
当客户需要使用关联对象的时候,他才会去查询关联对象
fetch=“select” lazy=“false”
//查询1号客户
Customer customer = session.get(Customer.class, 1L);//发送两条sql语句根据客户id查询客户信息的sql,根据客户id查询联系人
//查询1号客户每个联系人的信息
for (LinkMan linkMan:customer.getLinkMans()){
System.out.println(linkMan.getLkm_name());
}
即便不使用,他也会查询
fetch=“select” lazy=“extra”
//查询1号客户
Customer customer = session.get(Customer.class, 1L);//发送一条根据客户id查询客户信息的sql
System.out.println(customer.getLinkMans().size());//发送一条根据客户id查询联系人数目的sql
如果用不到对象中的属性,都不会发送查询信息的sql语句
fetch=“join”
//查询1号客户
Customer customer = session.get(Customer.class, 1L);//发送一条迫切左外连接的sql语句
//查询1号客户每个联系人的信息
for (LinkMan linkMan:customer.getLinkMans()){
System.out.println(linkMan.getLkm_name());
}
System.out.println(customer.getLinkMans().size());
如果fetch设置为join,他会发送一条迫切左外连接将客户和对应的联系人都查出来,这个时候不会发送第二条sql语句,所以lazy失效
fetch=“subselect” lazy=“true”
List<Customer> list = session.createQuery("from Customer").list();//查询所有客户的sql
for (Customer customer:list){
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());//发送一条子查询查询联系人信息
}
当客户需要使用关联对象的时候,他会使用子查询去查询关联对象的信息
问题:
List<Customer> list = session.createQuery("from Customer").list();
for (Customer customer:list){
System.out.println(customer.getCust_name());
for (LinkMan linkMan:customer.getLinkMans()){
System.out.println(linkMan.getLkm_name());
}
}
上面的代码运行后,首先会查询customer客户,然后在根据客户的id去一条一条的发送sql查询联系人,有多少客户就会发送多少sql,效率非常低
优化:
在set 标签上配置属性batch-size,一次查询多少条,就可以减少与数据库的交互
<set name="linkMans" cascade="delete,save-update" batch-size="5">
<key column="lkm_cust_id">key>
<one-to-many class="com.hibernate.pojo.LinkMan">one-to-many>
set>
联系人查询客户的时候也会这样,有多少联系人就会发送多少sql,可以在客户映射配置的class 标签上配置属性batch-size