持久化:将内存中的一个对象持久化到数据库的过程。Hibernate框架就是用来持久化的框架。
持久化类:一个java对象与数据表建立了映射关系,那么这个类在Hibernate中称为持久化类。 持久化类= java类 + 映射文件
1.提供无参构造 :Hibernate底层使用反射机制
2.私有属性提供公共的set/get方法 :Hibernate中获取、设置对象的值
3.对持久化类提供一个唯一标识属性OID与数据库主键对应:java中通过地址区分是否同一个对象,数据库通过主键确定是否同记录
4.持久化类中的属性尽量使用包装类型 :包装类型默认值为null;基本类型为0,有起义。
5.持久化类尽量不要用final修饰 :Hibernate使用延迟加载优化,返回的是代理对象,需要继承。(否则load变成get)
开发中尽量使用代理主键,这样可以在主键发生变化的时候不用修改源代码,也满足OCP原则。
Hibernate在实际开发中不允许用户手动设置主键,一般将主键交给数据库或手动编写程序进行设置。在hibernate中为了减少程序编写,提供了很多的主键生成策略,下面是重点:
increment hibernate中提供的自动增长机制,适用于short、int、long类型的主键。仅单线程程序中使用。
原理:首先发送一条语句:select MAX(id) from 表;然后将id+1作为下一条记录的主键。
identity 使用数据库底层的自动增长机制,适用于short、long、int。适用于有自动增长机制的数据库(MySQL、MSSQL)。 注意:Oracle是没有自动增长的。
sequence 采用序列机制,适用于short、int、long。适用于序列机制的数据库(Oracle)
uuid 适用于字符串类型主键。使用hibernate中随机方式生成字符串主键。
native 本地策略。可以在identity和sequence间进行自动切换。
assigned hibernate放弃外键管理。需要通过手动编写程序或用户自己设置。
foreign 外部的。会在一对一的关联映射下使用。
瞬时态(transient)
对象没有唯一表示OID,还没有被session管理。
持久态(persistent)
对象有唯一标识OID,被session管理。
持久化类的持久态对象可以自动更新数据库。
脱管态(detached)
有唯一表示OID,没有被session管理。
@Test
public void test1(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("二蛋"); //瞬时态对象:没有OID,没有被session管理
Serializable id = session.save(customer);//持久态对象:有OID,被session管理
transaction.commit();
session.close();
System.out.println("客户名称"+customer.getCust_name());//托管态对象:有OID,没被session管理
}
自动更新到数据库了:
@Test//持久态对象自动更新数据库
public void test2(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 1l);
customer.setCust_name("gg");
//不用保存到脱管,可以自动更新到数据库
// session.save(customer);
transaction.commit();
session.close();
}
那么,持久态是怎么自动保存数据到数据库中的呢——引出hibernate的一级缓存。
缓存是一种优化方式,可以将想用的数据保存到内存中,不用去存储源中 。
session级别的缓存:生命周期与session一致(一级缓存是由Session中的一系列java集合构成的)。一级缓存是hibernate自带的不可卸载。
一级缓存内部结构
一级缓存中的特殊区域:快照区。将一级缓存进行快照,提交的数据和快照区一样不更新数据库,不一致时更新到数据库。
注:close()和clear()和evict(Object obj)可以清除缓存。
默认不开启,需要配置,一般用redis替代二级缓存。是SessionFactory级别的缓存。
事务复习链接
在hibernate.cfg.xml中设置事务的隔离级别:
4
隔离级别参见事务部分文章。
往工具类中添加获取当前session的方法:
/**
*
* 这个方法默认不能用,需要配置
* thread
* 可以不需要close();线程结束会自动销毁session
* @return
*/
public static Session getCurrentSession(){
return sf.getCurrentSession();
绑定session本地线程:
thread
/**
* 测试当前线程绑定的session
* @author malaganguo
*/
public class HibernateDemo3 {
@Test
public void demo1(){
Session session = HibernateUtils.getCurrentSession();//保证同一个session
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("快乐风男");
session.save(customer);
transaction.commit();
//注意:getcurrentSession()方法会自动关闭线程,如果这里再写session.close()会报错。
}
}
用于接收HQL,查询多个对象。
@Test
public void test1(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//简单查询
String hql = "from Customer";
//条件查询
hql = "from Customer where cust_name like ?";
Query query = session.createQuery(hql);
//设置条件
query.setParameter(0, "%");//模糊查询的条件
//设置分页
query.setFirstResult(0);//相当于LIMIT的第一个参数,不过这里是从0开始的
query.setMaxResults(3);//每页显示多少条记录
List list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
/**
* Criteria
*/
@Test
public void test2(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
/* //通过session创建Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
List list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}*/
/* //criteria模糊查询
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.like("cust_name", "男", MatchMode.END));
//criteria.add(Restrictions.like("cust_name", "%男"));//两种模糊查询方式
List list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}*/
//criteria分页查询
Criteria criteria = session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResults(3);
List list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
Query和Criteria一般都可以搞定,但是遇到复杂的SQL操作,比如表关联等,则需要用到SQLQuery对象。
查询的代码:
//SQLQuery查询:创建查询时写sql语句就行了
SQLQuery query = session.createSQLQuery("select * from cst_customer");
List
SQL查询同样支持分页查询的方法调用和模糊查询的方法调用。