Hibernate持久化类&一级缓存&批量查询

  • 2019-05-16
  • 183
  • 0

什么是持久化类

持久化类: 与表建立了映射关系的实体类,就可以称之为持久化类。持久化类 = Java类 + 映射文件

持久化类的编写规则

  •  提供无参数的构造方法
  • 类中的成员都是私有的private
  • 对私有属性提供get/set方法
  • 属性尽量使用包装类类型 :默认值不同的,包装类默认值null,基本数据类型默认0。
  • 持久化类不要使用final进行修饰 :使用final修饰,延迟加载失效,变为立即加载。
  • 类中需要提供标识属性(OID),与表中主键建立映射关系 :Hibernate根据标识属性来判断对象是否是同一个的。

Hibernate中实体类的标识属性:  Object Identifie  简称OID属性,就是配置文件中对应主键的那个实体类属性。作用: 让hibernate来区分对象是否是同一个,如果多个对象的标识属性值相同,hibernate会认为是同一个对象,存储数据会报错


标识属性(oid属性)的作用在哪里

标识属性: Object Identifie  简称OID属性,作用: 可以让hibernate来区分多个对象是否是同一个对象。每个技术对于多个对象是否为同一个的判断凭据不同,jvm: 是根据内存地址,如果内存地址相同 多个对象它会认为是同一个。
数据库: 是根据主键,如果主键相同 多个对象它会认为是同一个。

hibernate:是根据oid,如果oid相同 多个对象它会认为是同一个,所以 hibernate必须得有一个oid属性,而且这个oid属性还不能相同

怎么保证每个对象oid属性的不同

使用就是hibernate提供的: 主键生成策略来保证

Hibernate主键生成策略

  • 自然主键:创建表的时候,使用的是实体中的自身属性作为表的主键。例如: 创建一张人员表,可以用自生的身份证号(唯一的不可重复的)作为主键
  • 代理主键:创建表的时候,使用的不是实体中的自身的属性作为主键,创建一个不相关一个字段作为主键。例如: 创建一张人员表,不使用自生的身份证号(唯一的不可重复的)作为主键,用另外创建一个id作为主键

尽量使用代理主键。如果自然主键,如果主键需要参与到业务逻辑中,有可能需要改变很多的设计和代码。


主键不应该由用户自己维护,应该统一管理,那么Hibernate就提供了主键统一管理的方式:主键生成策略。

  1. increment :自动增长,是Hibernate中提供一种自动增长方式,不是数据库中的自动增长。(适用于short、int、long类型的主键)首先使用select max(cust_id) from cst_customer;将这个最大值+1作为下一条记录的主键。对于并发访问数据库不适用
  2. identity :自动增长,适用于short、int、long类型的主键,使用的是数据库自动增长机制。不是所有数据库都支持自动增长,比如Oracle没有自动增长。 
  3. sequence :序列,适用于short、int、long类型的主键,使用序列方式完成主键的生成。必须是支持序列的方式的数据库。Oracle的自动增长
  4. native :本地策略,根据底层的数据库不同,自动选择使用identity还是sequence。
  5. uuid :随机字符串,适用于字符串类型的主键。
  6. assigned :Hibernate不维护主键,开发人员需要手动设置主键

总结: 以后如果针对是数值型,选择用native  如果是varchar类型,可以选择用uuid     但是也可以不用hibernate维护,自己在程序中手动设定唯一非空(assigned)uuid


Hibernate的持久化类的三种状态

Hibernate框架为了更好管理持久化类,将持久化类分成了三种状态:

  1. 瞬时态 :没有持久化标识OID,没有被session操作管理。
  2. 持久态 :有持久化标识OID,已经被session操作管理。
  3.  脱管态(离线态) :有持久化标识OID,没有被session操作管理。

public void test4()
		{
			Session session = HibernateUtils.openSession();
			Transaction tx = session.beginTransaction();
			// 瞬时态
			Customer customer = new Customer(); // oid属性没有值  session没有管理
			
			customer.setCust_name("abcd"); 
			
			// 持久态
			session.save(customer); // oid属性被生成策略(uuid)设置了 而且也被session管理
			
			tx.commit();
			session.close();
			
			// 脱管态 (离线态)
			System.out.println(customer.getCust_id()); //有oid属性值  没有被session操作管理
		}

持久态: 只要涉及到查询返回的就都是持久化类的持久态对象。特点: 如果持久态对象修改完属性,不需要执行更新操作,会自动更新数据库数据

public void test1()
		{
			Session session = HibernateUtils.openSession();
			Transaction tx = session.beginTransaction();
			
			// 先获取持久态对象: 只要涉及到查询返回的就都是持久化类的持久态对象
			Customer customer = session.get(Customer.class,"abcdefg");
			customer.setCust_name("hhhhhhhhhhhhh");
			
		/*	session.update(customer);*/
			
			tx.commit();
			session.close();
		}

为什么持久化类的持久态对象 在修改完了属性之后,不需要update也能自动更新到数据库?

原因: 一级缓存的存在  证明确实存在

Hibernate的一级概述

Hibernate框架本身的性能不是很好,但是Hibernate提供了很多的性能优化的手段,比如,延迟加载 缓存 

Hibernate框架共提供了两个级别的缓存:
一级缓存:称为Session级别的缓存。因为一级缓存的生命周期与session一致的。自带的,不可卸载的。(由Session中一系列的Java集合构成的)
二级缓存:称为SessionFactory级别的缓存。需要进行配置的缓存的插件。默认不开启的。 ehche==redis

注意:除了删除,增改查和数据库打完交道,都会往一级缓存中留一份,查询先去一级缓存查,差不到 在去数据库查 查询以后还会放到一级缓存中一份,但是session只要关闭,一级缓存的数据全部清空

// 一级缓存的存在
	@Test
	public void test2()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		// 保存  不止保存在数据库一份 还放在一级缓存中一份
		Customer customer = new Customer();
		customer.setCust_name("jjjjjjjjj");
		Serializable sl = session.save(customer);
		tx.commit();
		
		// 查询 先去一级缓存中查 查到了直接返回 差不到再去数据库
		Customer customer2 = session.get(Customer.class, sl);
		System.out.println(customer2.getCust_name());	
		session.close();
	}

清空一级缓存的数据

  • clear、evict、close管理一级缓存的相关的方法:
  • clear可以清空一级缓存的所有数据
  • evict可以清空一级缓存的某一个对象的数据

Hibernate中设置与当前线程绑定的session的使用

<property name="hibernate.current_session_context_class">thread</property>

	// 从当前线程种获取session使用
	@Test
	public void test10()
	{
		// 从当前线程中获取绑定的session
		// 好处: 那一层调用这个方法 获取的都是同一个session
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		Customer customer = new Customer();
		customer.setCust_name("下课");
		session.save(customer);
		tx.commit(); 
		//session.close();
	}
}

Hibernate的查询的API

我们只玩过oid查询  根据主键查询该条数据  sql语句会自动生成

	// oid查询
	@Test
	public void test1()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		Customer customser = session.get(Customer.class, "abcdefg");
		System.out.println(customser);
		
		tx.commit();
		session.close();
		
		// 只有增删改 一级oid查询 才会自动生成sql语句
	}

2种批量查询方式:

  1. Query方式    : 如果是使用这种方式做查询,又被称作为HQL查询 ,查的是对象和属性
  2. Criteria方式 : 如果是使用这种方式做查询,又被称作为QBC查询

Query之HQL查询

接收一个HQL进行查询:HQL-Hibernate Query Language Hibernate查询语言,与SQL语言语法很相似的一个语言。面向对象。

@Test
	/**
	 * Query接口
	 * HQL面向对象的查询.查询都是对象
	 */
	public void demo1(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		
		// 查询全部客户信息:
		/*Query query = session.createQuery("from Customer");
		List<Customer> list = query.list();
		
		for (Customer customer : list) {
			System.out.println(customer);
		}*/
		
		// 条件查询
		/*Query query = session.createQuery("from Customer where cust_name like ?");
		// 设置参数
		query.setParameter(0, "郝%");
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}*/
		
		// 分页查询:
		Query query = session.createQuery("from Customer");
		// 从哪开始的
		query.setFirstResult(3);
		// 每页显示记录数
		query.setMaxResults(3);
		
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}

全查

@Test
	public void test2()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		// 全查   类似sql语句的表达式  from 持久化类
		Query qr = session.createQuery("from Customer");
		List<Customer> list = qr.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
		session.close();
		
	}

条件查

@Test
	public void test3()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		// 条件查   类似sql语句的表达式  from 持久化类  where 属性=? 
		Query qr = session.createQuery("from Customer where cust_name like ?");
		qr.setParameter(0, "h%");
		List<Customer> list = qr.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
		session.close();
	}

分页查

@Test 
	public void test4()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		
		// 分页查   类似sql语句的表达式  from 持久化类  where 属性=? 
		Query qr = session.createQuery("from Customer");
		// from Customer limit 1,3;
		qr.setFirstResult(1);
		qr.setMaxResults(3);
		
		List<Customer> list = qr.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
		session.close();
	}
	

聚合查

@Test
	public void test9()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		// 聚合查
		Query qr = session.createQuery("select count(*) from Customer");
		Object obj = qr.uniqueResult();
		System.out.println(obj);
		tx.commit();
		session.close();
	}

投影查询

@Test
	public void test7()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		// 投影查询
				// 1 查多少字段 就需要在持久化类中写多少个构造参数
			    // 2 语法的书写: select new Customer(cust_id,cust_name) from Customer;
		Query qr = session.createQuery("select new Customer(cust_id,cust_name) from Customer");
		List<Customer> list = qr.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tx.commit();
		session.close();
	}

多列查

@Test
	public void test6()
	{
		Session session = HibernateUtils.openSession();
		Transaction tx = session.beginTransaction();
		// 多列查 返回的是Object数组 单列查  返回是Object
		Query qr = session.createQuery("select cust_id,cust_name from Customer");
		List<Object[]> list = qr.list();
		for (Object[] object : list) {
			System.out.println(Arrays.toString(object));
		}
		tx.commit();
		session.close();
	}
	

Criteria之QBC查询

QBC-Query By Criteria 条件查询。更加面向对象化查询语言。

@Test
	/**
	 * QBC查询:Query By Criteria
	 */
	public void demo2(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		
		// 查询全部:
	/*	Criteria criteria = session.createCriteria(Customer.class);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}*/
		
		// 条件查询
	    /**
		 * == 	eq
		 * >	    gt				 
* >=	ge		
		 * <	    lt		
		 * <=	le		
		 * <>	ne		
		 * in   in
		 * like like
		 * 
		 */


		/*Criteria criteria = session.createCriteria(Customer.class);
		// criteria.add(Restrictions.eq("cust_name", "郝天一"));
		criteria.add(Restrictions.like("cust_name", "郝%"));
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}*/
		
		// 分页查询
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.setFirstResult(3);
		criteria.setMaxResults(3);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		
		transaction.commit();
	}

评论

还没有任何评论,你来说两句吧

粤ICP备17155863号

- 友情链接 - Theme by Qzhai