( 转)Hibernate常用API
http://blog.csdn.net/yerenyuan_pku/article/details/65103203
可在度娘上摘抄如下文字:
Hibernate的核心类和接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。这6个核心类和接口在任何开发中都会用到。
还记得上一篇文章讲的是《Hibernate的配置详解》,本文继续在其基础之上讲解Hibernate常用的API。
Configuration
Configuration类主要是用于加载Hibernate的核心配置文件。
为了和之前写的单元测试类——HibernateTest1.java相区分,我们这儿在cn.itheima.test包下再创建一个单元测试类——HibernateTest2.java。像之前写的这样的代码:
public class HibernateTest2 {
@Test
public void test1() {
// 创建Configuration来加载配置文件
Configuration config = new Configuration().configure();
.......
}
}
主要是加载src目录下的hibernate.cfg.xml配置文件。
如果现在有人标新立异,他不是将Hibernate的核心配置文件命名为hibernate.cfg.xml,而是将其命名为比如说是my.xml,假设该文件同样是位于src目录下。那么应该像这样加载该文件:
public class HibernateTest2 {
@Test
public void test1() {
// 创建Configuration来加载配置文件
Configuration config = new Configuration().configure("my.xml"); // 加载指定名称的配置文件
.......
}
}
可归纳为:
Configuration config=new Configuration().config(核心配置文件名称); // 加载指定名称的配置文件
但我们又何必这么写昵?你说是不是?
由于我们将实体类(Customer.java)的映射配置文件配置在Hibernate的核心配置文件中:
<hibernate-configuration>
<session-factory>
......
<!-- 配置hibernate的映射文件所在的位置 -->
<mapping resource="cn/itheima/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
所以在编写程序代码的时候,勿须手动加载映射配置文件——Customer.hbm.xml。映射配置文件一般情况下是放置在实体类所在包下的,但是不这样做也是可以的,因为可以指定路径。所以即使在Hibernate的核心配置文件中没有映射文件的配置,也是可以手动加载映射配置文件的。
public class HibernateTest2 {
// 测试手动加载映射配置文件
@Test
public void test1() {
// 1.创建Configuration来加载配置文件
Configuration config = new Configuration().configure();
// 手动加载映射
config.addResource("cn/itheima/domain/Customer.hbm.xml"); // 直接加载映射配置文件
// 2.得到SessionFactory
SessionFactory sessionFactory = config.buildSessionFactory();
// 3.得到Session
Session session = sessionFactory.openSession();
// 开启事务
session.beginTransaction();
Customer c = session.get(Customer.class, 1);
System.out.println(c);
// 事务提交
session.getTransaction().commit();
// 关闭Session
session.close();
// 关闭SessionFactory
sessionFactory.close();
}
}
当然了,我们还可以这样做:
public class HibernateTest2 {
// 测试手动加载映射配置文件
@Test
public void test1() {
// 1.创建Configuration来加载配置文件
Configuration config = new Configuration().configure();
// 手动加载映射
config.addClass(Customer.class); // 这种方式它会直接在实体类所在包下查找规范的映射配置文件
// 2.得到SessionFactory
SessionFactory sessionFactory = config.buildSessionFactory();
// 3.得到Session
Session session = sessionFactory.openSession();
// 开启事务
session.beginTransaction();
Customer c = session.get(Customer.class, 1);
System.out.println(c);
// 事务提交
session.getTransaction().commit();
// 关闭Session
session.close();
// 关闭SessionFactory
sessionFactory.close();
}
}
只是这种情况下,Customer.hbm.xml映射配置文件须放置在实体类所在包下。
我们之前也说过对于Hibernate的核心配置文件它有两种方式:
- hibernate.cfg.xml
- hibernate.properties
假如Hibernate的核心配置文件采用的是hibernate.properties这种方式,那么如何加载该配置文件昵?
public class HibernateTest2 {
@Test
public void test1() {
Configuration config = new Configuration();
.......
}
}
结论:
Configuration config=new Configuration(); // 主要加载的是src目录下的hibernate.properties配置文件
那么问题来了,我们是在hibernate.cfg.xml文件中有(映射)了xxx.hbm.xml文件的位置。但如果我们使用的是hibernate.properties这种核心配置文件,那么它又如何加载映射配置文件昵?不用我说,大家应该都知道了。
SessionFactory
首先SessionFactory它的获取是通过Configuration得到:
// 1.创建Configuration来加载配置文件
Configuration config = new Configuration().configure();
// 2.得到SessionFactory
SessionFactory sessionFactory = config.buildSessionFactory();
可在度娘上摘抄如下有关SessionFactory的文字:
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
下面我们来着重分析以上这段话,我是从这几句话入手的。
它充当数据存储源的代理,并负责创建Session对象。
我们通过查看Hibernate的帮助文档,可发现通过SessionFactory可以得到Session有两种方式:
- 通过SessionFactory获得Session方式一:
注意:这是从连接池中获取一个连接。 - 通过SessionFactory获得Session方式二:
注意:这是获取一个与线程绑定的Session(即线程安全的Session)。
需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够
我的理解——SessionFactory它不是轻量级的,所以不要频繁创建关闭它。在一个项目中有一个SessionFactory就可以了,通过SessionFactory来获取Session进行操作。那么问题来了,怎样可以保证在一个项目中所使用的SessionFactory是同一个哪?
可在cn.itheima.utils包下创建一个工具类——HibernateUtils.java,其代码为:
public class HibernateUtils {
private static Configuration config;
private static SessionFactory sessionFactory;
static {
config = new Configuration().configure();
sessionFactory = config.buildSessionFactory();
}
public static Session openSession() {
return sessionFactory.openSession();
}
}
好了,来测试HibernateUtils工具类的使用吧!
public class HibernateTest2 {
// 测试HibernateUtils工具使用
@Test
public void test2() {
// 得到Session
Session session = HibernateUtils.openSession();
// 开启事务
session.beginTransaction();
Customer c = session.get(Customer.class, 1);
System.out.println(c);
// 事务提交
session.getTransaction().commit();
// 关闭Session
session.close();
// 注意:SessionFactory不要关闭,它开启就别关了,除非说你的项目结束了,否则,我们就不关闭它
}
}
SessionFactory内部还维护了一个连接池,如果我们要想使用c3p0连接池,应该怎样做昵?也即在Hibernate中如何使用c3p0连接池?
- 我们要导入c3p0的相关jar包。
在lib/options下有关于c3p0连接池所需jar包,如下: 在hibernate.cfg.xml文件中配置c3p0连接池。
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> <!-- C3P0连接池的配置 -->
<property name="hibernate.c3p0.max_size">20</property> <!-- 最大连接数 -->
<property name="hibernate.c3p0.min_size">5</property> <!-- 最小连接数 -->
<property name="hibernate.c3p0.timeout">120</property> <!-- 超时时间 -->
<property name="hibernate.c3p0.idle_test_period">3000</property> <!-- 空闲连接(等待)时间,以秒为单位 -->注意:有些童鞋可能忘记了这样的配置:
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
这当然是不可取的,以上配置是在设置连接池提供者,如没设置,默认为org.hibernate.connection.DriverManagerConnectionProvider,它会帮助我们从Hibernate本身维护的连接池里面获取连接。但是现在我们要用C3P0连接池,所以这样的设置是必不可少的,这样的话,Hibernate才知道你现在要用的是C3P0连接池!
当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
我觉得这是要涉及分布式数据库的节奏,对此我也是小白。只是知道怎么配置而已,大概类似于一下配置吧!
<hibernate-configuration>
<session-factory>
......
</session-factory>
<session-factory name="xxx">
......
</session-factory>
</hibernate-configuration>
Session
从度娘摘抄如下:
Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。
那么问题来了,我们如何解决session的安全问题?我们只需要在方法内部来使用Session就可以。
那么问题又来了,Session如何获取到昵?在讲SessionFactory接口时,我们就介绍了通过SessionFactory获得Session的两种方式,虽然这两种方式都可以获取到一个Session对象,那么这两种方式有什么区别呢?
SessionFactory.openSession();
:相当于直接通过SessionFactory创建一个新的Session,使用完成后要手动调用close()方法来关闭。SessionFactory.getCurrentSession();
:获取一个与线程绑定的Session,当我们提交事务或事务回滚后会自动关闭。
Session的常用方法
save()
:保存对象update ()
:修改操作delete()
:删除get()/load()
:根据id进行查询avenOrUpdate()
:执行save或update操作createQuery()
:获取一个Query对象CreateSQLQUery()
:获取一个可以操作SQL的SQLQuery对象createCriteria()
:取一个Criteria对象,它可以完成条件查询
以上的许多方法,我们都已接触过,不过后面随着我们学习的精进,还会对他们越来越熟悉。
Transaction
Transaction接口主要用于管理事务,它是Hibernate的事务接口,对底层的事务进行了封装。使用它可以进行事务操作。例如:
- 事务提交:commit()
- 事务回滚:rollback()
问题一:如何获取一个Transaction对象昵?可通过如下代码获得:
Transaction transaction = session.beginTransaction();
问题二:如果在程序中没有开启事务,是否存在事务?存在事务,默认session的每一个操作就会开启一个事务。并且默认情况下事务是不会自动提交的。相当于在Hibernate的核心配置文件中又如下配置:
<!-- 用于设置事务提交方式,默认是不自动提交的 -->
<property name="hibernate.connection.autocommit">false</property>
如果我们将其修改为:
<property name="hibernate.connection.autocommit">true</property>
则此时事务就会自动提交。
Query
从度娘上可摘抄到这样的文字:
Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作。
我们主要通过Query完成查询操作。通过Query即可以执行hql语句,如下:
Query query = session.createQuery("hql语句");
又可以执行本地sql语句:
SQLQuery sqlQuery = session.createSQLQuery("本地sql语句");
注意:SQLQuery是Query的子类。
查询所有操作——使用HQL
为了和之前写的单元测试类——HibernateTest1.java和HibernateTest2.java相区分,我们这儿在cn.itheima.test包下准备再创建一个单元测试类——HibernateTest3.java。
使用HQL语句完成查询所有客户的操作,代码如下:
public class HibernateTest3 {
// 使用hql完成查询所有操作
@Test
public void test1() {
Session session = HibernateUtils.openSession();
Query query = session.createQuery("from Customer"); // from后面是类名
List<Customer> list = query.list();
System.out.println(list);
session.close();
}
}
注意:from后面是类名。
分页查询
在执行分页查询时,我们试着向t_customer表中插入100条记录。代码如下:
public class HibernateTest3 {
// 向表中插入100条记录
@Test
public void test2() {
Session session = HibernateUtils.openSession();
// 不要忘记开事务
session.beginTransaction();
for (int i = 0; i < 100; i++) {
Customer c = new Customer();
c.setName("姓名" + i);
c.setSex("男");
c.setAddress("北京");
session.save(c);
}
session.getTransaction().commit();
session.close();
}
}
接下来,就来分页查询,要求:一页显示10条,但我们要得到第二页的数据。
public class HibernateTest3 {
// 分页查询
// 一页显示10条,要得到第二页数据
@Test
public void test3() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 一页显示10条,要得到第二页数据
Query query = session.createQuery("from Customer");
query.setFirstResult(10); // 从第几条开始,即开始位置,从0开始计数
query.setMaxResults(10); // 本次查询结果回显的条数
List<Customer> list = query.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
查询指定列信息
如果想如下这样子查询指定列的信息:
public class HibernateTest3 {
// 查询指定列信息
@Test
public void test4() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
Query query = session.createQuery("select name,address from Customer"); // 这时我们得到的不再是Customer对象,而是Object[]
List<Object[]> list = query.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
可以发现select name,address from Customer
得到的是List<Object[]>
结果,我们可不可以得到List<Customer>
这样的结果昵?我们要想得到这个结果,可以使用Hibernate中的投影查询。我们只须在Customer类中提供name与address作为参数的构造方法就可以了,注意无参数构造也要有。而且HQL语句要写成select new Customer(name,address) from Customer
。
public class HibernateTest3 {
// 查询指定列信息
@Test
public void test4() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
Query query = session.createQuery("select new Customer(name,address) from Customer");
List<Customer> list = query.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
条件查询
条件查询,可以使用where关键字。
例,需求:查询name=姓名0的客户。
首先通过无名称参数来完成这个需求。
public class HibernateTest3 {
// 条件查询,可以使用where关键字
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 查询name=姓名0的信息
Query query = session.createQuery("from Customer where name=?"); // 这是一种无名称参数
// 要对参数进行赋值
query.setParameter(0, "姓名0");
List<Customer> list = query.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
虽然我们可以查询出来,但我们有没有想过name=姓名0的客户即使查出来也只有一个,我们有必要把它放在List集合中嘛?如果查询结果可以保证就是唯一 的,我们可以使用query. uniqueResult()
来得到一个单独对象。
public class HibernateTest3 {
// 条件查询,可以使用where关键字
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 查询name=姓名0的信息
Query query = session.createQuery("from Customer where name=?"); // 这是一种无名称参数
// 要对参数进行赋值
query.setParameter(0, "姓名0");
// 如果能保证结果就是唯一的,那么可以使用另外一种方法
Customer customer = (Customer) query.uniqueResult();
System.out.println(customer);
session.getTransaction().commit();
session.close();
}
}
然后再通过有名称参数来完成这个需求。
public class HibernateTest3 {
// 条件查询,可以使用where关键字
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 查询name=姓名0的信息
Query query = session.createQuery("from Customer where name=:myname"); // 这是一种有名称参数
// 对有名称参数进行赋值
query.setParameter("myname", "姓名0");
// 如果能保证结果就是唯一的,那么可以使用另外一种方法
Customer customer = (Customer) query.uniqueResult();
System.out.println(customer);
session.getTransaction().commit();
session.close();
}
}
执行本地SQL
要想执行本地sql,可以这样子做:
SQLQuery sqlQuery=session.createSqlQuery(String sql);
需求一:执行本地sql,查询全部客户。
我想初次写代码完成这个需求,许多人都会这么写吧!
public class HibernateTest3 {
// 执行本地sql,查询全部
@Test
public void test6() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 执行 select * from t_customer;
SQLQuery sqlQuery = session.createSQLQuery("select * from t_customer");
List<Object[]> list = sqlQuery.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
可以发现select * from t_customer
得到的是List<Object[]>
结果,我们可不可以得到List<Customer>
这样的结果昵?可以,代码如下:
public class HibernateTest3 {
// 执行本地sql,查询全部
@Test
public void test6() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 执行 select * from t_customer;
SQLQuery sqlQuery = session.createSQLQuery("select * from t_customer");
// 想要将结果封装到Customer对象中
sqlQuery.addEntity(Customer.class);
List<Customer> list = sqlQuery.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
需求二:执行本地sql,条件查询。例如查询name=姓名1的客户。
public class HibernateTest3 {
// 执行本地sql,条件查询
@Test
public void test7() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 执行 select * from t_customer where name=?;
SQLQuery sqlQuery = session.createSQLQuery("select * from t_customer where name=?");
// 对参数进行赋值
sqlQuery.setParameter(0, "姓名1");
// 想要将结果封装到Customer对象中
sqlQuery.addEntity(Customer.class);
/*
List<Customer> list = sqlQuery.list();
System.out.println(list);
*/
Customer customer = (Customer) sqlQuery.uniqueResult();
System.out.println(customer);
session.getTransaction().commit();
session.close();
}
}
Criteria
根据度娘所得:
Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询。值得注意的是Criteria接口也是轻量级的,它不能在Session之外使用。
首先我要想使用Criteria,必须得到Criteria。可这么做:
Criteria criteria = session.createCriteria(Xxx.class);
需求一:查询所有客户。
public class HibernateTest3 {
// 测试Criteria
@Test
public void test8() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 得到Criteria
Criteria criteria = session.createCriteria(Customer.class);
// 查询所有
List<Customer> list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
需求二:分页查询。
分页查询操作与query的方法一样。通者自通。
需求三:多条件查询。例如查询name=”姓名1”并且address=”上海”的客户。
public class HibernateTest3 {
// 测试Criteria
@Test
public void test8() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 得到Criteria
Criteria criteria = session.createCriteria(Customer.class);
// 多条件查询
// 1.查询name='姓名1'
criteria.add(Restrictions.eq("name", "姓名1")); // where name="姓名1";
// 2.查询address='上海'
criteria.add(Restrictions.eq("address", "上海")); // where name="姓名1" and address="上海"
Customer customer = (Customer) criteria.uniqueResult();
session.getTransaction().commit();
session.close();
}
}
需求四:多条件查询。例如查询name=’姓名1’或者address=’上海’的客户。
public class HibernateTest3 {
// 测试Criteria
@Test
public void test8() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 得到Criteria
Criteria criteria = session.createCriteria(Customer.class);
// 多条件查询
// 查询name='姓名1'或者address='上海'
criteria.add(Restrictions.or(Restrictions.eq("name", "姓名1"),Restrictions.eq("address", "上海")));
List<Customer> list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
总结:我们使用Criteria可以更加面向对象地去操作,它非常适合进行多条件组合查询。但感觉没什么鸟用!
( 转)Hibernate常用API的更多相关文章
- java:Hibernate框架1(环境搭建,Hibernate.cfg.xml中属性含义,Hibernate常用API对象,HibernteUitl,对象生命周期图,数据对象的三种状态,增删查改)
1.环境搭建: 三个准备+7个步骤 准备1:新建项目并添加hibernate依赖的jar文件 准备2:在classpath下(src目录下)新建hibernate的配置文件:hibernate.cf ...
- Hibernate常用api以及增删改查
一 .API的定义 所谓的API全称就是(Application Programming Interface,应用程序编程接口).就是类库对外提供的接口.类.枚举.注解等元素. 如:JDK API ...
- Hibernate常用API以及使用说明
1===>Hibernate常用的aip有Configuration,SessionFactory,Transaction,Session Configuration主要用于加载配置文件,使用 ...
- Java程序员从笨鸟到菜鸟之(五十二)细谈Hibernate(三)Hibernate常用API详解及源码分析--csdn 曹胜欢
新接触一个框架的目的就是想利用这个框架来为我们做一些工作,或者是让他来简化我们的工作,利用这个框架无非就是要利用这个框架所给我们提供的API去操作我们的数据,所以利用一个框架的好坏很大一部分取决于你对 ...
- hibernate常用API详解
根据个人使用Hibernate的经验,介绍一下Hibernate的多种不同的查询和CUD操作,这些东西在日常开发中非常常用,希望对大家有所帮助. 以下示例均以两张表为例:member和userinfo ...
- 简单了解Hibernate核心API
一.SessionFactory 1.它代表的是数据库的连接,其实就是在hibernate.cfg.xml文件中的配置信息 2.可以预定义SQL语句 3.SessionFactory是线程安全的,它维 ...
- Hibernate常用接口
Hibernate的接口类型 在了解了Hibernate的基本配置,映射文件后,道路已经铺平了.我们继续往前走.接下来,我们应该做的是了解Hibernate常用的接口,对Hibernate的工作方式进 ...
- JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API
森林森 一份耕耘,一份收获 博客园 首页 新随笔 联系 管理 订阅 随笔- 397 文章- 0 评论- 78 JAVA基础学习day16--集合三-Map.HashMap,TreeMap与常用A ...
- html5 canvas常用api总结(一)
1.监听浏览器加载事件. window.addEventListener("load",eventWindowLoaded,false); load事件在html页面加载结束时发生 ...
随机推荐
- Javascript网址跳转方法
第一种: window.location.href="http://www.baidu.com"; 第二种: window.navigate("http://www.ba ...
- logout退出功能是怎么实现的?login登陆功能室怎么实现的
logout退出功能是怎么实现的?login登陆功能室怎么实现的 login就是登陆成功的时候,在session里面创建好用户对应的数据. logout就是登出的时候,在session里面销毁用户对应 ...
- PHP array_merge()
定义和用法 array_merge() 函数把两个或多个数组合并为一个数组. 如果键名有重复,该键的键值为最后一个键名对应的值(后面的覆盖前面的).如果数组是数字索引的,则键名会以连续方式重新索引. ...
- 去除ckeditor上传图片预览中的英文字母
去除ckeditor上传图片预览中的英文字母 CKEDITOR.replace('text', { filebrowserImageUploadUrl : 'upload_img.do', langu ...
- Python3基础(八) 模块
在程序中定义函数可以实现代码重用.但当你的代码逐渐变得庞大时,你可能想要把它分割成几个文件,以便能够更简单地维护.同时,你希望在一个文件中写的代码能够被其他文件所重用,这时我们应该使用模块(modul ...
- 鸟哥的Linux私房菜-----10、学习Bash
- CAS—改动默认登录页
1. 部署CAS-Server 本文以cas-server-3.4.11-release.zip为例.解压提取cas-server-3.4.11/modules/cas-server-webapp- ...
- 一个JS多个数组取交集算法
如题,多个数组中取交集(共同拥有元素),思路取第一个数组去跟每个数组中的元素对比,同时比较数据类型有救返回没有就返回null. 下面介绍到的算法数据格式是二维数组如: const parentArra ...
- hihoCoder #1175 : 拓扑排序·二
[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立马引 ...
- BestCoder Round #61 (div.2) B.Game 细节题
Game 问题描述 XY在玩一个游戏:有N根柱子排成一排,编号为1到N,每个柱子上面有一块宝石,现在XY站在第S根柱子上,出口在第T跟柱子上,XY需要拿到所有宝石后从出口离开.每次XY可以走到相邻 ...