SSH框架之Hibernate第二篇

  • 2019 年 10 月 5 日
  • 笔记

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/zhao1299002788/article/details/100622959

1.1 持久化类的编写规则  		1.1.1 什么是持久化类?  			持久化类 : 与表建立了映射关系的实体类,就可以称之为持久化类.  			持久化类 = Java类 + 映射文件.    		1.1.2 持久化类的编写规则  			(1): 提供无参数的构造方法  			(2): 类中的成员都是私有的private  			(3): 对私有属性提供get/set方法  			(4): 属性尽量使用包装类类型								: 默认值不同的,包装类默认值null,基本数据类型默认0.  			(5): 持久化类不要使用final进行修饰						: 使用final修饰,延迟加载失效,变为立即加载.  			(6): 类中需要提供标识属性(OID), 与表中主键建立映射关系  : Hibernate根据标识属性来判断对象是否是同一个的.    			持久化类就是一个特殊的javabean    			Hibernate 中实体类的标识属性 : Object Identifie  简称OID属性  					就是配置文件中对应主键的那个实体类属性.    					作用: 让Hibernate来区分对象是否是同一个.  							如果多个对象的标识属性值相同,hibernate会认为是同一个对象,存储数据会报错.    			OID属性都是交给hibernate来维护:  				好处 : 不会用重复相同的OID属性.  					不用自己去写代码保证非空唯一.    	1.2 Hibernate 主键生成策略:  		1.2.1 区分自然主键和代理主键  			自然主键 : 创建表的时候,使用的是实体中的自身属性作为表的主键.  				例如 : 创建一张人员表,可以用自生的身份证号(唯一的不可重复)作为主键.    			代理主键 : 创建表的时候,使用的不是实体中的自身的属性作为主键,创建一个不相关的字段作为主键.  				例如 : 创建一张人员表,不使用自生的身份证号(唯一的不可重复的)作为主键,用另外创建一个id作为主键.    			尽量使用代理主键.如果选用自然主键,当主键需要参与到业务逻辑中,有可能需要改变很多的设计和代码.    		1.2.2 的主键生成策略  			主键不应该由用户自己维护,应该统一管理,那么Hibernate就提供了主键统一管理的方式: 主键生成策略.    			increment : 自动增长, 是hibernate中提供一种自动增长方式,不是数据库中的自动增长.(适用于short,int,long类型的主键)  							首先使用 select max(cust_id) from cust_customer;将这个最大值 + 1 作为下一条记录的主键.  							对于并发访问数据库不适用.    			identity  : 自动增长, 适用于short,int,long类型的主键,使用的是数据库自动增长机制.不是所有数据库都支持自动增长,比如Oracle没有自动增长.    			sequence  : 序列, 适用于short,int,long类型的主键,使用序列方式完成主键的生成.必须是支持序列的方式的数据库.Oracle的自动增长.    			native 	  : 本地策略,根据底层的数据库不同,自动选择使用identity还是sequence.    			uuid 	  : 随机字符串,适用于字符串类型的主键.    			assigned  : Hibernate不维护主键,开发人员需要手动设置主键.    			总结: 以后如果是针对是数值型,选择用native,如果是varchar类型,可以选择用uuid  				但是也可以不用hibernate维护,自己在程序中手动设定唯一非空(assigned)    	1.3 持久化类的三种状态  		1.3.1 Hibernate 的持久化类的三种状态.  			Hibernate框架为了更好管理持久化类,将持久化类分成了三种状态.  				瞬时态 : 没有持久化标识OID,没有被session操作管理.  				持久态 : 有持久化标识OID,已经被session操作管理.  				脱管态(离线态) : 有持久化标识OID,没有被session操作管理.    		1.3.2 区分持久化类的三种状态  			public void demo1() {  				Session session = HibernateUtils.openSession();  				Transaction transaction = session.beginTransaction();    				//瞬时态 : 没有持久化标识OID,没有被session管理.  				Customer customer = new Customer();  				customer.setCust_name("黄天华");    				//持久态 : 有持久化标识OID,已经被session管理  				Serializable id = session.save(customer);  				System.out.println(id);    				transaction.commit();  				session.close();    				//脱管态 : 有持久化标识OID,没有被session管理.  				System.out.println(customer.getCust_name());    			}    		1.3.3 三种状态的转换(面试题)  			瞬时态 : 没有持久化标识OID,没有被session管理.  				获得:  				Customer customer = new Customer();  				状态转换:  					瞬时 --> 持久 : save,saveOrUpdate  					瞬时 --> 托管 : customer.setCust_id(1L);    			持久态 : 有持久化标识OID,已经被session管理  				获得 : 只要是涉及到查询方法都是直接获得持久态对象.  				Customer customer = session.get(Customer.class,1L);  				状态转换  				持久 --> 托管 : close  				持久 --> 瞬时 : delete    			脱管态 : 有持久化标识OID,没有被session管理  				获得  				Customer customer = new Customer();  				customer.setCust_id(1L);  				状态转换 :  				托管 --> 持久 : save,update,saveOrUpdate  				托管 --> 瞬时 : customer.setCust_id(null)    			持久态 : 只要涉及到查询返回的就都是持久态类的持久态对象.  				特点 : 如果持久态对象修改完属性,不需要执行更新操作,会自动更新数据库数据.    		1.3.4 持久态可以自动更新数据库    			public void demo2() {  				Session session = HibernateUtils.openSession();  				Transaction transaction = session.beginTransaction();  				//获得持久态对象  				Customer customer = session.get(Customer.class,1L);  				customer.setCust_name("王宝强");  				//session.update(customer);//没有手动调用update方法,但是也可以更新数据库  				transaction.commit();  				session.close();  			}    	1.4 Hibernate的一级缓存  		1.4.1 缓存的概述  			1.4.2 Hibernate 的一级概述:  			Hibernate框架本身的性能不是很好,但是Hibernate提供了很多的性能优化的手动,比如,缓存.    			Hibernate框架提供了两个级别的缓存:    			一级缓存: 称为Session级别的缓存.因为一级缓存的生命周期与session一致的.自带的,不可卸载的.(由Session中一系列的Java集合构成的)    			二级缓存: 称为SessionFactory级别的缓存.需要进行配置的缓存的插件.默认不开启的.ehche == redis    			ps : 除了删除,增改查和数据库打完交道,都会往一级缓存中留一份.  				但是session只要关闭,一级缓存的数据全部清空.    			原因: 一级缓存的存在    			原理:  				session.get(Customer.class, 1L)  // 去数据库查询,查完了之后放在一级缓存中  										一级缓存  											存储区  												放一份  											快照区  												备份一份    				ct.setCust_name("rose1234");   // 去一级缓冲中的存储区修改了内容,但是快照区不修改  										一级缓存  											存储区  												修改了  											快照区  												以前的      				tx.commit();      // 去一级缓存中,将存储区和快照区的数据都拿出来对比  							一致: 什么都不做  							不一致: 自动发送update语句做数据的数据更新    			1.4.3 证明一级缓存的存在:  				public void demo1() {  					Session session = HibernateUtils.ipenSession();  					Thransaction transaction = session.beginTransaction();    					Customer customer = new Customer();  					customer.setCust_name("好强");    					Serializable id = session.save(customer);  					session.get(Customer.classmid);//没有发烧SQL语句.    					Customer customer1 = session.get(Customer.class,1L);//发送SQL语句去查询  					System.out.println(customer1);  					Customer customer2 = session.get(Customer.class,1L);//不发送SQL语句  					System.out.println(customer2);    					transaction.commit();  					session.close();    				}    		一级缓存区里面有缓存区和快照区,当把数据重新设置以后,更新缓存区,进行commit提交,会对比一级缓冲区里面的缓存区和快照区是否一致,  		如果一致,则不更新数据库;如果不一致,则重新存储到快照区,并更新数据库.    		1.4.5 一级缓存的管理的方法 : 清空一级缓存的数据  			clear,evict,close 管理一级缓存的相关的方法.  			clear 可以清空一级缓存的所有数据.  			evict 可以清空一级缓存的某一个对象的数据.    	1.5 Session的绑定(ThreadLocal)  		1.5.1 Hibernate中设置与当前线程绑定的session的使用  		<!-- 设置与当前线程绑定的session -->  		<property name="hibernate.current_session_context_class">thread</property>    	1.6	Hibernate的其他的API  		在hibernate中,查询批量数据的方式:  				Query方式 : 如果是使用这种方式做查询,又被称作为HQL查询.  				Criteria方式 : 如果是使用这种方式做查询,又被称作为QBC查询.    		1.6.1 Query : HQL查询  			接收一个HQL进行查询 : HQL-Hibernate Query Language Hibernate查询语言,与SQL语言语法很相似的一个语言.面向对象.Query接口,HQL面向对象的查询.查询都是对象.  				@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();  			}    		1.6.2 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();  			}