目录
一、Hibernate实体的状态
1、状态介绍
2、瞬时状态 转 持久状态
3、持久状态转脱管状态(游离状态)
4、总结状态转换过程
二、缓存
1、一级缓存
session级别的缓存
2、快照----对一级缓存的数据进行备份
3、一级缓存的刷新
会执行select语句一次、update语句一次
4、一级缓存的细节
HQL结果是会进行一级缓存,SQL的结果不会添加到一级缓存中
@Test
public void testFirstCache(){
/**
* 一级缓存的细节
* HQL的结果会进行以及缓存,SQL的结果不一定添加到一级缓存中
*/
Session session = HibernateUtil.openSession();
/*
查询所有数据
*/
/* //1、HQL
Query queryq = session.createQuery("From User");
List<User> list1 = queryq.list();
System.out.println(list1);
//2、sql
SQLQuery query = session.createSQLQuery("select * from user");
List list = query.list();
System.out.println(list);*/
//3、Criteria,会对数据进行一级缓存
Criteria criteria = session.createCriteria(User.class);
List list = criteria.list();
System.out.println(list);
//使用get方法查询一条数据,没有则为空
User user = session.get(User.class, 4);//,Criteria查询后,会将数据添加到以及缓存中,查询主键为4的时候,首先在缓存中进行匹配,若没有匹配到对应的字段,然后再去数据库中查找
System.out.println(user);
//load方法:查询不存在的数据时会报错
//比如:ObjectNotFoundException: No row with the given identifier exists: [com.dzg.domain.User#4]
User loadUser = session.load(User.class, 3);
System.out.println(loadUser);
}
5、其它API
@Test
public void testSave(){
Session session = HibernateUtil.openSession();
session.getTransaction().begin();
//刚new出来的对象时瞬时状态 ,经过save后,变成持久状态
User user = new User("cacheName","1234");//瞬时态
session.save(user);//持久态
session.clear();//,移除缓存,user变成托管状态
session.save(user);//执行insert语句
session.getTransaction().commit();
session.close();
}
@Test
public void testPersist(){
Session session = HibernateUtil.openSession();
session.getTransaction().begin();
//刚new出来的对象时瞬时状态 ,经过save后,变成持久状态
User user = new User("persistName","5678");//瞬时态
//1、使用persit方法进行保存,不能设置主键,否则报错user.setId(8);
//javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.dzg.domain.User
session.persist(user);//持久态
session.getTransaction().commit();//注释掉该条语句,即不加事务,persist方法不会执行insert语句
session.clear();
}
save和persist方法的区别:
三、Hibernate的多表关联关系映射
1、案例:一对多、多对一
客户和订单表之间的关系
customer的配置文件
<?xml version="1.0"?>
<!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.dzg.domain.Customer" table="t_customer" >
<id name="id" column="id">
<generator class="native"/>
</id>
<!--模型和表格的字段名一样,column可以不写-->
<property name="name"/>
<!--
描述一对多的关系
key中column写的是外键的名称
one-to-many:一对多,里面写class,写多的一方
inverse:其作用是指定由哪一方来维护关联关系
当一方指定了inverse = false(默认)
那么另一方,就负责关联关系
true:则外键有另一方维护
-->
<set name="orders" inverse="true">
<key column="customerId"></key>
<one-to-many class="com.dzg.domain.Order"></one-to-many>
</set>
</class>
</hibernate-mapping>
order的配置文件
<?xml version="1.0"?>
<!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.dzg.domain.Order" table="t_order" >
<id name="id" column="id">
<generator class="native"/>
</id>
<!--模型和表格的字段名一样,column可以不写-->
<property name="name"/>
<!--
描述多对一的关系
many-to-one:多对一,
class:写一的一方
column:写外键
-->
<many-to-one name="customer" class="com.dzg.domain.Customer" column="customerId"/>
</class>
</hibernate-mapping>
测试添加数据:不需要自己创建表,可以使用创建会话的形式,对应的实体类属性JavaBean的写法,配置文件之间的关系配置好
可以自动创建表;
//这会自动创建表
@Test
public void testCreateTable(){
Session session = HibernateUtil.openSession();
session.close();
}
@Test
public void testOneToMany(){
Session session = HibernateUtil.openSession();
session.getTransaction().begin();//开启事务
//保存数据
//1、创建客户对象
Customer customer = new Customer();
customer.setName("张三");
//2、创建两个订单
Order order1 = new Order();
order1.setName("轩辕剑");
Order order2 = new Order();
order2.setName("倚天剑");
//3、维护客户与订单的关系
order1.setCustomer(customer);
order2.setCustomer(customer);
//4、客户拥有订单
customer.getOrders().add(order1);
customer.getOrders().add(order2);
//5、保存数据
session.save(customer);//保存客户先
session.save(order1);
session.save(order2);
session.getTransaction().commit();//提交事务
session.close();
}
2、设置外键维护的方式
3、一对多的查询和删除
/**
* 查询和删除
*/
@Test
public void testOneAndManyQuery(){
Session session = HibernateUtil.openSession();
//查询一对多
/**
* 默认情况下,只有当使用Customer的orders1的数据,会执行SQL语句
*/
//1、查询客户
Customer customer = session.get(Customer.class, 1);
System.out.println("客户的名称为:"+customer.getName());
//客户的所有订单
// Query query = session.createQuery("From Order o where o.customer = ?");
Set<Order> orders = customer.getOrders();
for (Order order:
orders) {
System.out.println("订单的名称:"+order.getName());
}
session.close();
}
@Test
public void testOneAndManyDelete(){
Session session = HibernateUtil.openSession();
//一对多的删除
session.getTransaction().begin();
Customer customer = session.get(Customer.class, 2);
//如果要删除一对多,至少将订单的约束去除
Set<Order> orders = customer.getOrders();
for (Order order:
orders) {
order.setCustomer(null);//回执行update语句,将外键设置为null
}
session.delete(customer);
session.getTransaction().commit();
session.close();
}
4、级联保存和删除
cascade级联
/**
* 级联保存,保存A的时候,也保存B
*/
@Test
public void testOneToManySaveCascade(){
Session session = HibernateUtil.openSession();
session.getTransaction().begin();//开启事务
//保存数据
//1、创建客户对象
Customer customer = new Customer();
customer.setName("凯斯凯德");
//2、创建两个订单
Order order1 = new Order();
order1.setName("数据一");
Order order2 = new Order();
order2.setName("数据二");
//3、维护客户与订单的关系
order1.setCustomer(customer);
order2.setCustomer(customer);
//4、客户拥有订单
customer.getOrders().add(order1);
customer.getOrders().add(order2);
//5、保存数据
session.save(customer);//保存客户,也保存订单
/*
设置 <set name="orders" inverse="true" cascade="save-update">中
cascade="save-update"则会级联保存数据
session.save(order1);
session.save(order2);*/
session.getTransaction().commit();//提交事务
session.close();
}
@Test
public void testOneAndManyDeleteCascade(){
Session session = HibernateUtil.openSession();
//一对多的删除
session.getTransaction().begin();
Customer customer = session.get(Customer.class, 3);
//配置了级联删除后,删除customer的同时将其对应的订单数据也删除
//<set name="orders" inverse="true" cascade="delete"> ---->cascade="delete"
/**执行删除的操作,先删除有外键的订单表内的相关数据,然后再删除客户表的数据
Hibernate:
select
customer0_.id as id1_0_0_,
customer0_.name as name2_0_0_
from
t_customer customer0_
where
customer0_.id=?
Hibernate:
select
orders0_.customerId as customer3_1_0_,
orders0_.id as id1_1_0_,
orders0_.id as id1_1_1_,
orders0_.name as name2_1_1_,
orders0_.customerId as customer3_1_1_
from
t_order orders0_
where
orders0_.customerId=?
Hibernate:
delete
from
t_order
where
id=?
Hibernate:
delete
from
t_order
where
id=?
Hibernate:
delete
from
t_customer
where
id=?
*/
session.delete(customer);
session.getTransaction().commit();
session.close();
}
孤儿删除:
@Test
public void testOneAndManyDeleteOrphan(){
Session session = HibernateUtil.openSession();
//一对多的删除
session.getTransaction().begin();
//获取客户
Customer customer = session.get(Customer.class, 1);
//删除客户1的所有订单,但是客户仍然存在
//孤儿删除步骤,1、设置cascade=“delete-orphan” 2、把订单从Customer的set集合中删除,移除客户的订单内的数据
Set<Order> orders = customer.getOrders();
Iterator<Order> iterator = orders.iterator();
while (iterator.hasNext()){
iterator.next();// 取出下一个元素
iterator.remove();
}
// session.delete(customer);
session.getTransaction().commit();
session.close();
}