文章目录
Hibernate 的主键生成策略
实际开发中不允许用户手动设计主键,一般将主键交给数据库,手动编写程序进行设置
- increment:hibernate中提供的自动增长机制,适用于short,int,long类型的主键,在单线程程序中使用
- identity:适用于short,int,long类型的主键,使用的是数据库底层的自动增长机制,适用于有自动增长机制的数据库(MySql)
- sequence:适用于short,int,long类型的主键,采用的是sequence的方式,像MYsql不能使用sequence
- uuid:适用于字符串类型的主键,使用hibernate中的随机方式生成字符串主键
- native:本地策略,可以在identity和sequence之间自动切换
- assigned:hibernate放弃外键的管理,需要通过手动编写程序或者用户自己设置
- foreign:外部的,一对一的关联映射的情况下使用
持久化类的三种状态
hibernate是持久化框架,通过持久化类完成ORM(object relational mapping)操作,hibernate为了更好的管理持久化类,将持久化类分成三种状态。
瞬时态
这种对象没有唯一的标识oid,没有被session所管理,称为瞬时态对象
瞬时态对象
获取 Customer customer = new Customer();
状态转换
瞬时->持久
save(),saveOrUpdate();
瞬时->脱管
Customer.setCust_id(1)
持久态(presisted)
这种对象有唯一的标识oid,被session所管理,称为持久态对象
- 持久化类的持久态的对象,可以自动更新数据库
持久态对象获取
get,load,find,iterate
session.get(Customer.class,1)
状态转换
持久->瞬时
delete
持久->脱管
session.close,clear, evict
脱管态(detached)
有唯一标识oid,没有被session管理,称为脱管态对象
获得Customer customer = new Customer > customer.setCust_id(1)
状态转换
脱管->持久
update(),saveOrUpdate()
脱管->瞬时
customer.setCust_id(null)
@Test
public void demo1() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();//瞬时态对象:没有唯一标识oid,没有session管理
customer.setCust_name("王东");
Serializable id = session.save(customer);//持久态对象,有唯一标识oid,被session管理
Customer c1 = session.get(Customer.class, id);
transaction.commit();
session.close();
System.out.println("客户名称:" + customer.getCust_name());//脱管态,有唯一标识oid,没有session管理
}
Hibernate的缓存
缓存:是一种优化的方式,将数据存入内存,使用的时候直接从缓存中获取,不用通过存储源
Hibernate的一级缓存:称为是Session级别的缓存,一级缓存生命周期与session一致(一级缓存是由Session中的一系列的java集合构成),一级缓存是自带的不可卸载的。(Hibernate的二级缓存是SessionFactory级别的缓存,需要配置缓存)
@Test
public void demo1() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 1l);
System.out.println(customer);
Customer customer1 = session.get(Customer.class, 1l);
System.out.println(customer1);
System.out.println(customer == customer1);
transaction.commit();
session.close();
}
Hibernate的一级缓存的结构
快照区:session的一级缓存区中存在这样一个快照区,它复制了一份当前session中的缓存,当这份缓存因为调用其他方法而被改变时,当tx.commit方法执行的时候,程序会比较缓存区和快照区的数据:数据一致的时候,不更新数据库;数据不一致的时候,更新数据库。
hibernate的事务管理
事务:事务指的是逻辑上的一组操作,组成这组操作的各个逻辑单元要么都成功,要么都失败
事务的特性:
- 原子性:代表事务不可分割
- 一致性:代表事务执行前后,数据的完整性保持一致
- 隔离性:事务执行的过程中,不应该受其他事务的干扰
- 持久性:事务执行完成后,数据就持久到数据库中
不考虑隔离性:
- 读问题:
- 脏读:一个事务读到了另一个事务未提交的数据
- 不可重复读:一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致
- 虚读:一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致
- 写问题:
引发两类丢失更新
事务的隔离级别:
设置事务的隔离级别
- read uncommited:以上读问题都会发生
- read commited:解决脏读,但是不可重复读和虚读有可能发生
- repeatable read:解决脏读和不可重复读,但是虚读有可能发生
- serializable:解决所有读问题
Service中封装业务逻辑操作
必须保证连接对象是同一个:
- 向下传递 DBUtils
- 使用ThreadLocal对象
Hibernate框架内部已经绑定好了ThreadLocal
在sessionFactory中提供了一个方法getCurrentSession()
通过一个配置完成
<!--配置当前线程绑定的session-->
<property name="hibernate.current_session_context_class">thread</property>
当前线程销毁,session销毁;因此不需要session.close
Hibernate的其他API
Query
public void demo1() {
Session currentSession = HibernateUtils.getCurrentSession();
Transaction transaction = currentSession.beginTransaction();
//通过session获得Query接口
//简单查询
String sql = "from Customer";
//条件查询
String sql1 = "from Customer where cust_name like ?";
Query query1 = currentSession.createQuery(sql1);
//设置条件
query1.setParameter(0, "王%");
//设置分页
query1.setFirstResult(0);
query1.setMaxResults(3);
Query query = currentSession.createQuery(sql);
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
List<Customer> list1 = query1.list();
for (Customer customer : list1) {
System.out.println(customer);
}
transaction.commit();
}
Criteria
SQLQuery
用于接收sql语句
Hibernate多对多的配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.itheima.hibernate.demo1.User" table="sys_user">
<!--建立OID与主键的映射-->
<id name="user_id">
<generator class="native"></generator>
</id>
<!--建立普通属性与字段的映射-->
<property name="user_code" column="user_code"/>
<property name="user_name" column="user_name"/>
<property name="user_password" column="user_password"/>
<property name="user_state" column="user_state"/>
<!--关联关系的映射配置-->
<!--
set标签
name:对方的集合的属性名称
table: 多对多需要使用中间表,table为中间表的名称
-->
<set name="roles" table="sys_user_role" cascade="save-update">
<!--
key标签:
column:当前对象对应中间表的外键的名称
-->
<key column="user_id"></key>
<!--
class:对方的类的全路径
column:对方的对象在中间表中外键的名称
-->
<many-to-many column="role_id" class="com.itheima.hibernate.demo1.Role"/>
</set>
</class>
</hibernate-mapping>