Hibernate 核心配置和核心API
1、 hibernate体系结构
Hibernate位于应用程序和数据库之间,将数据库底层完全封装,应用程序只需要操作持久化对象(Persistent Object),通过Hibernate生成SQL语句,完成对数据表中记录的操作。
hibernate 支持两种核心配置文件:
src/hibernate.properties(key-value文件键值对,主要配置Hibernate基本属性)
hibernate.connection.driver_class=com.mysql.jdbc.Driver
src/hibernate.cfg.xml (完成基本属性配置,加载hbm映射文件)
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<mapping resource="lsq/hibernate/domain/Customer.hbm.xml"/> 加载hbm映射
* hibernate.properties 无法加载 hbm映射 , 采用properties方式,必须手动编程加载 hbm文件或者 持久化类
2、 hibernate的常用属性
必须属性
hibernate.dialect 操作数据库方言
hibernate.connection.driver_class 连接数据库驱动程序
hibernate.connection.url 连接数据库URL
hibernate.connection.username 数据库用户名
hibernate.connection.password 数据库密码
可选属性
hibernate.show_sql true 在控制台上输出SQL语句
* hibernate 自己完成的,并没有使用日志系统 ,当关闭日志后,控制台仍然有SQL语句
hibernate.format_sql true 格式化控制台输出的SQL语句
* SQL 会自动换行,对于比较长的sql 查看方便
hibernate.hbm2ddl.auto create/create-drop/update/validate DDL策略
* DDL 主要建表语句,和表结构更新语句
create:表示启动的时候先drop,再create (测试人员 准备标准测试数据)
create-drop: 也表示创建,只不过再系统关闭前执行一下drop (测试程序是否正确)
update: 这个操作启动的时候会去检查schema是否一致,如果不一致会做scheme更新 (建表,更新表结构【只能加】)
validate: 启动时验证现有schema与你配置的hibernate是否一致,如果不一致就抛出异常,并不做更新
*** 在产品开发中 update 和 validate 使用较多
hibernate.connection.autocommit true 事务是否自动提交
* 用于解决 没有开启事务的操作时,事务如何自动处理
* 默认事务 自动回滚
3、 Hibernate 核心 API 详解
1) Configuration : 加载hibernate 配置
加载 hibernate.properties 和 hibernate.cfg.xml
持久化类与数据表的映射关系(*.hbm.xml 文件)
加载核心属性配置:
方式一:Configuration cfg = new Configuration(); 去src 读取 hibernate.properties 属性配置文件
方式二:Configuration cfg = new Configuration().configure(); 去src读取 hibernate.cfg.xml,
Configuration cfg = new Configuration().configure("自定义文件.xml"); 去src 加载指定文件
手动加载hbm映射配置:
如果没有对PO类进行hbm映射,运行时会报错:org.hibernate.MappingException: Unknown entity: lsq.hibernate.domain.Customer
需要手动加载hbm文件:
configuration.addResource("lsq/hibernate/domain/Customer.hbm.xml"); 加载hbm文件
或者
configuration.addClass(Customer.class); 加载Class,自动搜索hbm映射文件
** 如果使用 hibernate.cfg.xml配置,将映射配置xml中 <mapping resource="lsq/hibernate/domain/Customer.hbm.xml"/>
2)SessionFactory
Hibernate操作数据库,它的核心对象是Session,但是要想得到Session,需要先构造SessionFactory。
SessionFactory保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。
预定义SQL:
在配置文件中定义SQL,给SQL命名,在程序中通过预定义SQL名称(login)使用SQL
<sql-query name="login">
<![CDATA[select * from user where username= ? and password =?]]>
</sql-query>
SessionFactory对象是线程安全的。
SessionFactory负责维护Hibernate的二级缓存。
主要API:
Session openSession():随机从内部维护连接池中获取一个连接,构造Session对象。
Session getCurrentSession():获得一个与线程绑定Session的对象。(ThreadLocal)
SessionFactory内部维护数据库连接池很浪费资源,通常一个应用程序只有一个SessionFactory对象。
*抽象一个HibernateUtils工具类,确保只有一个SessionFactory(Static)
SessionFactory默认使用连接池时内置连接池,由DriverManagerConnectionProvider 类提供
* DriverManagerConnectionProvider 内部使用 DriverManager.getConnection 获得连接
package lsq.hibernate.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate操作工具类,只创建一个SessionFactory
* @author Daniel Li
*
*/
public class HibernateUtils {
private static Configuration configuration;
private static SessionFactory sessionFactory;
static{
//只对SessionFactory初始化一次
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
/**
* 获得Hibernate操作会话对象
* @return
*/
public static Session openSession(){
return sessionFactory.openSession();
}
}
配置c3p0连接池:
第一步 导入 c3p0-0.9.1.jar
第二步 在hibernate.cfg.xml 修改连接提供者
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
第三步 (选作) 配置c3p0连接池属性
<property name="c3p0.min_size">5</property>
<property name="c3p0.max_size">20</property>
<property name="c3p0.timeout">120</property>
<property name="c3p0.idle_test_period">3000</property>
3)Session
代表hibernate操作会话对象,相当于 Connection。
Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心。线程不安全(在方法内部定义和使用Session,不会出现线程问题)
Session进行PO对象的常见持久化操作,存在一级缓存。
常用方法:
save():插入;
update():完成修改;
delete():完成删除;
get/load():根据主键字段查询;
createQuery、createSQLQuery:创建查询对象,Query接收HQL,SQLQuery接收SQL;
createCriteria():面向对象条件查询
4)Transaction
commit():提交相关联的session实例。
rollback():撤销事务操作。
wasCommitted():检查事务是否提交。
如果没有开启事务,那么每个Session的操作,都相当于一个独立的事务。
*设置事务是否提交
<property name="hibernate.connection.autocommit">false</property> 事务不提交
<property name="hibernate.connection.autocommit">true</property> 事务提交
默认false
5)Query
Query代表面向对象的一个Hibernate查询操作。session.createQuery() 获得,接收参数 HQL语句
步骤:
获得Hibernate Session对象
编写HQL语句
调用session.createQuery 创建查询对象
如果HQL语句包含参数,则调用Query的setXXX设置参数
调用Query对象的list() 或uniqueResult() 方法执行查询
Query还包含两个方法用于控制返回结果。
setFirstResult(int firstResult):设置返回结果从第几条开始。
setMaxResults(int maxResults):设置返回结果记录条数。
案例一:查询所有数据 from Customer;
案例二:分页查询
案例三:通过select关键字,查询指定属性对应列
select name,age from Customer; 返回每条数据 保存 Object[] ----- List<Object[]>(返回的每条数据会保存到对象数组中,最后返回List)
如果想将查询结果,保存Customer对象中--->使用构造方法 !!!!!(在Customer类中,定义name和age属性构造器)
select new Customer(name,age) from Customer
案例四:通过where语句添加查询条件
无名字参数 from Customer where name= ? ; 设置参数 query.setParameter(0,"Curry");
有名字参数 from Customer where name= :myname; 设置参数 query.setParameter("myname","Curry");
package lsq.hibernate.test;
import java.util.List;
import lsq.hibernate.domain.Customer;
import lsq.hibernate.utils.HibernateUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
/**
* Hibernate的查询操作Query、Criteria
* @author Daniel Li
*
*/
public class HibernateTest2 {
//使用Query对象的查询
@Test
public void testQuery(){
//获得session
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//1、查询所有数据
String hql = "from Customer";
Query query = session.createQuery(hql);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//批量插入100条数据
@Test
public void testBatchInsert(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
for (int i = 0; i < 100; i++) {
Customer customer = new Customer();
customer.setName("name"+i);
customer.setAge(i);
customer.setCity("北京");
session.save(customer);
}
transaction.commit();
session.close();
}
//使用Query对象实现分页查询
@Test
public void testQueryPage(){
//获得session
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
String hql = "from Customer";
Query query = session.createQuery(hql);
query.setFirstResult(20);//索引20代表第21条数据
query.setMaxResults(10);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//使用Query对象查询指定属性对应列
@Test
public void testQuerySpecifiedColumn(){
//获得session
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//这里name和age是
// String hql = "select name,age from Customer";
String hql = "select new Customer(name,age) from Customer";
Query query = session.createQuery(hql);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//使用Query对象查询带有条件的查询(匿名参数)
@Test
public void testQueryCondition1(){
//获得session
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//匿名参数
String hql = "from Customer where name = ? and age = ?";
Query query = session.createQuery(hql);
//设置参数
query.setParameter(0, "Curry");
query.setParameter(1, 28);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//使用Query对象查询带有条件的查询(有名称的参数)
@Test
public void testQueryCondition2(){
//获得session
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//匿名参数
String hql = "from Customer where name = :cname and age = :cage";
Query query = session.createQuery(hql);
//设置参数
query.setParameter("cname", "Curry");
query.setParameter("cage", 28);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
}
6)Criteria接口
主要为了解决多条件查询问题,以面向对象的方式添加条件,无需拼接HQL语句
获得对象
Criteria criteria = session.createCriteria(Customer.class);
步骤
获得Hibernate的Session对象
通过Session获得Criteria对象
使用Restrictions的静态方法创建Criterion条件对象
向Criteria对象中添加Criterion 查询条件
执行Criterita的 list() 或uniqueResult() 获得结果
* Criteria查询 可以实现 和Query 一样效果
案例一 查询所有
Criteria criteria = session.createCriteria(Customer.class);
案例二 分页
criteria.setFirstResult(1);
criteria.setMaxResults(2);
案例三 条件查询
criteria.add(Restrictions.eq("name", "Curry"));
criteria.add(Restrictions.lt("age", 30));
criteria.add(Restrictions.like("name", "C%"));
** 当多条件组合查询时,criteria 更加方便
package lsq.hibernate.test;
import java.util.List;
import lsq.hibernate.domain.Customer;
import lsq.hibernate.utils.HibernateUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
/**
* 使用Criteria查询
* @author Daniel Li
*
*/
public class HibernateTest3 {
@Test
public void testCriteria(){
//获得session
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//1、查詢所有数据
// Criteria criteria = session.createCriteria(Customer.class);
// List<Customer> list = criteria.list();
// System.out.println(list);
//2、分页查询
// Criteria criteria = session.createCriteria(Customer.class);
// criteria.setFirstResult(1);
// criteria.setMaxResults(2);
// List<Customer> list = criteria.list();
// System.out.println(list);
//3、带有查询条件的查询
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("name", "Curry"));
criteria.add(Restrictions.lt("age", 30));
List<Customer> list = criteria.list();
System.out.println(list);
transaction.commit();
session.close();
}
}