您的位置:首页 > 其它

Hibernate --- 核心API

2018-01-09 17:08 267 查看
一、Configuration --- 配置启动Hibernate,创建SessionFactory

Configuration 类的作用是对Hibernate 进行配置,以及对它进行启动。在Hibernate 的启动过程中,Configuration 类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。虽然Configuration
类在整个Hibernate 项目中只扮演着一个很小的角色,但它是启动hibernate 时所遇到的第一个对象。

1.1 Configuration加载配置方式:

(1) 自动加载配置

方式一:

Configuration config=newConfiguration().config();	   //常用:主要加载src下的hibernate.cfg.xml


方式二:

//主要加载的src下的hibernate.properties
Configuration config = new Configuration();

(2) 手动加载配置

方式一:

//加载指定的名称的配置文件
Configuration config = new Configuration().configure("hibernate.cfg.xml");


方式二:

//加载配置文件hibernate.cfg.xml
Configuration config = new Configuration().configure();

//如果hibernate.cfg.xml配置文件中没有指明映射文件,则可以通过如下方式手动加载映射文件
config.addResource("com/hibernate/domain/Customer.hbm.xml");
config.addClass(Customer.class);


1.2 Configuration创建SessionFactory:

SessionFactory sessionFactory = config.buildSessionFactory();


二、SessionFactory --- 工厂对象,用来创建Session
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

一个SessionFactory的内部状态是不可变的,一旦创建了这个内部状态的内部设置便不再与Configuration对象关联,这种状态包括所有关于对象/关系映射数据。SessionFactory在Hibernate中起到一个缓冲区的作用,它缓冲了Hibernate自动生成的SQL语句和一些其他的映射数据。

2.1 SessionFactory可以通过两种方法产生Session:

(1)getCurrentSession() --- 线程安全

Session session = sessionFactory.getCurrentSession();


(2)openSession() --- 非线程安全

Session session = sessionFactory.openSession();


2.2 两种产生Session方法的区别有:

(1) openSession()每次打开都是新的Session,并且需要人为的调用close方法关闭Session。

(2) getCurrentSession()是从当前上下文中获取Session并且会绑定到当前线程,第一次调用会自动创建一个Session实例,如果未手动关闭多次获取的是同一个Session,事物提交或者回滚时会自动关闭Session。

(3)使用getCurrentSession时,需要在配置文件中添加如下:

如果使用的是本地事务(JDBC事务)

<property name="current_session_context_class">thread</property>


如果使用的是全局事务(JTA事务)

<property name="current_session_context_class">jta</property>

注意:SessionFactory它不是轻量级的,不要频繁创建关闭它。在一个项目中一般创建一个SessionFactory就可以,通过SessionFactory来获取Session进行操作。

三、Session --- 负责执行CRUD操作

Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSession对象称为用户session。

Session的生命周期是以一个逻辑事物的开始和结束为边界,Session的主要功能是提供创建、读取和删除映射的实体类的操作,实体可能存在于三种状态:

(1) 瞬时状态(Transient)

(2) 持久化状态(Persistent)

(3) 脱管状态(Detached)

Hibernate对象的三种状态:

http://blog.csdn.net/ka_ka314/article/details/79017306

Session中有一个缓存,被称为hibernate的第一级缓存,它存放被当前工作单元加载的对象,这块缓存中有一map,在执行save方法后,会生成一个id,这个id会保存在map的key中,与之对应的value值就是该是该对象的引用,执行commit()方法后,数据库就有对应这条数据了,此时该实体处于持久化状态,当执行完Session.close()后,处于托管状态。

Session常用方法:

(1) save() : 保存对象

session.save(Object);// session的save方法是向数据库中保存一个对象


(2) update() : 修改对象

session.update(Object);// session的update方法是向数据库中更新一个对象


(3) delete() : 删除对象

session.delete(Object);//Object对象需要有ID。对象删除后,对象状态为Transistent状态


(4) get()/load() : 根据id进行查询

get()和load()方法的区别:

--- 从返回结果上对比:

load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常
get方法检索不到的话会返回null

--- 从检索执行机制上对比:

get方法和find方法都是直接从数据库中检索 而load方法的执行则比较复杂首先查找session的persistentContext中是否有缓存,如果有则直接返回
如果没有则判断是否是lazy,如果不是直接访问数据库检索,查到记录返回,查不到抛出异常 如果是lazy则需要建立代理对象,对象的initialized属性为false,target属性为null在访问获得的代理对象的属性时,检索数据库,如果找到记录则把该记录的对象复制到代理对象的target上,并将initialized=true,如果找不到就抛出异常。

get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。

--- get()和load()只根据主键查询,不能根据其他字段查询,如果想根据非主键查询,可以使用HQL

(5) saveOrUpdate : 执行save或update操作

在执行的时候hibernate会检查,如果对象在数据库中已经有对应的记录(是指主键),则会更新update,否则会添加数据save

(6) createQuery() : 获取一个Query对象

获取指定列信息

// 查询指定列信息
@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();

//可以使用hibernate中投影查询获取List<Customer>。我们只需要在Customer类中提供name与address做为参数的构造方法
//注意:必须还要提供一个无参构造方法
Query query = session.createQuery("select new Customer(name,address) from Customer");
List<Customer> list = query.list();

session.getTransaction().commit();
session.close();
}


分页查询

// 分页查询 一页显示10条 要得到第二页数据
@Test
public void test3() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 一页显示10条 要得到第二页数据

Query query = session.createQuery("from Customer");
query.setFirstResult(10); // 开始位置
query.setMaxResults(10); // 本次查询结果回显的条数

List<Customer> list = query.list();
session.getTransaction().commit();
session.close();
}


条件查询
// 条件查询
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction();

//方式一:
//Query query = session.createQuery("from Customer where name=?");
//query.setParameter(0, "姓名0");

//方式二:
Query query = session.createQuery("from Customer where name=:myname"); // 有名称参数

// 对有名称参数进行赋值
query.setParameter("myname", "姓名0");

// 如果能保证结果就是唯一的,那么可以使用
Customer c = (Customer) query.uniqueResult();

session.getTransaction().commit();
session.close();
}


(7) createSQLQuery() : 获取一个可以操作SQL的SQLQuery对象

// 执行本地sql----查询全部
@Test
public void test6() {
Session session = HibernateUtils.openSession();
session.beginTransaction();

SQLQuery sqlQuery = session.createSQLQuery("select * from t_customer");
// 想要将结果封装到Customer对象中
sqlQuery.addEntity(Customer.class);
List<Customer> list = sqlQuery.list();

session.getTransaction().commit();
session.close();
}


(8) createCriteria() : 获取一个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);

// 分页查询
// criteria.setFirstResult(firstResult)
// criteria.setMaxResults(maxResults)

// 多条件查询
// 1.查询name='姓名1'
//criteria.add(Restrictions.eq("name", "姓名1")); // where name='姓名1';
// 2.查询address='上海'
//criteria.add(Restrictions.eq("address", "上海"));
//Customer c = (Customer) criteria.uniqueResult();
//System.out.println(c);

//查询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();
}

QBC查询对照表:



(9) clear() : 清除session缓存

无论是load还是get,都会首先查找缓存(一级缓存,也叫session级缓存),如果没有,才会去数据库查找,调用clear()方法可以强制清除session缓存

(10) flush()

在hibernate中也存在flush这个功能,在默认的情况下session.commit()之前时,其实执行了一个flush命令。

Session.flush功能:

清理缓存;
执行sql(确定是执行SQL语句(确定生成update、insert、delete语句等),然后执行SQL语句。)

注意:

flush时,可以自己设定,使用session.setFlushMode(FlushMode)来指定,

FlushMode的取值:

FlushMode.ALWAYS : 任意一条SQL语句,都会flush一次
FlushMode.AUTO : 自动flush(默认)
FlushMode.COMMIT : 只有在commit时才flush
FlushMode.MANUAL : 手动flush
FlushMode.NEVER : 永远不flush,此选项在性能优化时可能用,比如session取数据为只读时用,这样就不需要与数据库同步了  

设置flush模式时,需要在session开启事务之前设置。

如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。

(11) evict() : 从session缓存中逐出对象

session.evict(customer);


四、Transaction --- 管理事务

Transaction 接口是一个可选的API,可以选择不使用这个接口,取而代之的是Hibernate 的设计者自己写的底层事务处理代码。 Transaction 接口是对实际事务实现的一个抽象,这些实现包括JDBC的事务、JTA
中的UserTransaction、甚至可以是CORBA 事务。之所以这样设计是能让开发者能够使用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移植。

五、Query --- 执行数据库查询

Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作。

参考Session.createQuery() or Session.creatSQLQuery()

六、Criteria --- 执行数据库查询

Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询。值得注意的是Criteria接口也是轻量级的,它不能在Session之外使用。

参考Session.createCriteria()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: