Hibernate查询方式
OID查询
它就是根据id查询一个实体
涉及的方法:
get(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。
load(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。
Hibernate的检索策略
类级别检索策略:
get方法:
它永远都是立即加载。返回的对象是实体类类型。
立即加载的含义:不管用不用,都马上发起查询。
load方法:
它默认是延迟加载。返回的是实体类对象的代理对象。
它可以通过配置的方式改为立即加载。配置的位置是映射文件的class标签。
涉及的属性是:lazy。含义就是是否延迟加载。 取值true延迟加载(默认值) false不是延迟加载
延迟加载的含义:什么时候用,什么时候真正发起查询。
测试OID检索方式
package com.pc.hibernate.test.querymethod;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.pc.hibernate.domain.Customer;
import com.pc.hibernate.utils.HibernateUtils;
/**
* Hibernate中的查询方式:
* OID查询:
* 它就是根据id查询一个实体
* 涉及的方法:
* get(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。
* load(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。
*
* Hibernate的检索策略
* 类级别检索策略:
* get方法:
* 它永远都是立即加载。返回的对象是实体类类型。
* 立即加载的含义:不管用不用,都马上发起查询。
* load方法:
* 它默认是延迟加载。返回的是实体类对象的代理对象。
* 它可以通过配置的方式改为立即加载。配置的位置是映射文件的class标签。
* 涉及的属性是:lazy。含义就是是否延迟加载。 取值true延迟加载(默认值) false不是延迟加载
* 延迟加载的含义:什么时候用,什么时候真正发起查询。
* @author Switch
*
*/
public class TestOIDQuery {
/**
* 需求:
* 查询id为1的客户
*/
@Test
public void test1() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 1L);
transaction.commit();
// 输出1和客户信息
System.out.println(customer.getCustId());
System.out.println(customer);
}
/**
* 需求:
* 查询id为1的客户
*/
@Test
public void test2() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.load(Customer.class, 1L);
transaction.commit();
// 输出1和报错could not initialize proxy - no Session
// 当<class name="Customer" table="cst_customer" lazy="false">时
// 该方法正确,因为这时候已经不延迟加载了
System.out.println(customer.getCustId());
System.out.println(customer);
}
}
对象导航查询
对象图导航检索方式是根据己经加载的对象,导航到他的关联对象 。它利用类与类之间的关系来检索对象 。譬如要查找一个联系人对应的客户,就可以由联系人对象自动导航找到联系人所属的客户对象。当然,前提是必须在对象关系映射文件上配置了多对一的关系。
当我们两个实体类有关联关系时(一对多,多对一等等),在获取一个实体时,可以根据对象的方法,获取该实体关联对象的数据。
customer.getLinkMans();获取当前客户下的所有联系人
linkman.getCustomer();获取当前联系人所属客户。
package com.pc.hibernate.test.querymethod;
import java.util.List;
import java.util.Set;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.pc.hibernate.domain.Customer;
import com.pc.hibernate.domain.LinkMan;
import com.pc.hibernate.utils.HibernateUtils;
/**
*
* Hibernate中的查询方式:
* 对象导航查询
* 当我们两个实体类有关联关系时(一对多,多对一等等),在获取一个实体时,可以根据对象的方法,获取该实体关联对象的数据。
* customer.getLinkMans();获取当前客户下的所有联系人
* linkman.getCustomer();获取当前联系人所属客户。
*
* @author Switch
*/
public class TestObjectNavigationQuery {
/**
* 一般情况下我们都会有一个这样的方法:根据id查询一个实体。
* 任何实体都应该有这么个方法
*/
public Customer findById(Long custId){
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
Customer c1 = s.get(Customer.class, custId);
tx.commit();
return c1;
}
/**
* 根据客户id查询联系人信息
* @param custId
* @return
*/
public List<LinkMan> findLinkManByCid(Long custId){
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
SQLQuery query = s.createSQLQuery("select * from cst_linkman where lkm_cust_id = ? ");
query.setLong(0, custId);
query.addEntity(LinkMan.class);
@SuppressWarnings("unchecked")
List<LinkMan> mans = query.list();
tx.commit();
return mans;
}
/**
* 需求:
* 查询id为1的客户下的所有联系人
*/
@Test
public void test1(){
// 传统的使用方式
List<LinkMan> list = findLinkManByCid(1L);
System.out.println(list);
Customer c = findById(1L);
//对象导航查询
// 需要将Customer上对应于LinkMan的关系检索策略的懒加载关闭
Set<LinkMan> linkmans = c.getLinkMans();
for(LinkMan linkMan : linkmans){
System.out.println(linkMan);
}
}
/**
* 需求:
* 查询id为5的联系人所属客户
*/
@Test
public void test2() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 5L);
// 对象导航查询
System.out.println(linkMan.getCustomer());
transaction.commit();
}
}
HQL查询
HQL (Hibernate Query Language ) 是面向对象的查询语言,它和 SQL 查询语言有些相似 ,但它使用的是类、对象和属性的概念 ,而没有表和字段的概念 。在Hibernate提供的各种检索方式中 ,HQL是官方推荐的查询语言,也是使用最广泛的一种检索 方式。
涉及的对象:
Query
如何获取Query:
session.createQuery(String hql);
HQL语句写法:
表名用实体类名称替代
字段名用实体类属性名称(get/set方法后面的部分,并且把首字母转小写)
Hibernate 进行 多表查询与 SQL 其实是很相似的 ,但是 HQL 会在原来 SQL 分类的基础上又多出来一些操作 。
HQL 的多表连接查询的分类如下 :
- 交叉连接
- 内连接
- 显式内连接
- 隐式内连接
- 迫切内连接
- 外连接
- 左外连接
- 迫切左外连接
其实这些连接查询语法大致都是一致的,就是HQL查询的是对象而SQL查询的是表。那么我们来比较一下SQL和HQL的连接查询。
SQL 连接查询
SELECT * FROM cst_customer c INNER JOIN cst_linkman 1 ON c.cust_id = l.lkm_cust_id;
HQL 连接的查询
from Customer c inner join c.linkMans
在HQL中,我们不用写关联宇段了,因为客户中的联系人的集合其实对应的就是外键,所以我们在inner join的后面直接可以写 c.linkMans。
迫切内连接其实就是在内连接的inner join后添加一个fetch关键字。
from Customer c inner join fetch c.linkMans
内连接或是迫切内连接发送的底层SQL都是一样的,而且在生成的SQL语句中也没有fetch关键字,当然fetch本身就不是SQL语句的关键字。所以一定要注意,fetch只能在HQL中使用的,生成了SQL语句以后,fetch就消失了 。
其实HQL内连接查询的和SQL的内连接查询到的结果集是一样的 ,都是两个表的交集部分的数据。
然后在封装数据的时候,普通内连接会将属于客户的数据封装到Customer对象中,会将属于联系人的数据封装到LinkMan对象中,所以每条记录都会是装有两个对象的集合,所以封装以后的数据是 List<Object[ ]>,在Object[ ]中有两个对象一个是 Customer另一个是 LinkMan 。
那么加了fetch以后,虽然查询到的数据是一样的,但是Hibernate发现HQL中有fetch就会将数据封装到一个对象中,把属于客户的数据封装到Customer对象中,将属于联系人的部分封装到Customer中的联系人的集合中,这样最后封装完成以后是一个 List<Customer> 中。
测试HQL方式
package com.pc.hibernate.test.querymethod;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.pc.hibernate.domain.Customer;
import com.pc.hibernate.domain.LinkMan;
import com.pc.hibernate.utils.HibernateUtils;
/**
* Hibernate中的查询方式:
* HQL查询:
* 它是使用HQL语句进行查询的。 HQL:Hiberante Query Language
* 涉及的对象:
* Query
* 如何获取Query:
* session.createQuery(String hql);
* HQL语句写法:
* 表名用实体类名称替代
* 字段名用实体类属性名称(get/set方法后面的部分,并且把首字母转小写)
*
* @author Switch
*/
public class TestHQLQuery {
/**
* 查询所有
* 需求:查询所有客户
*/
@Test
public void test1() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 查询所有客户
Query query = session.createQuery("from Customer");
@SuppressWarnings("unchecked")
List<Customer> customers = query.list();
transaction.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 条件查询:
* 需求:
* 查询客户级别是23的,客户名称带有 集 字的
* 给HQL语句加条件用where
* HQL语句的参数占位符也可以使用?
* hibernate中,参数占位符是从0开始的。
*/
@Test
public void test2(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 查询客户级别是23的,客户名称带有 集 字的
Query query = session.createQuery("from Customer where custLevel = ? and custName like ?");
query.setString(0, "23");
query.setString(1, "%集%");
@SuppressWarnings("unchecked")
List<Customer> customers = query.list();
transaction.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 具名查询:
* 给参数占位符提供一个具体的名称
* HQL语句中的写法:
* 需要使用 :参数名称
* 例如: :custLevel :custName
* 参数站位符赋值的写法:
* 需要注意:此处不能写冒号,直接写冒号后面的部分
*/
@Test
public void test3(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 查询客户级别是23的,客户名称带有 集 字的
// 给参数占位符提供一个具体的名称
Query query = session.createQuery("from Customer where custLevel = :custLevel and custName like :custName");
query.setString("custLevel", "23");
query.setString("custName", "%集%");
@SuppressWarnings("unchecked")
List<Customer> customers = query.list();
transaction.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 排序查询:
* 使用HQL语句,给查询结果排序
*
* HQL语句中的排序:
* order by
* asc:升序(默认值)
* desc:降序
*/
@Test
public void test4(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 按联系人ID降序排序联系人
Query query = session.createQuery("from LinkMan order by lkmId desc");
@SuppressWarnings("unchecked")
List<LinkMan> linkMans = query.list();
transaction.commit();
for (LinkMan linkMan : linkMans) {
System.out.println(linkMan);
}
}
/**
* 分页查询
* MySQL中分页关键字:
* Limit
* limit的两个参数: 第一个参数:查询的开始记录索引。(它是从0开始的)
* 第二个参数:每次查询多少条记录。(它是固定的)
* Hibernate中涉及的方法
* setFirstResult(int firstResult):查询的开始记录索引
* setMaxResults(int maxResults):每次查询多少条记录
*/
@Test
public void test5(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//1.获取Query对象
Query query = session.createQuery("from LinkMan");
//2.使用Hibernate提供的方法来设置分页条件
Integer firstResult = 0;
Integer maxResults = 2;
query.setFirstResult(firstResult);
query.setMaxResults(maxResults);
//3.执行query对象的方法
@SuppressWarnings("unchecked")
List<LinkMan> list = query.list();
transaction.commit();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
}
/**
* 统计查询
* 其实就是在HQL语句中使用聚合函数
* count() sum() avg() max() min()
* 使用聚合函数查询时,如果没有group by,返回的结果集是一行一列的
*
* 聚合函数都不会计算为null的字段。
*
* count(*)和count(主键)是一样的。
*/
@Test
public void test6(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 查询一共有多少个联系人
Query query = session.createQuery("select count(lkmId) from LinkMan");
Long count = (Long) query.uniqueResult();
transaction.commit();
System.out.println(count);
}
/**
* 投影查询:
* 当我们查询实体对象时,并不需要所有字段信息,只查询部分,但是还想让他成为一个实体对象。其实就是用部分字段来投影出整个实体对象。
* 使用要求:
* HQL语句:
* 写法必须是 new 实体类名称(查询的字段)
* select new Customer(custId,custName) from Customer
* 注意:如果你的实体类在工程中唯一,则可以直接写类名。如果实体类在工程中不唯一,需要写全限定类名。
* 实体类要求:
* 必须在实体类中提供一个相同参数列表的构造函数。
*
*/
@Test
public void test71(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 只获取客户的ID和名字,并封装成客户对象
Query query = session.createQuery("select new Customer(custId, custName) from Customer");
@SuppressWarnings("unchecked")
List<Customer> customers = query.list();
transaction.commit();
for (Customer customer : customers) {
System.out.println(customer.getCustId() + " " + customer.getCustName());
}
}
@Test
public void test72(){
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
//1.获取Query对象
Query query = s.createQuery("select custId,custName from Customer ");
//2.执行query对象的方法
@SuppressWarnings("unchecked")
List<Object[]> list = query.list();
tx.commit();
for(Object[] os : list){
System.out.println("----------每个数组中的内容------------");
for(Object o : os){
System.out.println(o);
}
}
}
/**
* 左外连接查询和迫切左外连接查询的区别
* 区别:
* 返回的结果集不一样。在实际开发中用的不多,此处讲解就是为了说明他们之间的区别
* 注意:
* Hibernate中没有右外连接
*
* Hibernate左外连接返回的数据:
* 返回的是一个有Object数组组成的List集合,该数组中有两个对象。一个是主表实体,一个是从表实体。
* 主表实体有可能重复
*/
//左外连接查询
@Test
public void test81(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//1.获取Query对象
//sql语句的左外:select * from cst_customer c left outer join cst_linkman l on c.cust_id = l.lkm_cust_id;
Query query = session.createQuery("from Customer c left join c.linkMans");
//2.执行query对象的方法
@SuppressWarnings("unchecked")
List<Object[]> list = query.list();
transaction.commit();
for (Object[] objects : list) {
System.out.println("------一组对象-------");
for (Object object : objects) {
System.out.println(object);
}
}
}
/**
* 迫切左外连接查询:
* 要想使用迫切,需要在查询HQL语句中加入一个关键字:fetch
* Hibernate迫切左外连接返回的数据:
* 返回的是左表实体对象的List集合,并且左表中对应右表的字段已经被填充
*/
@Test
public void test82(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//1.获取Query对象
Query query = session.createQuery("from Customer c left join fetch c.linkMans");
//2.执行query对象的方法
@SuppressWarnings("unchecked")
List<Customer> customers = query.list();
transaction.commit();
for (Customer customer : customers) {
System.out.println("------一组对象-------");
System.out.println(customer);
for (LinkMan linkMan : customer.getLinkMans()) {
System.out.println(linkMan);
}
System.out.println("");
}
}
/**
* 使用HQL进行更新操作
*/
@Test
public void test9(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//1.获取Query对象
Query query = session.createQuery("update Customer set custName = ? where custId = ?");
query.setString(0, "XX公司");
query.setString(1, "1");
//2.执行query对象的方法
int result = query.executeUpdate();
transaction.commit();
System.out.println(result);
}
}
QBC查询
QBC(Query By Criteria)是Hibernate提供的另一种检索对象的方式,它主要由Criteria 接口、Criterion接口和Expression类组成 。Criteria接口是Hibernate API中的一个查询接口,它需要由session进行创建。Criterion是Criteria的查询条件,在Criteria中提供了add(Criterion criterion)方法来添加查询条件。
涉及的对象:
Criteria
DetachedCriteria
获取的方式:
session.createCriteria(Class clazz);参数指的是要查询的字节码
添加条件的方法:
Criteria的add方法
添加条件涉及的对象:
Restrictions
Restrictions类提供的方法
方法名 | 说明 |
Restrictions.eq | 等于 |
Restrictions. allEq | 使用 Map ,使用key/value进行多个等于的比较 |
Restrictions.gt | 大于> |
Restrictions.ge | 大于等于>= |
Restrictions.lt | 小于 |
Restrictions.le | 小于等于<= |
Restrictions.between | 对应 SQL 的 between 子句 |
Restrictions.like | 对应 SQL 的 like 子句 |
Restrictions.in | 对应 SQL 的 IN 子句 |
Restrictions.and | and 关系 |
Restrictions.or | or 关系 |
Restrictions.sqlRestriction | SQL 限定查询 |
离线条件检索
DetachedCriteria 翻译为离线条件查询,因为它是可以脱离Session来使用的一种条件查询对象,我们都知道Criteria对象必须由Session对象来创建。那么也就是说必须先有Session才可以生成Criteria对象。而DetachedCriteria对象可以在其他层对条件进行封装。
这个对象也是比较有用的,尤其在SSH整合以后这个对象经常会使用 。它的主要优点是做一些特别复杂的条件查询的时候,往往会在WEB层向业务层传递很多的参数,业务层又会将这些参数传递给DAO层。最后在DAO中拼接SQL完成查询。有了离线条件查询对象后,那么这些工作都可以不用关心了,我们可以在WEB层将数据封装好,传递到业务层,再由业务层传递给DAO完成查询。
测试QBC检索方式
package com.pc.hibernate.test.querymethod;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
import com.pc.hibernate.domain.Customer;
import com.pc.hibernate.domain.LinkMan;
import com.pc.hibernate.utils.HibernateUtils;
/**
* Hibernate中的查询方式:
* QBC查询:
* Query By Criteria 它是一种更加面向对象的查询方式。
* 它把查询条件都用方法封装了。里面的参数全都需要使用实体类的属性名称。
* 涉及的对象:
* Criteria
* DetachedCriteria
* 获取的方式:
* session.createCriteria(Class clazz);参数指的是要查询的字节码
* 添加条件的方法:
* Criteria的add方法。
* 添加条件涉及的对象:
* Restrictions
*
* @author Switch
*/
public class TestQBCQuery {
/**
* 基本查询:查询所有
*
* 需求:
* 查询所有客户
*/
@Test
public void test1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List<Customer> customers = criteria.list();
tx.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 条件查询
* 需求:查询客户级别是23的,客户名称带有集字的
*/
@Test
public void test2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
// 添加条件
criteria.add(Restrictions.eq("custLevel", "23"));
criteria.add(Restrictions.like("custName", "%集%"));
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List<Customer> customers = criteria.list();
tx.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 分页查询
*
* 涉及的方法:
* setFirstResult(int firstResult);
* setMaxResults(int maxResults);
* 含义和HQL是一模一样的
*/
@Test
public void test3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResults(2);
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List<Customer> customers = criteria.list();
tx.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 统计查询:
* 使用QBC来添加聚合函数
*
* count() avg() min() max() sum()
*
* 涉及的方法:
* setProjections(Projection p ); 它可以加查询语句的结构。
* 涉及的类:
* Projections
* 该类中提供了一些静态方法
*/
@Test
public void test4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
criteria.setProjection(Projections.count("custId"));
//2.执行uniqueResult方法,得到结果
Long result = (Long) criteria.uniqueResult();
tx.commit();
System.out.println(result);
}
/**
* 排序查询
*
* 涉及方法:
* Criteria的addOrder方法。该方法需要一个Order对象作为参数
* Order对象有两个方法:
* desc(String propertyName):按照指定的属性名称,倒序排序。
* asc(String propertyName):按照自顶的属性名称,正序排序。
*/
@Test
public void test5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.addOrder(Order.desc("lkmId"));
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List<LinkMan> linkMans = criteria.list();
tx.commit();
for (LinkMan linkMan : linkMans) {
System.out.println(linkMan);
}
}
/**
* 离线查询:
* 在线对象:
* Criteria对象。它的获取必须要一个可用的Session来创建。如果Session不能用,则不能创建Criteria。
* 我们使用Criteria进行的查询就是在线查询。
* 离线对象:
* 创建DetachedCriteria不需要一个可用的Session。
* 用DetachedCriteria进行的查询就叫做离线查询
* 涉及的对象
* DetachedCriteria
* 如何获取
* DetachedCriteria.forClass(Class clazz);参数的含义:要查询的实体类
* 如何设置查询条件:
* 和Criteria是一样的
*
* 在实际开发中:多条件查询用此种方式
*/
//Servlet的方法
@Test
public void doGet(){
//1.获取请求参数
String custLevel = "23";
String custName = "集";
//2.查询所有客户
DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);
dCriteria.add(Restrictions.eq("custLevel", custLevel));
dCriteria.add(Restrictions.like("custName", "%"+custName+"%"));
List<Customer> cs = servicefindAllCustomer(dCriteria);
for(Customer c : cs){
//3.存入请求域中
//4.转向列表页面
System.out.println(c);
}
}
//Service的方法
public List<Customer> servicefindAllCustomer(DetachedCriteria dCriteria){
return daofindAllCustomer(dCriteria);
}
//Dao中的方法
public List<Customer> daofindAllCustomer(DetachedCriteria dCriteria){
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
//1.把离线对象激活
Criteria c = dCriteria.getExecutableCriteria(s);
//3.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List<Customer> list = c.list();
tx.commit();
return list;
}
}
原生SQL查询
采用HQL或QBC检索方式时,Hibernate生成标准的SQL查询语句,适用于所有的数据库平台,因此这两种检索方式都是跨平台的。但有的应用程序可能需要根据底层数据库的SQL方言,来生成一些特殊的查询语句。在这种情况下,可以利用Hibemate提供的原生SQL检索方式 。
原生SQL查询时通过SQLQuery sqlQuery = session.createSQLQuery(String sql)来实现的,因为操作方式就是SQL语句,故不再介绍。
/**
* SQLQuery 它使用的是原始的SQL语句查询
*/
@Test
public void test3() {
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
// 1.获取SQLQuery对象
SQLQuery sqlquery = s.createSQLQuery("select * from cst_customer");// 参数是SQL语句
// 2.执行sqlquery的方法,返回结果集
/*
* List<Object[]> list = sqlquery.list(); for(Object[] os : list){
* System.out.println(
* "-------------每出现一行分割线,表示外层循环执行了一次-------------------"); <br/>
* for(Object o : os){ System.out.println(o); } }
*/
// 添加实体类字节码,把查询结果转成实体类对象
sqlquery.addEntity(Customer.class);
List<Customer> cs = sqlquery.list();
for (Customer c : cs) {
System.out.println(c);
}
tx.commit();
}
该博文使用的Hibernate配置文件和映射文件
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
1、导入dtd约束
在Hibernate的核心jar包中:hibernate-mapping-3.0.dtd
2、编写配置文件
实体类和数据库表的对应关系
实体类中属性和表的字段的对应关系
-->
<hibernate-mapping package="com.pc.hibernate.domain">
<!-- class标签:
作用:用于配置实体类和表之间的对应关系
属性:
name:实体类的名称。它应该写全限定类名
table:数据库表的名称
-->
<class name="Customer" table="cst_customer" lazy="true" batch-size="3">
<!-- id标签:
作用:映射主键
属性:
name:实体类的属性名称
column:数据库表的字段名称
type:主键的类型
-->
<id name="custId" column="cust_id" type="java.lang.Long">
<!-- generator标签:
作用:主键的生成方式
属性:
class:指定方式
取值:native
含义:使用本地数据库的自动增长能力。
-->
<generator class="native"/>
</id>
<!-- property标签:
作用:映射其他字段
属性:
name:实体类的属性名称
column:数据库表的字段名称
type:字段的类型
length:数据库中对应列的长度
-->
<property name="custName" column="cust_name" type="java.lang.String" length="32"/>
<property name="custSource" column="cust_source" type="java.lang.String" length="32"/>
<property name="custIndustry" column="cust_industry" type="java.lang.String" length="32"/>
<property name="custLevel" column="cust_level" type="java.lang.String" length="32"/>
<property name="custAddress" column="cust_address" type="java.lang.String" length="128"/>
<property name="custPhone" column="cust_phone" type="java.lang.String" length="64"/>
<!-- 配置一对多 -->
<set name="linkMans" inverse="false" cascade="save-update" batch-size="4" lazy="true" fetch="select">
<key column="lkm_cust_id" />
<one-to-many class="LinkMan"/>
</set>
</class>
</hibernate-mapping>
LinkMan.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pc.hibernate.domain">
<class name="LinkMan" table="cst_linkman">
<id name="lkmId" column="lkm_id" type="java.lang.Long">
<generator class="native" />
</id>
<property name="lkmName" column="lkm_name" type="java.lang.String" length="16"/>
<property name="lkmGender" column="lkm_gender" type="java.lang.String" length="10"/>
<property name="lkmPhone" column="lkm_phone" type="java.lang.String" length="16"/>
<property name="lkmMobile" column="lkm_mobile" type="java.lang.String" length="16"/>
<property name="lkmEmail" column="lkm_email" type="java.lang.String" length="64"/>
<property name="lkmPosition" column="lkm_position" type="java.lang.String" length="16"/>
<property name="lkmMemo" column="lkm_memo" type="java.lang.String" length="512"/>
<!-- 配置多对一 -->
<many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="save-update" lazy="proxy" fetch="select"/>
</class>
</hibernate-mapping>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- 1、导入dtd约束 在hibernate核心jar包中:hibernate-configuration-3.0.dtd 2、编写配置文件 -->
<hibernate-configuration>
<!-- 配置SessionFactory -->
<!-- 创建SessionFactory需要3部分信息。 而配置文件中要写哪些配置,我们可以翻阅资料。 -->
<!-- 第一部分:连接数据库的基本信息,第二部分:hibernate的基本配置,第三部分:映射文件的位置 -->
<session-factory>
<!-- 1、连接数据库的基本信息 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mycrm</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<!-- 数据库的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 2、hibernate的基本配置 -->
<!-- 是否显示SQL语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 是否格式化显示SQL语句 -->
<!-- <property name="hibernate.format_sql">true</property> -->
<!-- 采用何种策略来创建表结构: -->
<!-- update:检查表结构和实体类映射文件的变化,如果发现映射文件和表结构不一致,更新表结构。 -->
<!-- 注意:hibernate不能创建数据库,只能在有数据库的情况下创建表结构。 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置hibernate使用连接池:告知Hibernate使用连接池的厂商 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 配置把Session绑定到当前线程上,从而保证一个线程只有一个Session -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 3、映射文件的位置 -->
<mapping resource="com/pc/hibernate/domain/Customer.hbm.xml" />
<mapping resource="com/pc/hibernate/domain/LinkMan.hbm.xml" />
</session-factory>
</hibernate-configuration>