【教程】Hibernate 的使用手册 -- Day 02【Hibernate 基本操作和事务】

实体类编写规则 ☆

  • 类似于JavaBean,实体类属性是私有
  • 私有属性通过公开的getset方法编辑
  • 要求(强制)实体类有属性作为唯一值(主键),通常用id
  • 实体类属性建议(非强制)不使用基本数据类型,使用对应包装类
    好处:Java 有8个基本数据类型,都有其对应的包装类,使用包装类可以使用NULL值,而基本数据类型不可以

HIbernate 主键生成策略

  • Hibernate 要求实体类中偶一个属性作为唯一值,对应表的主键,主键可以使用不同的生成策略
  • Hibernate 主键生成策略有很多值
<!--   配置文件中该行表示主键生成策略
	   native:主键自动增长
	   通常用 native | uuid
	   native会根据数据库选择使用identity | sequence
	   uuid会生成唯一的字符串,不需要自己设置
-->
<generator class="native"></generator>

多种生成策略

实体类操作

CRUD操作 ☆

  • 增 – 调用session的save方法实现
    //测试类
    public void testGet() {
    	//1 调用工具类得到sessionFactory
    	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    	//2 获取session
    	Session session = sessionFactory.openSession();
    	//3 开启事务
    	Transaction tx = session.beginTransaction();
    	//4 设置值,调用save方法
    	User u = new User();
    	u.setUsername("jack");
    	u.setPassword("124");
    	u.setAddress("china");	
    	session.save(u);
    	System.out.println(user);
    	//5 提交事务
    	tx.commit();
    	//6 关闭
    	session.close();
    	sessionFactory.close();	
    }
    
  • 删 – 调用session的delete方法实现
    //测试类
    //第一种 根据id查询对象再删除
    //第二种 new一个对象后设置其id再删除
    public void testDelete() {
    	//1 调用工具类得到sessionFactory
    	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    	//2 获取session
    	Session session = sessionFactory.openSession();
    	//3 开启事务
    	Transaction tx = session.beginTransaction();
    	
    	//4 删除操作
    	//第一种 根据id查询对象
    	User user = session.get(User.class, 2);
    	session.delete(user);
    	
    	//第二种 
    	User user = new User();
    	user.setUid(3);
    	session.delete(user);
    	
    	//5 提交事务
    	tx.commit();
    	//6 关闭
    	session.close();
    	sessionFactory.close();	
    }
    
  • 改 – 先查询,再根据返回的对象修改,最后调用session的update方法修改
    //测试类
    public void testUpdate() {
    	//1 调用工具类得到sessionFactory
    	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    	//2 获取session
    	Session session = sessionFactory.openSession();
    	//3 开启事务
    	Transaction tx = session.beginTransaction();
    	
    	//4 修改操作
    	// 修改uid=2记录username值
    	//4.1 根据id查询
    	User user = session.get(User.class, 2);
    	//4.2 向返回的user对象里面设置修改之后的值
    	user.setUsername("岳不群");
    	//4.3 调用session的方法update修改
    	//执行过程:到user对象里面找到uid值,根据uid进行修改
    	session.update(user);
    	
    	//5 提交事务
    	tx.commit();
    	//6 关闭
    	session.close();
    	sessionFactory.close();	
    }
    
  • 根据id查询 – 调用session的get方法实现
    //测试类
    public void testGet() {
    	//1 调用工具类得到sessionFactory
    	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    	//2 获取session
    	Session session = sessionFactory.openSession();
    	//3 开启事务
    	Transaction tx = session.beginTransaction();		
    	//4 根据id查询
    	//调用session里面的get方法
    	//第一个参数:实体类的class
    	//第二个参数:id值
    	User user = session.get(User.class, 1);
    	
    	System.out.println(user);
    	//5 提交事务
    	tx.commit();
    	//6 关闭
    	session.close();
    	sessionFactory.close();	
    }
    
  • SaveOrUpdate 操作 – 既能修改也能添加(根据实体类不同的状态做不同操作)
    //测试类
    
    //1 瞬时态 - 添加
    User user = new User();
    user.setUserName("demo1");
    user.setPassword("123");
    user.setAddress("中国");
    //实体类对象为瞬时态,做添加
    session.saveOrUpdate(user);
    
    //2 托管态 - 更新
    User user = new User();
    user.setUid(2);
    user.setUserName("demo2");
    user.setPassword("123");
    user.setAddress("中国");
    //实体类对象为托管态,做更新
    session.saveOrUpdate(user);
    
    //3 持久态 - 更新
    User user = session.get(User.class,3);
    user.setUserName("demo3");
    //实体类对象为持久态,做更新
    session.saveOrUpdate(user);
    

实体类对象状态

  • 实体类的三种状态
    • 瞬时态
      对象没有id值,对象与session也没有关联
      User a = new User();
      u.setUserName("TOM");
      u.setPasword("123");
      u.setAddress("China");
      //在save操作前对象与session无关联,也没有id值
      session.save(u);
      
    • 持久态
      对象里面有id值,且对象与session有关联
      User user = session.get(User.class,1);
      //user通过id查询所得,且通过session的get方法查询所得
      
    • 托管态
      对象里面有id值,对象与session无关联
      User user = new User();
      user.setUid(3);
      //对象内有id值,但是对象与session无关联
      session.delete(user);
      

Hibernate 一级缓存

缓存

  • 数据存到数据库里,数据库本身是文件系统,java中使用流的方式操作文件效率不高
  • 把数据存到内存中,不需要使用流的方式,可以直接读取内存中的数据,提高读取效率

Hibernate缓存(两类)

  • Hibernate 框架提供了很多优化方式,Hibernate 的缓存就是一个优化方式
  • 第一类:Hibernate的一级缓存,其特点如下:
    • 一级缓存是默认打开的
    • Hibernate 的一级缓存有使用范围,就是session的范围
    • Hibernate 的一级缓存中,存储的数据必须是持久态数据
  • 第二类:Hibernate的二级缓存,其特点如下:
    • 目前已经不使用了,使用替代技术redis
    • 二级缓存默认不是打开的,需要配置
    • 二级缓存使用范围是SessionFactory的范围
  • 一级缓存的使用的例子:
    1、 首先根据uid=1查询,返回对象
    2、 其次再根据uid=1查询,返回对象
    查询了两次uid=1的数据,第一次会发送SQL语句查询数据库,当第二次再查询相同数据时就不会发送SQL语句查数据库,而是直接查一级缓存

一级缓存的执行过程

  • 当第一次根据 uid=1 查询数据时,会先到一级缓存中查询,发现一级缓存中没有数据,才会到数据库中查询数据,返回 user1对象(持久态对象)
  • 把 user1 持久态对象放到一级缓存中
  • 当第二次根据相同条件查询数据时,也是先查询一级缓存,发现一级缓存中有相同的数据,直接返回
  • 一级缓存存储结构:存的不是一个整个的对象,是把整个对象的值放在一个空间内,再给这个空间起个名字,当有查询时,就会根据起的名字判断是否符合,符合则把这些值包装成一个对象再返回

一级缓存的特性 ---- 持久态自动更新数据库

  • 不需要update方法,也能实现修改
    //1 查询
    User user = session.get(User.class,1);
    //2 设置修改的对象值
    user.setUserName("demo4");
    //3 调用方法实现更新
    //但是有了持久态自动更新,便无需再调用update方法
    //持久态会自动更新一级缓存中的值
    //当你提交事务的时候就会直接发送update的SQL语句
    
  • 执行流程
    1. 一级缓存有对应的一块区域 – 快照区(也称副本,类似于备份);
    2. 当根据id查询的时候(上面第一行代码 ),会把返回的user持久态对象放到一级缓存中,还会放到一级缓存对应的快照区里面;
    3. 当修改user对象里面的值的时候,会修改持久态对象的值,同时还会修改一级缓存中的内容,但是不会修改一级缓存对应的快照区内容
    4. 最后需要提交事务,在提交事务的时候,会做比较一级缓存中的内容和对应的快照区内容是否相同;若不同,会把一级缓存中的内容更新到数据库里;若相同,就不会更新到数据库中;

Hibernate 事务操作

事务

  • 一项事务是由一条或多条操作数据库的SQL语句组成的一个不可分割的工作单元,即事务可理解为逻辑上的一组操作,组成这组操作的各个单元,要么都成功,要么有一个失败就全部失败,例如银行转账
  • 事务的特性(原子性,一致性,隔离性,持久性)
  • 不考虑隔离产生的问题
    脏读即一个事务读取到另一个事务未提交的数据;
    不可重复读即一个事务读到了另一个事务已经提交的update数据,导致同一个事务中的多次查询结果不一致;
    虚读即一个事物读到了另一个事务已经提交的insert的数据,导致同一个事务中的多次查询结果不一致;
  • 设置隔离级别(MySQL中默认的隔离级别 - repeatable read)

    在这里插入图片描述
    在这里插入图片描述

事务代码规范写法 ☆

  • 代码结构
    try{
      1. 开启事务
      2. 提交事务
    }catch(){
      3. 回滚事务
    }finally{
      4. 关闭
    }
    
  • 例子
    public void textTx(){
    	SessionFactory sessionFactory = null;
    	Session session = null;
    	Transaction tx = null;
    	try{
    		//获得session
    		sessionFactory = HibernateUtils.getSessionFactory();
    		session = SessionFactory.openSession();
    		//开启事务
    		tx = session.beginTransaction();
    		//添加
    		User a = new User();
    		a.setUserName("demo");
    		a.setAge(23);
    		session.save(a);
    		//提交
    		tx.commit();
    	}catch(Exception  e){
    		//回滚
    		tx.rollback();
    	}finally{
    		//关闭
    		session.close();
    
    		//在真正的web项目中不需要关闭,静态代码块只执行一次
    		SessionFactory.close();
    	}
    }
    

Hibernate 绑定 session

  • session 类似于jdbc的connection,底层就是ThreadLocal,session已经封装好
  • session是单线程的,但是当用户量非常大的时候,很难保证session还是单线程的,而与本地线程绑定,则可保证session的单线程
  • Hibernate框架已经实现了与本地线程绑定session,以保证session绝对的单线程
  • 获取与本地线程绑定的session
    (1)在Hibernate核心配置文件中配置
    <!-- 在第二部分配置Hibernate信息中配置 -->
    <property name="hibernate.current_session_context_class">thread</prooerty>
    
    (2)调用SessionFactory里面的方法得到
    //在HibernateUtils工具类中提供即可
    public static Session getSessionObject(){
    	return sessionFactory.getCurrentSession();
    }
    //测试类中可直接获得与本地线程绑定的session,不需要再通过SessionFactory获得
    session = HibernateUtils.getSessionObject();
    
  • session绑定本地线程,操作结束,线程结束,session会自动关闭,不需要再手动关闭session,而用openSession方法开启就需要手动关闭

Hibernate 其他API(查询)☆

Query 对象

  • 使用query对象,不需要写SQL语句,但是要写HQL(Hibernate query language)语句
  • HQL和SQL的区别
    (1) 使用SQL操作表和表字段
    (2)使用HQL操作实体类和属性
  • 查询所有数据的HQL语句
    (1) from 实体类名称
public void textQuery(){
	Session session = null;
	Transaction tx = null;
	try{
		//获得session
		session = HibernateUtils.getSessionObject();
		//开启事务
		tx = session.beginTransaction();
		//操作
		
		//1 创建Query对象
		//方法里面写HQL语句
		Query query = session.createQuery("from User");
		//2 调用Query对象的方法返回表中所有数据(多条用list)
		List<User> list = query.list();
		
		//提交
		tx.commit();
	}catch(Exception  e){
		//回滚
		tx.rollback();
	}finally{
		//session已自动关闭
	}
}

Criteria 对象

  • 新版已经不用了
  • 使用该对象不需要写语句,直接调用方法实现
public void textCriteria(){
	Session session = null;
	Transaction tx = null;
	try{
		//获得session
		session = HibernateUtils.getSessionObject();
		//开启事务
		tx = session.beginTransaction();
		//操作
		
		//1 创建Criteria对象
		//方法里面是参数实体类class
		Criteria criteria = session.createCriteria(User.class);
		//2 调用Criteria对象的方法返回表中所有数据(多条用list)
		List<User> list = criteria.list();
		
		//提交
		tx.commit();
	}catch(Exception  e){
		//回滚
		tx.rollback();
	}finally{
		//session已自动关闭
	}
}

SQLQuery 对象

  • 使用 Hibernate 的时候,通过调用底层SQL实现
public void textSQLQuery(){
	Session session = null;
	Transaction tx = null;
	try{
		//获得session
		session = HibernateUtils.getSessionObject();
		//开启事务
		tx = session.beginTransaction();
		//操作
		
		//1 创建SQLQuery对象
		//方法里面是sql语句
		String sql = "select * from user";
		SQLQuery sqlQuery = session.createSQLQuery(sql);
		//2 调用SQLQuery对象的方法返回表中所有数据(多条用list)
		//默认返回的list集合是数组的结构
		List<Object[]> list = criteria.list();
		//Arrays.toString(objects)可将数组以字符串形式输出
		
		//若要返回的list集合是对象的形式
		String sql = "select * from user";
		SQLQuery sqlQuery = session.createSQLQuery(sql);
		sqlQuery.addEntity(User.class);
		List<User> list = sqlQuery.list();
		//以上根据场景选一使用即可
		
		//提交
		tx.commit();
	}catch(Exception  e){
		//回滚
		tx.rollback();
	}finally{
		//session已自动关闭
	}
}
发布了27 篇原创文章 · 获赞 12 · 访问量 5186

猜你喜欢

转载自blog.csdn.net/Kobe_k/article/details/103984335