Hibernate的API一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。通过这些接口,可以对持久化对象进行存取、事务控制。
一、Configuration:
Configuration 类的作用是对Hibernate 进行配置,以及对它进行启动。在Hibernate 的启动过程中,Configuration 类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。
- 如果是配置文件写在了hibernate.properties文件中,则用如下形式创建配置对象:
Configuration cfg = new Configuration();
//这种方式需要手动加载映射文件
cfg.addResource("cn/jingpengchong/pojo/Customer.hbm.xml");
- 如果是配置文件写在了hibernate.cfg.xml文件中,则直接用如下形式创建配置对象并加载映射文件:
Configuration cfg = new Configuration().configure();
- 根据Configuration对象获取SessionFactory对象:
SessionFactory factory = cfg.buildSessionFactory();
二、SessionFactory:
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,内部维护了数据库连接池,并负责创建Session对象。这里用到了工厂模式,在一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
- 根据SessionFactory对象获得Session对象:
Session session = factory.openSession();
由于一个项目通常只需要一个SessionFactory,因此可以将Session的创建抽取工具类:
package cn.jingpengchong.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SessionFactoryUtil {
private static final Configuration CFG;
private static final SessionFactory SF;
static {
CFG = new Configuration().configure();
SF = CFG.buildSessionFactory();
}
public static Session getSessionFactory() {
return SF.openSession();
}
public static void closeSessionFactory() {
SF.close();
}
}
三、Session:
Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession,这里当使用session这个术语时,其实指的是Hibernate中的session。
可以根据需要开启事务,事务对象根据Session对象获得:
Transaction transaction = session.beginTransaction();
Session对被持久化对象的CRUD操作:以上篇博客的代码为例
1、增加操作:save()和saveOrUpdate()
save():添加操作;
saveOrUpdate():如果没有该数据(以id判断是否是同一数据或对象)则执行添加操作,如果有,则执行修改操作。
以save()为例,将Test类的主方法的第5步做如下修改:
Customer customer = new Customer();
customer.setName("猪八戒");
session.save(customer);
运行结果如下:
此时数据库的数据如下:
2、查询操作:get()、load()、createQuery()和createSQLQuery()
get()与load():查询一个对象,例:将Test类的主方法的第5步做如下修改
//方法一:get()
//Customer customer = session.get(Customer.class, 1l);
//方法二:load()
Customer customer = session.load(Customer.class, 1l);
System.out.println(customer);
运行结果如下:
get()与load()的区别:
- 执行到get()时立即发送SQL语句,而执行到load()时不发送SQL语句,只有在第一次使用查到的数据(除了访问该对象的id)时才发送SQL语句;
- get()获得的是真实的持久化类对象,load()获得的是继承了持久化类的代理类对象;
- get()没有查询到返回null,load()没有查询到会抛出异常。
createQuery():查询多个对象,例:将Test类的主方法的第5步做如下修改
Query<Customer> query = session.createQuery("from Customer",Customer.class);
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
运行结果如下:
createSQLQuery():查询多个对象,例:将Test类的主方法的第5步做如下修改
NativeQuery<Object[]> query = session.createSQLQuery("select * from cst_customer");
List<Object[]> list = query.list();
for (Object[] customer : list) {
System.out.println(Arrays.toString(customer));
}
运行结果如下:
createQuery()与createSQLQuery()的区别:
- createQuery()返回的是泛型为持久化类的Query对象,调用的list()方法可将其转换为泛型为持久化类的List集合;而createSQLQuery()返回的是泛型为Object[]的NativeQuery对象,调用的list()方法可将其转换为泛型为Object[]的List集合;
- createQuery()需要两个参数,一个是HQL语句,一个是Class类的实例;createSQLQuery()需要一个SQL表达式参数;
3、修改操作:update()和saveOrUpdate()
update():修改操作,如果不存在会报错;
saveOrUpdate():修改操作,如果不存在会作为新数据添加;
以update()为例,将Test类的第5步做如下修改:
//方法一:创建一个对象,将id设置为要修改的数据,根据cust_id修改cust_name
//Customer customer = new Customer();
//customer.setId(3l);
//customer.setName("齐天大圣");
//session.update(customer);
//方法二:根据要修改的记录的cust_id查询一个对象,然后对其进行修改(推荐)
Customer customer = session.get(Customer.class, 1l);
customer.setName("齐天大圣");
session.update(customer);
运行结果如下:
再看数据库确实已经修改:
4、删除操作:delete()
delete():删除记录,例:将Test类主方法的第5步做如下修改:
//方法一:创建一个对象,将id设置为要删除的数据,根据cust_id删除记录
//Customer customer = new Customer();
//customer.setId(1l);
//session.delete(customer);
//方法二:根据要修改的记录的cust_id查询一个对象,然后对其进行删除(推荐)
Customer customer = session.get(Customer.class, 1l);
session.delete(customer);
运行结果如下:
再看数据库确实已经删除了:
四、Transaction:
Transaction 接口是一个可选的API,可以选择不使用这个接口,取而代之的是Hibernate 的设计者自己写的底层事务处理代码。
- 事务的提交:
transaction.commit();
- 事务的回滚:
transaction.rollback();
五、Query:
Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作,例如下面的操作:
条件查询:
- from后应该写持久化类名,而非数据库中的表名
- 限定的条件可以是持久化类的属性名,也可以是与之对应的字段名
- 参数占位符的格式为“?0”、“?1”等,下面setParameter方法的第一个参数应与之对应
- setParameter(int arg0, Object arg1)用于指明给第arg0个参数设置为arg1
- list()用于将Query对象中查询到的对象存入List集合中
String hql = "from Customer where name like ?0";
Query<Customer> query = session.createQuery(hql,Customer.class);
query.setParameter(0, "%天%");
List<Customer> list = query.list();
for (Customer user : list) {
System.out.println(user);
}
运行结果如下:
分页查询:
- from后应该写持久化类名,而非数据库中的表名
- setFirstResult(int arg0)方法用于设置从第几条数据开始查询,从0开始
- setMaxResults(int arg0)方法用于设置一页显示几条数据
String hql = "from Customer";
Query<Customer> query = session.createQuery(hql,Customer.class);
query.setFirstResult(1);
query.setMaxResults(2);
List<Customer> list = query.list();
for (Customer user : list) {
System.out.println(user);
}
运行结果如下:
六、Criteria:
Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询。值得注意的是Criteria接口也是轻量级的,它不能在Session之外使用。