http://blog.csdn.net/yerenyuan_pku/article/details/70554816

Hibernate检索方式概述

我们在对数据库的操作中,最常用的是select,那么使用Hibernate如何进行select操作呢?本文就来徐徐道来。 
Hibernate检索方式可分为5种:

  1. 导航对象图检索方式,根据已加载的对象导航到其它对象。
  2. OID检索方式,按照对象的OID来检索对象。
  3. HQL检索方式,使用面向对象的HQL查询语言。
  4. QBC检索方式,使用QBC(Query by Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
  5. 本地SQL检索方式,使用本地数据库的SQL查询语句。

导航对象图检索方式

导航对象图检索这种方式我们也是经常用的,例如:

Customer c = session.get(Customer.class, 2);
System.out.println(c.getOrders().size());

所谓的导航对象图检索方式就是通过在Hibernate中进行映射关系,然后在Hibernate操作时,可以通过导航方式得到其关联的持久化对象信息。

OID检索方式

OID检索这种检索方式我们用的也是比较多的,例如:

session.get(Customer.class, 3);
session.load(Order.class, 1);

Hibernate中通过get/load方法查询指定的对象要通过OID来查询。

HQL

HQL是我们在Hibernate中最常用的一种检索方式。HQL(Hibernate Query Language)提供了更加丰富灵活、更为强大的查询能力,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖Criteria查询的所有功能的前提下,提供了类似标准SQL语句的查询方式,同时也提供了更加面向对象的封装。完整的HQL语句形式如下:select/update/delete…… from …… where …… group by …… having …… order by …… asc/desc 其中的update/delete为Hibernate3中所新添加的功能,可见HQL查询非常类似于标准SQL查询。HQL检索的基本步骤:

  1. 得到Session
  2. 编写HQL语句
  3. 通过session.createQuery(hql)创建一个Query对象
  4. 为Query对象设置条件参数
  5. 执行list()查询所有,它返回的是一个List集合或者执行uniqueResult()返回一个查询结果

数据准备

首先肯定是搭建好Hibernate的开发环境啦,我在此也不过多赘述,读者自行实践。接着在src目录下创建一个cn.itheima.domain包,并在该包下创建两个实体类,分别是客户类(Customer)和订单类(Order),而且这两个实体类都使用注解配置,所以就不用编写那个映射配置文件啦!

  • 客户类(Customer)

    // 客户 ---- 一的一方
    @Entity
    @Table(name="t_customer")
    public class Customer { @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id; // 主键
    private String name; // 姓名 // 描述客户可以有多个订单
    /*
    * targetEntity="...":相当于<one-to-many class="...">
    * mappedBy="...":相当于inverse=true,即放弃关联关系的维护,不然会生成一个中间表
    */
    @OneToMany(targetEntity=Order.class,mappedBy="c")
    private Set<Order> orders = new HashSet<Order>(); public Customer() { } public Customer(Integer id, String name) {
    super();
    this.id = id;
    this.name = name;
    } public Set<Order> getOrders() {
    return orders;
    }
    public void setOrders(Set<Order> orders) {
    this.orders = orders;
    }
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    } @Override
    public String toString() {
    return "Customer [id=" + id + ", name=" + name + ", orders=" + orders + "]";
    } }
  • 订单类(Order)

    // 订单 ---- 多的一方
    @Entity
    @Table(name="t_order")
    public class Order { @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private Double money;
    private String receiverInfo; // 收货地址 // 订单与客户关联
    @ManyToOne(targetEntity=Customer.class)
    @JoinColumn(name="c_customer_id") // 指定外键列
    @Cascade(CascadeType.SAVE_UPDATE)
    private Customer c; // 描述订单属于某一个客户 public Customer getC() {
    return c;
    }
    public void setC(Customer c) {
    this.c = c;
    }
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public Double getMoney() {
    return money;
    }
    public void setMoney(Double money) {
    this.money = money;
    }
    public String getReceiverInfo() {
    return receiverInfo;
    }
    public void setReceiverInfo(String receiverInfo) {
    this.receiverInfo = receiverInfo;
    } @Override
    public String toString() {
    return "Order [id=" + id + ", money=" + money + ", receiverInfo=" + receiverInfo + "]";
    } }

编写完以上两个实体类之后,我们可千万不要忘记了下面这一步:我们最终需要在hibernate.cfg.xml文件中将我们类中的注解配置引用生效。即需要在Hibernate核心配置文件中添加如下配置:

<mapping class="cn.itheima.domain.Customer"/>
<mapping class="cn.itheima.domain.Order"/>

接下来,我就来准备一些数据,不然查什么呢?我是这样做的,添加武松和潘金莲两个客户,每个客户都下10个订单,又因为我在订单类中做了级联操作,所以一旦订单关联了客户,那么保存订单时,就会顺便保存客户。怎么做到呢?在src目录下新建一个cn.itheima.test包,在该包下编写一个HQLTest单元测试类,并在该包下编写如下方法:

public class HQLTest {

    // 准备数据(2个Customer,每一个Customer有10个Order)
@Test
public void test1() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); /*
// 操作
Customer c = new Customer();
c.setName("武松"); for (int i = 0; i < 10; i++) {
Order order = new Order();
order.setMoney(1000d + i * 10);
order.setReceiverInfo("北京");
order.setC(c);
session.save(order);
}
*/ Customer c = new Customer();
c.setName("潘金莲"); for (int i = 0; i < 10; i++) {
Order order = new Order();
order.setMoney(2000d + i * 10);
order.setReceiverInfo("上海");
order.setC(c);
session.save(order);
} session.getTransaction().commit();
session.close();
}
}

测试以上方法之后,我们所想要的数据就准备好了,下面就正式进入正题。

基本检索

基本检索就是from 类名,from是关键字,后面是类名,关键字是不区分大小写的,但是类名是区分的。以码明示,在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 基本检索
@Test
public void test2() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1.编写HQL语句
String hql = "from Customer"; // from是关键字,后面是类名,关键字是不区分大小写的,但是类名是区分的
// 2.通过session.createQuery(hql)去把HQL语句作为参数传递
Query query = session.createQuery(hql);
// 3.通过list方法得到数据
// List<Customer> list = query.list(); // Hibernate在操作时还支持链式编程,如下:
List<Customer> list = session.createQuery(hql).list();
System.out.println(list.get(0)); session.getTransaction().commit();
session.close();
} }

从上可知Hibernate在操作时还支持链式编程,即session.createQuery(hql).list()

排序检索

现在我们的需求是查询订单时,根据订单的价格进行降序排序。以码明示,在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 排序检索——查询订单,根据订单的价格进行排序
@Test
public void test3() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1.定义HQL语句
String hql = "from Order order by money desc"; // desc:降序,默认是asc(升序)
// 2.执行hql语句,根据价格进行排序
List<Order> list = session.createQuery(hql).list(); System.out.println(list); session.getTransaction().commit();
session.close();
} }

条件检索

我首先来讲根据位置来绑定hql语句参数的条件检索。以码明示,在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 条件查询
@Test
public void test4() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1根据位置来绑定参数
// 1.1创建hql语句
String hql = "from Order where money > ?"; // 1.2执行hql语句
List<Order> list = session.createQuery(hql).setParameter(0, 2000d).list();
// 可以使用例如setString()、setDouble这样的方法来添加参数,参数的序号是从0开始 session.getTransaction().commit();
session.close();
} }

接着来讲根据名称来绑定hql语句参数的条件检索,将以上test4方法修改为:

public class HQLTest {

    // 条件查询
@Test
public void test4() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.根据名称来绑定
// 1.1创建hql语句
String hql = "from Order where money > :mymoney"; // 1.2执行hql语句
List<Order> list = session.createQuery(hql).setParameter("mymoney", 2000d).list(); System.out.println(list); session.getTransaction().commit();
session.close();
} }

分页检索

现在我们的需求是查询订单时,每页显示6条数据,我们要得到第二页的数据。以码明示,在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 分页检索
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); Query query = session.createQuery("from Order");
// 每页显示6条数据,我们要得到第二页数据
query.setFirstResult((2 - 1) * 6); // 设定开始位置
query.setMaxResults(6); // 设置条数 List<Order> list = query.list();
System.out.println(list); session.getTransaction().commit();
session.close();
} }

分组统计检索

先看我们的第一个需求:统计一共有多少个订单。以码明示,在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 分组统计操作
@Test
public void test6() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 统计操作——统计一共有多少订单(count)
String hql = "select count(*) from Order"; Object count = session.createQuery(hql).uniqueResult();
System.out.println(count); session.getTransaction().commit();
session.close();
} }

再看我们的第二个需求:分组统计每一个人的订单总价。那么以上test6方法应修改为:

public class HQLTest {

    // 分组统计操作
@Test
public void test6() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 分组统计——每一个人的订单总价()
String hql = "select sum(money) from Order group by c";
List list = session.createQuery(hql).list();
System.out.println(list); session.getTransaction().commit();
session.close();
} }

投影检索

这儿我也只是主要讲解关于实体类中部分属性的查询,这样我们可以使用投影检索将部分属性封装到对象中。下面我步步为营地讲解投影检索。开始,我们的需求可能是这样的:查询出所有Customer的name,故我们可能会在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 投影查询
@Test
public void test7() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1.查询出所有的Customer的name
String hql = "select name from Customer"; List list = session.createQuery(hql).list();
System.out.println(list); // [武松, 潘金莲] // 如果只查询一个列,得到的结果是List<Object> session.getTransaction().commit();
session.close();
} }

运行以上方法,输出[武松, 潘金莲],则可以得出结论:如果只是查询一个列,那么得到的结果是List<Object>。 
接着我们的需求又可能会变成这样:查询所有Customer的id、name。故我们可能会在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 投影查询
@Test
public void test7() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.查询所有的Customer的id, name
String hql = "select id,name from Customer";
List list = session.createQuery(hql).list();
System.out.println(list); session.getTransaction().commit();
session.close();
} }

运行以上方法,输出[[Ljava.lang.Object;@592e843a, [Ljava.lang.Object;@1d1f7216],则说明如果是查询多列,那么得到的结果是List<Object[]>。故可将以上test7方法改为:

public class HQLTest {

    // 投影查询
@Test
public void test7() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.查询所有的Customer的id, name
String hql = "select id,name from Customer";
List<Object[]> list = session.createQuery(hql).list();
for (Object[] objs : list) {
for (Object obj : objs) {
System.out.print(obj + " ");
}
System.out.println();
}
// 如果是查询多列,得到的结果是List<Object[]> session.getTransaction().commit();
session.close();
} }

运行以上方法,输出:

1 武松 
2 潘金莲

最后我们可想到使用投影查询将查询的结果封装到Customer对象中。故可将以上test7方法改为:

public class HQLTest {

    // 投影查询
@Test
public void test7() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 3.使用投影查询将查询的结果封装到Customer对象中
String hql = "select new Customer(id,name) from Customer"; // 必须在PO类中提供对应的构造方法
List<Customer> cs = session.createQuery(hql).list();
System.out.println(cs); session.getTransaction().commit();
session.close();
} }

注意:我们必须在PO类中提供对应属性的构造方法,也要有无参数构造。

命名检索

现在我就来讲命名检索了,我们可以将HQL语句先定义出来,在使用时通过session.getNamedQuery(hqlName);得到一个Query对象,然后再执行检索。那么问题就来了,这个HQL语句到底定义在什么位置呢?答案如下:

  1. 如果你有hbm映射配置文件,那么当前的hql操作是针对哪一个实体进行操作的,就在哪一个实体的映射配置文件中进行声明。声明如下:

    <query name="myHql">
    from Customer
    </query>
  2. 如果是使用注解来描述PO类的配置,那么我们可直接在PO类中使用@NamedQuery注解来声明。例如:

    @Entity
    @Table(name="t_customer")
    @NamedQuery(name="myHql", query="from Customer")
    public class Customer {
    ......
    }

第一种方式我就不讲了,专讲第二种方式。在Customer实体类中使用@NamedQuery注解,如下:

// 客户 ---- 一的一方
@Entity
@Table(name="t_customer")
@NamedQuery(name="myHql", query="from Customer")
public class Customer { @Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id; // 主键
private String name; // 姓名 // 描述客户可以有多个订单
/*
* targetEntity="...":相当于<one-to-many class="...">
* mappedBy="...":相当于inverse=true,即放弃关联关系的维护,不然会生成一个中间表
*/
@OneToMany(targetEntity=Order.class,mappedBy="c")
private Set<Order> orders = new HashSet<Order>(); public Customer() { } public Customer(Integer id, String name) {
super();
this.id = id;
this.name = name;
} public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", orders=" + orders + "]";
} }

此时我们是准备查询所有客户的,以码明示,在HQLTest单元测试类中编写如下单元测试方法:

public class HQLTest {

    // 命名查询
@Test
public void test8() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); Query query = session.getNamedQuery("myHql");
List<Customer> list = query.list();
System.out.println(list); session.getTransaction().commit();
session.close();
} }

运行以上方法,不仅查询出了客户的基本信息,还查询出了客户下的所有订单。 
现在我们有了这么一个需求:查询【武松】这个客户的所有订单。解决方法如下:

  1. 在Order实体类中使用@NamedQuery注解,如下:

    // 订单 ---- 多的一方
    @Entity
    @Table(name="t_order")
    @NamedQuery(name="findOrderByCustomer", query="from Order where c = :c")
    public class Order { @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private Double money;
    private String receiverInfo; // 收货地址 // 订单与客户关联
    @ManyToOne(targetEntity=Customer.class)
    @JoinColumn(name="c_customer_id") // 指定外键列
    @Cascade(CascadeType.SAVE_UPDATE)
    private Customer c; // 描述订单属于某一个客户 public Customer getC() {
    return c;
    }
    public void setC(Customer c) {
    this.c = c;
    }
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public Double getMoney() {
    return money;
    }
    public void setMoney(Double money) {
    this.money = money;
    }
    public String getReceiverInfo() {
    return receiverInfo;
    }
    public void setReceiverInfo(String receiverInfo) {
    this.receiverInfo = receiverInfo;
    } @Override
    public String toString() {
    return "Order [id=" + id + ", money=" + money + ", receiverInfo=" + receiverInfo + "]";
    } }
  2. 在HQLTest单元测试类中编写如下单元测试方法:

    public class HQLTest {
    
        // 命名查询
    @Test
    public void test9() {
    Session session = HibernateUtils.openSession();
    session.beginTransaction(); // 1.我要查询武松这个客户的订单
    Customer c = session.get(Customer.class, 1); Query query = session.getNamedQuery("findOrderByCustomer");
    // 现在hql语句里面的参数是一个实体,那么我们在操作它时怎么办?
    List<Order> list = query.setEntity("c", c).list(); System.out.println(list); session.getTransaction().commit();
    session.close();
    } }

QBC

QBC(query by criteria),它是一种更加面向对象的检索方式。使用QBC检索的步骤为:

  1. 通过Session的createCriteria方法得到一个Criteria对象,即session.createCriteria()
  2. 设定条件,每个Criterion实例就代表一个条件,它的获取可以通过Restrictions类提供的静态方法得到,然后可通过Criteria的add方法添加查询条件
  3. 调用Criterion的list方法进行查询,即criterion.list()

基本检索

有一个需求:查询所有的Customer对象。以码明示,在cn.itheima.test包下编写一个QBCTest单元测试类,并在改类中编写如下测试方法:

public class QBCTest {

    // 基本检索
@Test
public void test1() {
// 查询所有的Customer对象
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1.得到Criteria对象
Criteria criteria = session.createCriteria(Customer.class); // 2.调用list方法得到List集合
List<Customer> list = criteria.list(); System.out.println(list); session.getTransaction().commit();
session.close();
} }

排序检索

有这样一个需求:查询订单信息,并根据订单的价格进行排序。以码明示,在QBCTest单元测试类中编写如下测试方法:

public class QBCTest {

    // 排序检索
@Test
public void test2() {
// 查询订单信息,根据订单的价格进行排序
Session session = HibernateUtils.openSession();
session.beginTransaction(); Criteria criteria = session.createCriteria(Order.class);
// 指定排序
// criteria.addOrder(org.hibernate.criterion.Order.desc("money")); // 降序排序
criteria.addOrder(org.hibernate.criterion.Order.asc("money")); // 升序排序 List<Order> list = criteria.list(); System.out.println(list); session.getTransaction().commit();
session.close();
} }

条件检索

有这样一个需求:查询名称叫武某(武_)的客户。 以码明示,在QBCTest单元测试类中编写如下测试方法:

public class QBCTest {

    // 条件检索
@Test
public void test3() { Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1.查询名称叫武某的客户 武_
Criteria criteria = session.createCriteria(Customer.class);
Criterion like = Restrictions.like("name", "武_");
criteria.add(like); // 添加条件
/*
* 其他条件:
* lt:<
* gt:>
* le:<=
* ge:>=
* eq:==
*/
Customer c = (Customer) criteria.uniqueResult();
System.out.println(c); session.getTransaction().commit();
session.close(); } }

现在又有这样一个需求:查询订单价格在1050以上的订单,并且它的客户是武某。以码明示,将QBCTest单元测试类中的test3方法修改为:

public class QBCTest {

    // 条件检索
@Test
public void test3() { Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.查询订单价格在1050以上的订单,并且它的客户是武某
Criteria cri = session.createCriteria(Order.class); SimpleExpression lt = Restrictions.gt("money", 1050d);
SimpleExpression eq = Restrictions.eq("c", c);
LogicalExpression and = Restrictions.and(lt, eq);
cri.add(and);
List<Order> orders = cri.list(); // 上面代码写的非常臃肿,可简化为
// List<Order> orders = cri.add(Restrictions.and(Restrictions.gt("money", 1050d), Restrictions.eq("c", c))).list(); System.out.println(orders); session.getTransaction().commit();
session.close(); } }

分页检索

有这样一个需求:查询订单时,每页显示6条数据,我们要得到第二页的数据。以码明示,在QBCTest单元测试类中编写如下单元测试方法:

public class QBCTest {

    // 分页检索
@Test
public void test4() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); Criteria criteria = session.createCriteria(Order.class);
criteria.setFirstResult((2 - 1) * 6);
criteria.setMaxResults(6);
List<Order> list = criteria.list(); System.out.println(list); session.getTransaction().commit();
session.close();
} }

统计分组检索

有这样一个需求:统计订单总数。以码明示,在QBCTest单元测试类中编写如下单元测试方法:

public class QBCTest {

    // 统计检索
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 1.统计订单总数
Criteria criteria = session.createCriteria(Order.class);
Object obj = criteria.setProjection(Projections.rowCount()).uniqueResult(); // 统计总行数,可以理解为count(*)
System.out.println(obj); session.getTransaction().commit();
session.close();
} }

现在又有这样一个需求:根据客户分组统计订单的总价格。以码明示,将QBCTest单元测试类中的test5方法修改为:

public class QBCTest {

    // 统计检索
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.订单的总价格——根据客户分组统计
// criteria.setProjection(Projections.sum("money")); // 统计总金额 criteria.setProjection(Projections.projectionList().add(Projections.sum("money")).add(Projections.groupProperty("c"))); List<Object[]> list = criteria.list(); // 在这个集合中,保存的是Object[money的统计信息, 客户信息] for (Object[] objs : list) {
for (Object obj : objs) {
System.out.println(obj);
}
} session.getTransaction().commit();
session.close();
} }

从以上代码可知,criteria.list()所得结果类型是List<Object[]>,在这个集合中,保存的是Object数组,数组的第一个元素是money的统计信息,第二个元素是客户信息。

离线条件检索

Hibernate框架支持在运行时动态生成查询语句,DetachedCriteria对象可以脱离session而使用。之前我们在三层架构之间传递用户提交的参数可能是这样的: 

但使用离线条件对象进行检索时,情况又可能是这样的: 

现在有这样一个需求:查询名称叫武某(武_)的客户。以码明示, 在QBCTest单元测试类中编写如下单元测试方法:

public class QBCTest {

    // 离线的检索
@Test
public void test6() {
// 1.得到一个DetachedCriteria对象
DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
dc.add(Restrictions.like("name", "武_")); // 2.生成Criteria执行我们的操作
Session session = HibernateUtils.openSession();
session.beginTransaction();
Criteria criteria = dc.getExecutableCriteria(session);
List<Customer> list = criteria.list(); System.out.println(list);
session.getTransaction().commit();
session.close();
} }

本地SQL

有这样一个需求:查询所有的Customer对象。以码明示, 在cn.itheima.test包中编写一个SQLTest单元测试类,并在类中编写如下方法:

public class SQLTest {

    // 测试执行本地sql
@Test
public void test1() { Session session = HibernateUtils.openSession();
session.beginTransaction(); // 执行本地sql
SQLQuery sqlQuery = session.createSQLQuery("select * from t_customer");
// List list = sqlQuery.list();
// System.out.println(list); // List<Object[]> list = sqlQuery.list(); sqlQuery.addEntity(Customer.class); // 如何能得到一个对象呢?
// 将查询结果绑定到指定对象
List list = sqlQuery.list();
System.out.println(list); session.getTransaction().commit();
session.close(); } }

需要说明的是本地sql也支持命名查询。那么问题就来了,这个本地sql语句到底定义在什么位置呢?答案如下:

  1. 如果你有hbm映射配置文件,那么当前的sql操作是针对哪一个实体进行操作的,就在哪一个实体的映射配置文件中进行声明。声明如下:

    <sql-query name="xxx">...</sql-query>
    • 1
    • 1
  2. 本地命名sql使用注解来定义,例如,在Customer实体类上添加一个@NamedNativeQuery注解,如下:

    // 客户 ---- 一的一方
    @Entity
    @Table(name="t_customer")
    @NamedQuery(name="myHql", query="from Customer")
    @NamedNativeQuery(name="findCustomer",query="select * from t_customer")
    public class Customer { ....... }

    接着在SQLTest单元测试类中编写如下方法:

    public class SQLTest {
    
        // 测试本地sql命名查询
    @Test
    public void test2() { Session session = HibernateUtils.openSession();
    session.beginTransaction(); Query query = session.getNamedQuery("findCustomer");
    List list = query.list();
    System.out.println(list); session.getTransaction().commit();
    session.close(); } }

    test2方法正常运行,并没有所谓的异常。可能有些同学运行时,会报以下异常: 
     
    出现问题的原因是Hibernate框架不知道执行select * from t_customer语句后如何将结果封装。要想解决该异常,Customer实体类的代码应修改为:

    // 客户 ---- 一的一方
    @Entity
    @Table(name="t_customer")
    @NamedQuery(name="myHql", query="from Customer")
    // @SqlResultSetMapping注解才真正帮我们去规定执行sql语句如何将结果封装到Customer对象
    @SqlResultSetMapping(name="customerSetMapping",entities={ @EntityResult(entityClass=Customer.class,fields={
    @FieldResult(name="id",column="id"),@FieldResult(name="name",column="name") }) })
    // fields指定类里面的每一个属性跟表中的列是如何对应的
    @NamedNativeQuery(name="findCustomer",query="select * from t_customer",resultSetMapping="customerSetMapping")
    // resultSetMapping需要指定一个名字,它用来指定结果如何封装的操作
    public class Customer { @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id; // 主键
    private String name; // 姓名 // 描述客户可以有多个订单
    /*
    * targetEntity="...":相当于<one-to-many class="...">
    * mappedBy="...":相当于inverse=true,即放弃关联关系的维护,不然会生成一个中间表
    */
    @OneToMany(targetEntity=Order.class,mappedBy="c")
    private Set<Order> orders = new HashSet<Order>(); public Customer() { } public Customer(Integer id, String name) {
    super();
    this.id = id;
    this.name = name;
    } public Set<Order> getOrders() {
    return orders;
    }
    public void setOrders(Set<Order> orders) {
    this.orders = orders;
    }
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    } @Override
    public String toString() {
    return "Customer [id=" + id + ", name=" + name + "]";
    } }

    注意:@NamedNativeQuery注解中的resultSetMapping属性需要指定一个名字,它用来指定结果如何进行封装,但@SqlResultSetMapping注解才真正帮我们去规定了执行sql语句如何将结果封装到Customer对象中,而且@EntityResult注解中的fields属性指定了PO类里面的每一个属性跟表中的列是如何对应的。

(转) Hibernate检索方式概述的更多相关文章

  1. Hibernate入门6.Hibernate检索方式

    Hibernate入门6.Hibernate检索方式 20131128 代码下载 链接: http://pan.baidu.com/s/1Ccuup 密码: vqlv Hibernate的整体框架已经 ...

  2. Hibernate 检索方式

    概述 •Hibernate 提供了以下几种检索对象的方式 –导航对象图检索方式:  根据已经加载的对象导航到其他对象 –OID 检索方式:  按照对象的 OID 来检索对象 –HQL 检索方式: 使用 ...

  3. hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)

    hibernate有五种检索方式,这儿用 单向的一对多的映射关系 例子,这儿有后三种的方式: 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 ...

  4. [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. Hibernate检索方式 分类: SSH框架 2015-07-10 22:10 4人阅读 评论(0) 收藏

    我们在项目应用中对数据进行最多的操作就是查询,数据的查询在所有ORM框架中也占有极其重要的地位.那么,如何利用Hibernate查询数据呢?Hibernate为我们提供了多种数据查询的方式,又称为Hi ...

  6. Hibernate 检索方式之 HQL 检索方式

    HQL(Hibernate Query Language) 是面向对象的查询语言,它和 SQL 查询语言有些相似.在 Hibernate 提供的各种检索方式中,HQL 是使用最广的一种检索方式,它有如 ...

  7. Hibernate -- 检索方式 HQL

    Hibernate 提供了以下几种检索对象的方式 导航对象图检索方式:  根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的OID 来检索对象 HQL 检索方式:使用面向对象的HQL查询 ...

  8. Hibernate检索方式(转载)

    我们在项目应用中对数据进行最多的操作就是查询,数据的查询在所有ORM框架中也占有极其重要的地位. 那么,如何利用Hibernate查询数据呢?Hibernate为我们提供了多种数据查询的方式,又称为H ...

  9. 04_Hibernate检索方式

    一.Hibernate检索方式概述 OID检索方式:按照对象的OID来检索对象(get/load) HQL检索方式:使用面向对象的HQL查询语言 QBC检索方式:使用QBC(Query By Crit ...

随机推荐

  1. Servlet监听器(Listener)实例

    以下内容是翻译自http://www.journaldev.com/1945/servletcontextlistener-servlet-listener-example: 说明:web.xml的加 ...

  2. 【转】gcov lcov 覆盖c/c++项目入门

    原文: http://www.cnblogs.com/turtle-fly/archive/2013/01/09/2851474.html ------------------------------ ...

  3. 通用的Adapter

    activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...

  4. HDOJ题目4417 Super Mario(划分树求区间比k小的个数+二分)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  5. LeetCode 249. Group Shifted Strings (群组移位字符串)$

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  6. 构建一个简单的基于MVC模式的JavaWeb

    零晨三点半了,刚刚几个兄弟一起出去吼歌,才回来,这应该是我大学第二次去K歌,第一次是大一吧,之后每次兄弟喊我,我都不想去,因为我还是很害怕去KTV,或许是因为那里是我伤心的地方,也或许是因为我在那里失 ...

  7. IDEA Spark Streaming Flume数据源 --解决无法转化为实际输入数据,及中文乱码(Scala)

    需要三步: 1.shell:往 1234 端口写数据 nc localhost 1234 2.shell: 启动flume服务 cd /usr/local2/flume/bin ./flume-ng ...

  8. java动态代理实例

    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflec ...

  9. 【TODO】Ruby Range类

    创建: 2017/10/28   Range类                                                                             ...

  10. 基于Spark Streaming预测股票走势的例子(二)

    上一篇博客中,已经对股票预测的例子做了简单的讲解,下面对其中的几个关键的技术点再作一些总结. 1.updateStateByKey 由于在1.6版本中有一个替代函数,据说效率比较高,所以作者就顺便研究 ...