非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿
持久化类的状态
持久化类三种状态
持久化类有三种状态,区分不同的状态,使用两种操作区分:
第一个 判断对象是否有oid
第二个 判断对象是否与session相关联
1、瞬时态
没有oid,没有与session相关联
User user = new User();
user.setUsername("xxx");
user.setBirthday(new Date());
2、持久态
有oid,与session相关联
User user = (User)session.get(User.class, 1);
3、托管态
有oid,没有与session相关联
User user = new User();
user.setId(1);
user.setUsername("大黄蜂");
三种状态之间转换
瞬时态
转换成持久态:调用save方法,saveOrUpdate方法实现
状态成脱管态:设置oid值
持久态
转换成瞬时态:调用delete方法实现
转换成脱管态:调用session里面的close方法实现
脱管态
转换成瞬时态:设置oid值为空
转换成持久态:调用update和saveOrUpdate方法实现
Hibernate的一级缓存
什么是缓存
把数据不放到文件系统中,放到系统内存中,可以直接从内存中获取数据,提高获取数据的效率
Hibernate的缓存
Hibernate的一级缓存
在Hibernate中的一级缓存默认是打开的,一级缓存使用的范围是session范围的。从session创建,到session关闭的过程。如果session关闭了,那么一级缓存也就关闭了。
Hibernate的二级缓存
在Hibernate中的二级缓存默认不是打开的,手动设置才可以使用。二级缓存使用范围是sessionFactory范围的二级缓存。
验证一级缓存的存在
第一个操作:首先添加记录,添加完成后,根据oid进行查询
//添加操作
User user = new User();
user.setUsername("岳不群");
user.setBirthday(new Date());
//调用save方法
Serializable id = session.save(user);
//根据返回的id值查询
User u = (User) session.get(User.class, id);
System.out.println(u);
第一次执行添加操作,发送sql语句,实现添加数据到数据库
第二次根据添加之后返回的id进行查询,没有查询数据库,而是查询一级缓存内容
第二个操作:第一次查询id是1的记录,第二次再次查询id值是1的记录
//第一次查询id值是1的记录
User user1 = (User) session.get(User.class, 1);
System.out.println(user1);
//第二次查询id值是1的记录
User user2 = (User) session.get(User.class, 1);
System.out.println(user2);
第一次查询数据库获取数据,第二次没有查询数据库,查询一级缓存的内容
持久态自动更新数据库
//查询id是2的记录
//持久态
User user = (User) session.get(User.class, 2);
//设置要修改的值
user.setUsername("哈哈");
//调用update
//session.update(user);
不需要调用update方法实现修改
一级缓存的快照区(副本)
//查询id是2的记录
//持久态
User user = (User) session.get(User.class, 2);
//设置要修改的值
user.setUsername("哈哈");
//调用update
//session.update(user);
首先根据id查询用户数据,返回user是持久态对象。
首先把返回的持久态user对象放到一级缓存中,另外,把user对象复制一份,再放到一级缓存对应的快照区。
设置了持久态对象里面的值的时候(修改了user里面的值),执行之后
首先,同步更新一级缓存中的内容;其次,但是不会更新对应快照区的内容
提交了事务之后,实现比较一级缓存和快照区的内容是否相同,如果不相同,把一级缓存中的内容更新到数据库里
一级缓存使用Java的集合存储,使用map集合
Key是一级缓存,Value是快照区
操作持久化类的方法
常用的方法
描述 | 方法 |
---|---|
添加 | save() |
修改 | update() |
删除 | delete() |
根据id查询 | get()、load() |
添加或修改 | saveOrUpdate() |
saveOrUpdate方法使用(保存、修改)
这个方法可以实现添加操作,也可以实现修改操作。根据实体类的不同状态实现不同的操作
第一个 实现添加操作
当实体类状态是瞬时态时候,调用这个方法实现添加操作
//实现添加操作
//瞬时态
User user = new User();
user.setUsername("东方不败");
user.setBirthday(new Date());
//执行saveOrUpdate方法
session.saveOrUpdate(user);
第二个 实现修改操作
持久化类状态是持久态和脱管态时,实现修改操作
//实现修改操作
User user = (User) session.get(User.class, 1);
user.setUsername("令狐冲");
//调用方法
session.saveOrUpdate(user);
//脱管态
User user = new User();
user.setId(2);
user.setUsername("任盈盈");
user.setBirthday(new Date());
//调用方法
session.saveOrUpdate(user);
load方法使用(延迟查询)
load方法和get方法相同,根据id查询数据,返回对象
区别:
get方法:立刻查询,执行方法之后,马上查询数据库
load方法:延迟查询,执行load方法之后,不会马上查询数据库,得到返回对象里面的值的时候才会去查询数据库
//get方法查询
User user = (User) session.get(User.class, 1);
System.out.println(user);
执行get方法之后,立刻发送语句查询数据库
//load方法查询
User user = (User) session.load(User.class, 3);
System.out.println(user.getId());
System.out.println(user.getUsername());
执行load方法之后,没有发送sql语句查询数据库,返回实体类对象中只有一个id值,但是得到实体类对象中除了id值之外其他值的时候,才会发送sql语句查询数据库
Hibernate的一对多关系映射
内容回顾
表与表之间关系
一对多
范例:一个客户可以有多个订单,一个订单只能属于一个客户
建表原则:在多的那一端创建字段作为外键,指向一的那一端的主键
多对多
范例:一定订单里面可以有多个商品,一个商品可以属于多个订单;一个学生可以选择多个课程,一个课程可以被多个学生选择
建表原则:创建第三张表,至少有两个字段,左为外键,指向另外两张表的主键
一对一
范例:一个公司对应一个注册地址,一个注册地址只能有一个公司
Hibernate的一对多关系映射
第一步 创建客户和订单的实体类
第二步 让实体类之间相互表示
客户实体类 Customer
package cn.itcast.onetomany;
import java.util.HashSet;
import java.util.Set;
/**
* 客户实体类
*/
public class Customer {
private Integer cid;
private String cname;
private String address;
//在客户里面表示所有的订单
//第二步使用集合表示 set集合 set集合有序的 并且内容不重复
private Set setOrders = new HashSet();
public Set getSetOrders() {
return setOrders;
}
public void setSetOrders(Set setOrders) {
this.setOrders = setOrders;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
订单实体类 Orders
package cn.itcast.onetomany;
/**
* 订单实体类
*/
public class Orders {
private Integer oid;
private String oname;
private Integer price;
//第二步表示订单所属的客户
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public String getOname() {
return oname;
}
public void setOname(String oname) {
this.oname = oname;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}
第三步 使用映射文件配置一对多关系(两个映射文件)
创建客户映射文件 Customer.hbm.xml 一的一方
创建订单映射文件夹 Order.hbm.xml 多的一方
第四步 需要把配置的映射文件引入到核心文件中
创建核心配置文件 hibernate.cfg.xml
com.mysql.jdbc.Driver
jdbc:mysql:///hibernate_day02
root
root
org.hibernate.dialect.MySQLDialect
true
true
update
第五步 创建工具类运行建表
创建工具类HibernateUtils工具类,并添加main方法
package cn.itcast.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 创建sessionFactory对象
*/
public class HibernateUtils {
static Configuration cfg = null;
static SessionFactory sessionFactory = null;
//静态代码块
static {
cfg = new Configuration();
cfg.configure();
//创建sessionFactory
sessionFactory = cfg.buildSessionFactory();
}
//提供得到Session的方法
public static Session getSession() {
Session session = sessionFactory.openSession();
return session;
}
public static void main(String[] args) {
}
}
一对多的级联保存(同时向多个表里添加数据)
有客户,有订单。比如添加一个客户,同时添加这个客户对应多个订单
原始方式:(开发一般不用)
创建TestOneToMany类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 演示级联保存操作
*/
public class TestOneToMany {
@Test
public void testSave1() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//第一步创建不同对象
//添加一个用户
Customer c1 = new Customer();
c1.setCname("小奥");
c1.setAddress("美国");
//添加用户对于的两个订单
Orders o1 = new Orders();
o1.setOname("飞机");
o1.setPrice(10);
Orders o2 = new Orders();
o2.setOname("航空母舰");
o2.setPrice(20);
//第二步互相表示
//设置用户和订单之间的关联关系
//表示用户里面有两个订单
//把两个订单放到customer的set集合里面
c1.getSetOrders().add(o1);
c1.getSetOrders().add(o2);
//表示两个订单所属的用户
o1.setCustomer(c1);
o2.setCustomer(c1);
//第三步添加这些对象
//调用方法保存
session.save(c1);
session.save(o1);
session.save(o2);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
这种方法如果只保存用户 或者只保存订单,不能进行操作,出现异常
级联保存另外实现方式(都使用)
设置互相表示的关系的时候,只需要设置一方,可以直接保存一方就可以了
但是在哪一方进行保存,需要在哪一方配置cascade="save-update"
通过客户进行保存
创建TestOneToMany测试类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 演示级联保存操作
*/
public class TestOneToMany {
//演示通过用户进行保存
@Test
public void testSave2() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//第一步 创建实体类对象
//添加一个用户
Customer c1 = new Customer();
c1.setCname("小温");
c1.setAddress("中国");
//添加用户对于的两个订单
Orders o1 = new Orders();
o1.setOname("篮球");
o1.setPrice(30);
Orders o2 = new Orders();
o2.setOname("足球");
o2.setPrice(20);
//第二步 设置用户所有的订单
//设置用户里面的所有的订单
c1.getSetOrders().add(o1);
c1.getSetOrders().add(o2);
//第三步 直接保存用户对象
//保存用户
session.save(c1);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
第四步 在用户的映射文件中配置 Customer.hbm.xml
通过订单进行保存
创建TestOneToMang测试类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 演示级联保存操作
*/
public class TestOneToMany {
//演示通过订单进行保存
@Test
public void testSave3() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//第一步 创建实体类对象
//添加一个用户
Customer c1 = new Customer();
c1.setCname("小江");
c1.setAddress("中国");
//添加用户对于的两个订单
Orders o1 = new Orders();
o1.setOname("眼镜");
o1.setPrice(30);
Orders o2 = new Orders();
o2.setOname("汽车2");
o2.setPrice(20);
//第二步 设置用户所有的订单
//设置订单所属的用户
o1.setCustomer(c1);
o2.setCustomer(c1);
//第三步 直接保存用户对象
//保存订单
session.save(o1);
session.save(o2);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
第四步 在订单的映射文件中配置 Order.hbm.xml
一对多的级联删除(同时删除多个表里面管理的数据)
不配置方法用户删除但是只是把订单变为null(不用)
创建TestOneToMany类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 演示级联删除操作
*/
public class TestOneToMany {
//级联删除操作
@Test
public void testDelete1() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//删除cid值是1的记录
Customer c1 = (Customer) session.get(Customer.class, 3);
//删除操作
session.delete(c1);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
根据用户删除配置方法(都用)
在hibernate的一对多的进行删除操作时候
比如删除用户,首先把用户关联的订单的外键设置为NULL,再删除用户
1、创建TestOneToMany类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 演示级联删除操作
*/
public class TestOneToMany {
//级联删除操作
@Test
public void testDelete1() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//删除cid值是1的记录
Customer c1 = (Customer) session.get(Customer.class, 3);
//删除操作
session.delete(c1);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
2、在用户的映射文件中配置 hibernate.hbm.xml
根据订单删除配置方法(不用)
1、创建TestOneToMany类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 演示级联删除操作
*/
public class TestOneToMany {
//级联删除操作
@Test
public void testDelete2() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//删除oid值是1的订单
Orders o1 = (Orders) session.get(Orders.class, 1);
//删除操作
session.delete(o1);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
2、在订单的映射文件中配置 Orders.hbml.xml
Hibernate的多对多关系映射
第一步 创建实体类
第二步 让学生和课程的实体类相关联
学生类 student
package cn.itcast.manytomany;
import java.util.HashSet;
import java.util.Set;
public class Student {
private Integer sid;
private String sname;
private String address;
//第二步 学生选择课程 ,一个学生可以选择多门课程
private Set setCourse = new HashSet();
public Set getSetCourse() {
return setCourse;
}
public void setSetCourse(Set setCourse) {
this.setCourse = setCourse;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
课程类 Course
package cn.itcast.manytomany;
import java.util.HashSet;
import java.util.Set;
public class Course {
private Integer cid;
private String cname;
// 第二步 在课程端表示被哪些学生选择,一门课程可以被多个学生选择
private Set setStudent = new HashSet();
public Set getSetStudent() {
return setStudent;
}
public void setSetStudent(Set setStudent) {
this.setStudent = setStudent;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
第三步 使用映射文件配置多对多关系(两个映射文件)
学生映射文件 student.hbm.xml
课程映射文件 Course.hbm.xml
第四步 需要把配置的映射文件引入到核心配置文件中
核心配置文件 hibernate.cfg.xml
com.mysql.jdbc.Driver
jdbc:mysql:///hibernate_day02
root
root
org.hibernate.dialect.MySQLDialect
true
true
update
第五步 创建工具类运行建表
HibernateUtils工具类 main方法
package cn.itcast.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 创建sessionFactory对象
*/
public class HibernateUtils {
static Configuration cfg = null;
static SessionFactory sessionFactory = null;
//静态代码块
static {
cfg = new Configuration();
cfg.configure();
//创建sessionFactory
sessionFactory = cfg.buildSessionFactory();
}
//提供得到Session的方法
public static Session getSession() {
Session session = sessionFactory.openSession();
return session;
}
public static void main(String[] args) {
}
}
多对多级联保存
创建TestManyToMany类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.manytomany.Course;
import cn.itcast.manytomany.Student;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 多对多操作
*/
public class TestManyToMany {
//根据课程保存
@Test
public void testSave2() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//添加两个学生
Student s1 = new Student();
s1.setSname("tom");
s1.setAddress("usa");
Student s2 = new Student();
s2.setSname("jack");
s2.setAddress("japan");
//添加课程
Course c1 = new Course();
c1.setCname("ui设计");
Course c2 = new Course();
c2.setCname("java开发");
Course c3 = new Course();
c3.setCname("韩语");
//根据课程保存
// s1 -- c1/c2
// s2 -- c1/c3
c1.getSetStudent().add(s1);
c1.getSetStudent().add(s2);
c2.getSetStudent().add(s1);
c3.getSetStudent().add(s2);
//保存
session.save(c1);
session.save(c2);
session.save(c3);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
//根据学生保存
@Test
public void testSave1() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//添加两个学生
Student s1 = new Student();
s1.setSname("lucy");
s1.setAddress("china");
Student s2 = new Student();
s2.setSname("mary");
s2.setAddress("japan");
//添加课程
Course c1 = new Course();
c1.setCname("汽车修理");
Course c2 = new Course();
c2.setCname("美容美发");
Course c3 = new Course();
c3.setCname("厨师");
//根据学生保存
// s1 --- c1 / c2
// s2 ---- c2 / c3
s1.getSetCourse().add(c1);
s1.getSetCourse().add(c2);
s2.getSetCourse().add(c2);
s2.getSetCourse().add(c3);
//保存
session.save(s1);
session.save(s2);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
根据学生保存 配置学生映射student.hbm.xml
根据课程保存 Courses.hbm.xml
多对多级联删除(不用)
创建TestManyToMany类
package cn.itcast.hibernate.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.manytomany.Course;
import cn.itcast.manytomany.Student;
import cn.itcast.onetomany.Customer;
import cn.itcast.onetomany.Orders;
import cn.itcast.utils.HibernateUtils;
/**
* 多对多操作
*/
public class TestManyToMany {
//多对多删除
@Test
public void testDelete() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//sid=1的学生删除
Student s = (Student) session.get(Student.class, 1);
session.delete(s);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
}
}
}
根据学生删除 配置学生映射student.hbm.xml
根据课程删除 配置课程映射Courses.hbml.xml