Hibernate框架自学笔记

一、Hibernate

    书中配置方法:
        在eclipse中部署Hibernate开发环境
        在线安装方式:
            (1)运行Eclipse,选择主菜单Help--Install New Software选项
            (2)输入地址:http://download.jboss.org/jbosstools/mars/stable/updates/
            (3)选择相关功能:
                JBoss Tools 4.3.0.Final下的Hibernate Tools选项
                单机next选项
JavaEE三层结构:
    1、web层,struts框架。
    2、service层:spring框架
    3、dao层:hibernate框架 
        (1)对数据库进行crud操作
MVC思想:
    1、m:模型
    2、v:视图
    3、c:控制器
hibernate概述
    1、什么是框架:
       (1)写一个程序,使用框架后, 帮我们实现一部分功能,使用框架的好处就是少些一部分代码实现功能
       
    2、什么是hibernate框架
        (1)hibernate框架应用在javaee三层接口中dao层框架
        (2)在dao层里做对数据库crud操作,使用hibernate实现crud操作,
            hibernate底层代码就是jdbc,hibernate对jdbc进行封装,
            使用hibernate的好处:
                不需要写复制的jdbc代码,不需要使用写sql语句。
                
        (3)hibernate是一个开源的轻量级的框架
        (4)hibernate版本,主要使用Hibernate5.x
    3、什么是orm思想
        1、hibernate使用orm思想对数据库进行crud操作,
        2、javabean:实体类
        3、orm:Object  relational  mapping  对象关系映射
            (1)描述:
                让实体类和数据库进行一一对应关系
                    让实体类首先和数据库表对象
                    让实体类属性和表里面字段对象
                不需要直接操作数据库,而操作表对应实体类对象
hibernate入门
    1、搭建hibernate环境
        (1)需要导入的jar包,jpa,required
            因为使用hibernatehibernate时候,有日志信息输出,hibernate本身没有日志输出的jar包,
            导入其他日志的jar包,
            不要忘记还有mysql驱动的jar
        (2)创建实体类
            使用hibernate的时候,不需要自己手动创建表,hibernate会自动创建表
        (3)配置实体类和数据库表一一对应关系(映射关系)
            使用配置文件实现映射关系
                1.创建xml格式的配置文件
                    映射配置文件名称和位置没有固定要求
                    建议:在实体类所在包里面创建,实体类名称.hbm.xml
                2.配置文件是xml格式,在配置文件中首先引用xml约束。
                     eg:
                        <!DOCTYPE hibernate-mapping PUBLIC 
                        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
                3.配置映射关系
                    eg:
                        <!DOCTYPE hibernate-mapping PUBLIC 
                            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
                            
                        <hibernate-mapping>
                        	<!-- 1配置类和表对应 
                        		class标签
                        			name属性:实体类全路径,
                        			table属性:数据库表名称
                        	-->
                        	<!-- 要写全路径 -->
                        	<class name="cn/itcast.entity.User" table="tbl_user">
                        		<!-- 2配置实体类id和表id对应
                        			hibernate要求实体类有一个属性唯一值
                        			hibernate要求表有字段作为唯一值
                        		 -->
                        		 <!-- id标签
                        		 	name 属性:实体列里面id属性名称
                        		 	column属性:最终生成的表里面字段名称
                        		  -->
                        		<id name="id" column="id">
                        			<!-- 设置数据库表id增长策略 -->
                        			<!-- native:生成id值计时主键自动增长 -->
                        			<generator class="native"></generator>
                        		</id>
                        		<!-- 配置其他的属性和表字段对应 -->
                        		<property name="name" column="name"></property>
                        		<property name="password" column="password"></property>
                        		<property name="email" column="email"></property>
                        	</class>
                        </hibernate-mapping>
                 
                4. 创建hibernate的核心配置文件
                    (1)核心配置文件格式xml,但是核心文件名称和位置是固定的
                    -位置:必须在src下面
                    -名称:必须hibernate.cfg.xml
                    (2)引入dtd约束
                        <!DOCTYPE hibernate-configuration PUBLIC
                        	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                        	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
                    (3)hibernate操作过程中,只会加载核心配置文件,其他的配置文件不会加载
                        第一部分:配置数据库信息
                            
                        第二部分:配置hibernate信息
                        第三部分,把映射文件放到核心配置文件中
                        eg:
                            <?xml version="1.0" encoding="UTF-8"?>
                                <!DOCTYPE hibernate-configuration PUBLIC
                                	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
                                <hibernate-configuration>
                                	<session-factory>
                                		<!-- 第一部分:配置数据库信息 -->
                                		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
                                		<property name="hibernate.connection.url">jdbc:mysql:///jsp_db</property>
                                		<property name="hibernate.connection.username">root</property>
                                		<property name="hibernate.connection.password">root</property>
                                		<!-- 第二部分:配置hibernate信息 可选 -->
                                		<!-- 输出底层sql语句 -->
                                		<property name="hibernate.show_sql">true</property>
                                		<!-- 输出底层sql语句格式 -->
                                		<property name="hibernate.format_sql">true</property>
                                		<!-- hibernate帮创建表,需要配置之后
                                			update:如果已经有此表会进行更新,没有的话自动创建。
                                		 -->
                                		<property name="hibernate.hbm2ddl.auto">update</property>
                                		<!-- 配置数据库方言	在mysql会用分页使用关键字:limit,只能使用mysql里面。在Oracle数据库分页使用rownum
                                			让hibernate框架识别不同数据库的语句
                                		 -->
                                		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
                                		
                                		<!-- 第三部分 把映射文件放到核心配置文件中 -->
                                		<mapping resource="cn/itcast/entity/User.hbm.xml"/>
                                	</session-factory>
                                </hibernate-configuration>
    2、实现添加操作:
        第一步:加载hibernate核心配置文件
        第二步:创建SessionFactory对象
        第三部:使用SessionFactory创建Session对象
        第四步:开启事务
        第五步:写具体逻辑crud操作
        第六步:提交事务
        第七步:关闭资源
        eg:
            //第一步:加载hibernate核心配置文件
    			//到src下面找到名称是hibernate.cfg.xml
    		Configuration cfg=new Configuration();
    		cfg.configure();//加载配置文件
    		
           // 第二步:创建SessionFactory对象
    			//读取hibernate核心配置文件内容,在此过程中,
    			//他会在数据库里根据映射关系在数据库中创建表
    		SessionFactory sessionFactory=cfg.buildSessionFactory();
    		//第三部:使用SessionFactory创建Session对象
    	    //类似于连接
    	    Session session=sessionFactory.openSession();
           //第四步:开启事务
    	    Transaction tx= session.beginTransaction();
           //第五步:写具体逻辑crud操作
    	    User user=new User();
    	    user.setName("小王");
    	    user.setPassword("haha");
    	    user.setEmail("666");
    	    session.save(user);
           //第六步:提交事务
    	    tx.commit();
           //第七步:关闭资源
    	    session.close();
    	    sessionFactory.close();
            
    3、Hibernate配置文件详解
        
        Hibernate映射配置文件
            1.映射配置文件名称和位置没有固定要求;
            2.映射配置文件中,标签name属性值写实体类相关内容
                (1)class标签name属性值为实体类全路径
                (2)id标签和property标签name属性值为实体类属性名称
            3.id标签和property标签中 column属性可以省略,省略后自动生成和name一样的名字
            4.在property标签中type属性,设置生成表字段的类型,自动生成对应类型
            
        Hibernate核心配置文件
            1.配置写位置,必须在session-factory标签内
            2.配置三部分要求
                (1)数据库部分
                (2)hibernate部分是可选的
                (3)映射文件是必须的,可引用多个配置文件
Hibernate核心api:
    1、Configuration
            
    	(1)到src下面找到名称hibernate.cfg.xml配置文件,创建对象,把配置文件放到对象里面
    	    eg:
    	        Configuration cfg=new Configuration();
	        	cfg.configure();//加载配置文件
	        	
    2、SessionFactory
    
        (1)使用configuration对象创建sessionFactory对象
            1.创建SessionFactory过程中会:
                -根据核心配置文件在,有数据库配置,映射文件部分,到数据库里面根据映射关系把表创建
                eg:
                    SessionFactory sessionFactory=cfg.buildSessionFactory();
        (2)创建SessionFactory过程中,耗费资源
            在hibernate操作中,建议一个项目一般创建一个SessionFactory对象
            
        (3)实现
            (1)写工具类,写静态代码块,在类加载时执行,执行一次
            eg:
                public class hibernateUtils {
            	 static Configuration cfg=null;
            	 static SessionFactory sessionFactory=null;
            	//静态代码块
            		static {
            			//加载核心配置文件
            			cfg=new Configuration();
            			cfg.configure();
            			sessionFactory=cfg.buildSessionFactory();
            		}
            		public static SessionFactory getsessionFactory() {
            			return sessionFactory;
            		}
            }
            
            (2)
    
    3、Session
    
        (1)session类似于jdbc中connection
        (2)调用session里面不同的方法实现crud操作
            1.添加save方法;
            2.修改update方法;
            3.删除delete方法;
            4.根据id查询get方法;
        (3)session对象单线程对象,表示session对象不能共用,只能自己使用 
         
    4、Transaction
        (1)事务对象;
            Transaction tx= session.beginTransaction();//开启
        (2)事务提交和回滚方法
            tx.commit();
            tx.rollback();//回滚
        (3)事务的概念
            1.事务的四个特性:
                原子性,一致性,隔离性,持久性
解决配置文件没有提示问题
    1、可以上网
    2、将约束文件引入到eclipse中
实体类编写规则
        1、实体类属性都是私有的;
        2、私有属性使用公开的setget方法操作
        3、要求实体类里面有属性作为唯一值
        4、实体类属性建议不适用基本数据类型,使用基本数据类型对应的包装类
            (1)八个基本数据类型对应的包装类
                -Int---Integer
                -char--Character
                -其他的都是首字母大写,比如double--Double
            (2)比如,表示学生的分数,加入int score;
            -比如学生的了0分,int score=0;
            -如果表示学生没有参加考试,int scoure=0;不能准确表示学生是否参加考试
                解决:
                    使用包装类可以,等于null
hibernate主键生成策略
        1、hibernate乔秋实体类里面有一个属性作为唯一值,对应表主键,
            主键可以不同生成策略
        2、hibernate主键生成策略有很多值:
            eg:
                <generator class="assigned" />
        3、在class属性里面有值,
            主要两个
                (1)natice:根据使用的数据库,自动选择。自动加一
                (2)uuid:自动生成32位16字符串,uuid值
            uuid:
                (1)使用uuid生成策略,实体类id属性类型必须为字符串
                (2)配置部分携程uuid值
实体类操作
    (1)crud操作
        1.添加操作:
            eg:
                User user=new User();
        	    user.setName("小王");
        	    user.setPassword("haha");
        	    user.setEmail("666");
        	    session.save(user);
        2.根据id查询:
            User user=session.get(User.class,1)
        3.修改
            eg:
                //修改
        		//修改id=339记录中name的值
        		//1、根据id进行查询
        		User user= session.get(User.class, 339);
        		//2、向返回的user对象里面设置修改后的值
        		user.setName("修改后");
        		//3、调用session里的修改方法
        		session.update(user);
        		tx.commit();
        		session.close();
        		sessionFactory.close();
        4、删除
            eg:
                //删除
        		//方法1:根据id查询对象
        		User user=session.get(User.class, 2);
        		session.delete(user);
        		//方法2:
        		User user=new User();
        		user.setId(3);;
        		session.delete(user);
        		
    (2)实体类对象状态
        1.实体类状态有3种状态
            (1)瞬时态:
                对象里面没有id值,对象与session没有关联 eg:save
            (2)持久态:
                对象里有id值,对象与session有关联 eg:get
            (3)托管态
                对象里面有id值,对象与session没有关联 eg:update
        2.操作实体类的方法
            savrOrUpdate方法:
                实体类对象状态是瞬时态的话做添加
                实体类对象状态时托管态做修改
                实体类对象状态是持久态的话做修改
hibernate的一级缓存
    1、什么是缓存: 
        (1)数据存到数据库里面,数据库本身就是文件系统,要使用流的方式操作文件,效率低,
            解决方法:
                1.把数据存到内存里面,不需要使用流方式,可以直接读取内存中数据
        (2)吧数据放到内存中,提高读取效率
        
    2、Hibernate缓存:
        (1)hibernate框架中提供很多优化方式,Hibernate的缓存就是一个优化方式
        (2)hibernate缓存特点:
            第一类,hibernate的一级缓存
                1.hibernate的一级级缓存默认就是打开的
                2.hibernate的一级缓存存在使用范围,是session范围(从session创建到session关闭的范围)
                3.hibernate的一级缓存中,储存数据必须是持久态数据
            第二类 hibernate的二级缓存
                1.目前已经不适用了,替代技术redis
                2.二级缓存默认不是打开的,需要配置
                3.二级缓存使用范围,是sessionFactory范围
                
    3、验证一级缓存的存在
        验证方式
            1.首先根据id=1查询,返回对象
            2.再根据id=1的查询,返回对象
    
    4、一级缓存的特性
        (1)持久态自动更新数据库
        (2)执行过程:
Hibernate事务代码规范写法
    try{
        开启事务
        提交事务
    }catch{
        回滚事务
    }finally{
        关闭事务
    }
        
        eg:
        public  void testget() {
		Transaction tx=null;
		SessionFactory sessionFactory=null;
		Session session=null;
		try {
			 sessionFactory=hibernateUtils.getsessionFactory();
			 session=sessionFactory.openSession();
			tx=session.beginTransaction();
			User user=session.get(User.class, 1);
			System.out.println(user.getName());
			tx.commit();
		} catch (Exception e) {
			// TODO: handle exception
			tx.rollback();
		}finally {
			
			session.close();
			sessionFactory.close();
		}
Hibernate绑定session
1、session类似于jdbc的connection,之前web阶段学过threadLocal
2、帮实现与本地线程绑定session
3、获取与本地线程session
    (1)在hibernate核心配置文件中配置
        eg:
            <!-- 在hibernate核心配置文件中配置线程 --> 
             <property name="hibernate.current_session_context_class">thread</property>
    (2)调用sessionFactory里面的方法得到
        //提供返回与本地线程绑定的session方法
		public static Session getSession() {
			return sessionFactory.getCurrentSession();
		}
		
		public  void testget() {
		Transaction tx=null;
		SessionFactory sessionFactory=null;
		Session session=null;
		try {
			session=hibernateUtils.getSession();
			tx=session.beginTransaction();
			User user=session.get(User.class, 1);
			System.out.println(user.getName());
			tx.commit();
		} catch (Exception e) {
			// TODO: handle exception
			tx.rollback();
		}
		
		//绑定本地线程session不需要关闭session
hibernate的其他api(查询)
    1、Query对象:
        (1)使用query对象,不需要写sql语句,但是写hql语句
            hql:hibernate query language,hibernate提供查询语句
            hql和sql的区别:
                -使用sql操作表和表字段
                -使用hql操作实体类和属性
        (2)查询所有hql语句
            from 实体类名称
        (3)Query对象使用
            1.常见Query对象
            2.调用query对象里面的方法
            
        eg:
            Query query=session.createQuery("from User");
			//2调用query对象里面的方法
			List<User> list=query.list();
			for(User user:list) {
				System.out.println(user);
			}
			
    2、Critica对象:
        (1)使用这个对象查询操作,但是使用这个对象的时候。
        不需要写语句,直接调用方法实现
        (2)实现过程
            1.创建criteria对象
            2.使用此对象得到结果
        eg:
            	Criteria criteria=session.createCriteria(User.class);
    			List<User> list=criteria.list();
    			for(User user:list) {
    				System.out.println(user);
    			}
    3、SQLQuery对象:
        (1)使用hibernate的时候,也可以使用底层sql语句。
        
        (2)实现过程:
            1.创建对象
            2.调用方法
        eg:
            	//查询Critica对象对象
    			//1创建Critica对象对象
    			SQLQuery sqlQuery=session.createSQLQuery("select * from tbl_user");
    			List<Object[]> list=sqlQuery.list();
    			System.out.println(list.size());
    			for(Object[] objects:list) {
    				
    				System.out.println(Arrays.toString(objects));
    			}
    			//或者!!
    			//设置list为对象形式
    			sqlQuery.addEntity(User.class);
    			List<User> list2=sqlQuery.list();
    			for(User user:list2) {
    				System.out.println(user);
    			}
表与表之间关系
    1、一对多关系
        (1)分类和商品关系,一个分类里有多个商品,一个商品只能属于一个分类
        (2)一对多建表:
            通过外键建立关系
            在多的那一方建立字段,作为外键,与一的主键绑定在一起
    2、多对多
        (1)订单和商品关系,一个订单里面有多个商品,一个商品属于多个订单
        (2)一个用户有多个角色,一个角色有多个用户
        (3)多对多建表:
            创建第三张表来维护其中的关系
            至少有两个字段作为外键,指向两个表主键
    
    3、一对一
        (1)一个男人只能有一个妻子
Hibernate的一对多操作
    1、一对多映射配置
        第一步:创建两个实体类
        第二步:让两个实体类之间相互表示
            (1)在客户实体类里面表示多个联系人
                -一个客户里面有多个联系人
                	private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
            (2)在联系人实体类里面表示所属客户
                一个联系人只能属于一个客户
                    private Customer customer;
        第三部:配置映射关系
            (1)一般情况下,有几个实体类就要写几个映射文件
            (2)映射最基本配置完成
            (3)在映射文件中,配置一对多关系
            ---在客户映射文件中
            eg:
                 <!-- 在客户映射文件中,表示所有联系人
                	使用set标签表示所有联系人
                	set标签里面name属性:属性值写在客户实体类表示联系人的set集合名称
                	
                 -->
                <set name="setLinkMan" table="LINKMAN" inverse="false" lazy="true">
                    <!-- key:hibernate机制:双向维护外键,在一和多哪一方都需要配置外键
                    	key表示外键
                     -->
                    <key>
                        <column name="CID" />
                    </key>
                    <!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
                    <one-to-many class="cn.itcast.entity.LinkMan" />
                </set>
                ---在联系人映射文件中
                   <!-- 表示联系人所属客户
                    	Name属性:因为在联系疼实体类使用了customer对象表示,写customer名称
                    	class属性:customer全路径
                    	column属性:外键的名称
                    	 -->
                    <many-to-one name="customer" class="cn.itcast.entity.Customer" fetch="join">
                        <column name="CUSTOMER" />
                    </many-to-one>
    2、一对多的级联操作
        级联操作:
            (1)级联保存
                1.添加一个客户,为这个客户添加多个联系人
            (2)级联删除
                1.删除某个客户,这个客户里面的所有联系人也都删除
        一对多级联保存:
            (1)添加客户,为这个客户添加一个联系人
                方法1:
                    eg:
                        Customer customer=new Customer();
            			customer.setCustName("name1");
            			customer.setCustLevel("level1");
            			customer.setCustSource("source1");
            			customer.setCustPhone("111");
            			customer.setCustMobile("mobule1");
            			
            			LinkMan linkMan=new LinkMan();
            			linkMan.setLkm_name("lucy");
            			linkMan.setLkm_gender("男");
            			linkMan.setLkm_phone("111");
            			//2在客户里表示所有联系人,在联系人表示客户
            			//建立客户对象和联系人对象的关系
            			//2.1把联系人对象放到客户实体类set集合里面
            			customer.getSetLinkMan().add(linkMan);
            			//2.2吧客户对象放到联系人里面
            			linkMan.setCustomer(customer);
            			//3保存到数据库
            			
            			session.save(customer);
            			session.save(linkMan);
            			tx.commit();
                方法2:简化写法
                    根据客户添加联系人
                    第一步:
                        在客户映射文件中进行配置:
                        在客户映射文件里面set标签进行配置
                        <set name="setLinkMan" table="LINKMAN" cascade="save-update" >
                    第二步:
                        创建客户和联系人对象,只需要把联系人放到客户里面就可以了。
                        最终只要保存客户联系人就可以了。
                        eg:
                            Customer customer=new Customer();
                			customer.setCustName("name2");
                			customer.setCustLevel("level2");
                			customer.setCustSource("source2");
                			customer.setCustPhone("222");
                			customer.setCustMobile("mobule2");
                			
                			LinkMan linkMan=new LinkMan();
                			linkMan.setLkm_name("小红");
                			linkMan.setLkm_gender("女");
                			linkMan.setLkm_phone("222");
                			//2把联系人放到客户里面
                			customer.getSetLinkMan().add(linkMan);
                			//3保存客户
                			session.save(customer);
                	
        一对多级联删除        
            (1)删除某个客户,把客户里面的所有的联系人删除
            (2)实现:
                第一步:
                        在客户映射文件中进行配置:
                        在客户映射文件里面set标签进行配置
                        <set name="setLinkMan" table="LINKMAN" cascade="delete,save-updata" >
                第二步:
                    直接删除客户
                         //删除
                		Customer customer=session.get(Customer.class, 2);
		                session.delete(customer);
		                
		一对多级联修改
		     eg:
		        //修改操作
    			//1根据id查询联系人,根据id查询客户
    			Customer customer= session.get(Customer.class, 1);
    			LinkMan linkMan= session.get(LinkMan.class, 1);
    			//2设置持久态对象值
    			//把联系人放到客户里
    			customer.getSetLinkMan().add(linkMan);
    			//把客户放到联系人里
    			linkMan.setCustomer(customer);
        inverse属性
            (1)因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题。
            (2)解决方式:
                让其中的一方不维护外键,
                --让一对多里面,让其中一的一方放弃外键的维护。
            (3)具体实现:
                在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性
                eg:    
                     <!-- 
                     	inverse属性默认值:
                     			false不放弃关系维护
                     			true表示放弃关系维护
                      -->
                    <set name="setLinkMan" table="LINKMAN" cascade="save-update,delete" inverse="true" >
Hibernate的多对多操作
        1、多对多映射配置
            以用户和角色为例
                第一步 创建实体类,用户和角色
                
                第二步 让两个实体类互相表示
                    (1)一个用户里面要表示所有角色,set集合
                    (2)一个角色里面有多个用户,set集合
                  eg:  private Set<User> setuser=new HashSet<Us
                第三步 配置映射关系
                    (1)基本配置
                    (2)配置多对多关系
                        在用户里面表示所有角色,使用set标签
                            <set name="setRole" table="ROLE" inverse="false" lazy="true">
                                <key>
                                    <column name="USER_ID" />
                                </key>
                                <many-to-many class="cn.itcast.manytomany.Role" column="ROLE_ID" />
                            </set>
                        在角色里面表示所有用户,使用set标签
                            <set name="setuser" table="USER" inverse="false" lazy="true">
                                <key>
                                    <column name="ROLE_ID" />
                                </key>
                                <one-to-many class="cn.itcast.manytomany.User" />
                            </set>
                            
                    **其中table属性表示第三张表名称
                        key标签里面的column配置当前映射文件在第三张表外键名称
                    **many-to-many中 class为角色实体类全路径,column表示角色在第三张表外键名称
                第四步 在核心配置文件中引入映射文件
                    <mapping resource="cn/itcast/manytomany/Role.hbm.xml"/>
                    <mapping resource="cn/itcast/manytomany/User.hbm.xml"/>
        
        2、多对多级联保存     
            
            根据用户保存角色
                第一步 在用户配置文件中set标签进行配置,cascade
                <set name="setRole" table="USER_ROLE" inverse="false" cascade="save-update" lazy="true">
                第二步 写代码实现
                    (1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以
                    //对多对级联添加
    				//添加两个用户,为每个用户添加两个角色
    				//1创建对象
    				User user=new User();
    				user.setUser_name("1");
    				user.setUser_password("1");
    				
    				User user2=new User();
    				user2.setUser_name("2");
    				user2.setUser_password("2");
    				
    				Role r1=new Role();
    				r1.setRole_name("总经理");
    				r1.setRole_memo("123");
    				
    				Role r2=new Role();
    				r2.setRole_name("秘书");
    				r2.setRole_memo("234");
    				
    				Role r3=new Role();
    				r3.setRole_name("保安");
    				r3.setRole_memo("5667");
    				
    				//2建立关系
    				
    				user.getSetRole().add(r1);
    				user.getSetRole().add(r2);
    				
    				user2.getSetRole().add(r2);
    				user2.getSetRole().add(r3);
    				
    				session.save(user);
    				session.save(user2);
                    
                
        多对多级联删除
            第一步 在set标签配置,cascade值delete
                cascade="save-update,delete"
            第二步删除用户
                 session.delete(session.get(User.class, 1));
            **很少用,因为直接把角色都删除了
                
        多对多维护第三张表
            (1)用户和角色多对多关系,维护关系通过第三张表维护
                eg:
            (2)让某个用户有某个角色
                    第一步 根据id查询出用户和角色
                    第二步 把角色放到用户里
                        把橘色对象放到用户set集合
                   eg:
                        User user= session.get(User.class, 1);
        				Role role=session.get(Role.class, 1);
        				
        				//2把角色放到用户的set集合里面
        				user.getSetRole().add(role);
        				
            (3)让某个用户没有某个角色
                    第一步 根据id查询出用户和角色
                    第二步 把角色放到用户里
                        把角色对象放到用户set集合
                        
                    eg:User user= session.get(User.class, 1);
        				Role role=session.get(Role.class, 1);
        				
        				//2从用户里面吧角色去掉
        				user.getSetRole().remove(role);
Hibernate查询方式;
    1、对象导航查询
        eg:根据id查询某个客户,再查询这个客户里面所有的联系人
         sessionFactory=hibernateUtils.getsessionFactory();
			session=sessionFactory.openSession();
			tx=session.beginTransaction();
			//根据cid=1客户,再查询这个客户里面所有联系人
			Customer customer= session.get(Customer.class,1);
			//在查询这个客户所有联系人
			//直接得到客户里面联系人的set集合
			Set<LinkMan> linkMans= customer.getSetLinkMan();
			System.out.println(linkMans.size());
			tx.commit();
        
    2、OID查询
        eg:根据id查询某一条记录,返回对象
        (1)调用session里面get方法查询
        Customer customer= session.get(Customer.class,1);
    
    3、hql查询
        eg:Query对象,写hql语句实现查询
        (1)hql:hibernate query language 一种查询语言,和sql相似
            区别:普通sql操作数据库表和字段,hql操作实体类和属性
        (2)常用的hql语句
            1.查询所有:
                Query query= session.createQuery("from Customer");
				List<Customer> list= query.list();
				
				for(Customer customer:list) {
					System.out.println(customer.getCid()+""+customer.getCustName());
				}
			2.条件查询:
			    条件查询语句写法:
			        from 实体类名称 where 实体类属性名称=? and 实体类属性名称 like ?
			        eg:
			            Query<Customer> query=session.createQuery("from Customer where CUSTNAME like ?");
        				//2.设置条件值
        				//向?里面设置值
        				//setParameter方法两个参数
        				//第一个参数:int类型是?位置,从0开始;
        				query.setParameter(0, %3%);
        				List<Customer> list= query.list();
        				
        				for(Customer customer:list) {
        					System.out.println(customer.getCid()+"::::"+customer.getCustName());
        				}

			3.排序查询
			    (1)hql排序语句:
			        from 实体类名称 + order by 实体类属性名称   asc/desc 
			        eg:
			            Query<Customer> query=session.createQuery("from Customer order by CID desc");
			    
			
			4.分页查询
			    **开始位置计算公式:(当前页-1)*没页记录数
                mysql实现:select * from cutomer LIMIT 0,8
                在hql中:
                    在hql操作中,不能使用LIMIT,hibernate的Query对象中封装了两个方法,
                        可用于实现分页操作
                eg:
                    //1.创建一个Query对象
    				Query<Customer> query=session.createQuery("from Customer");
    				//2.设置分页数据
    				//设置开始位置
    				query.setFirstResult(0);
    				//设置每页记录数
    				query.setMaxResults(1);
    				//调用方法得到结果
    				List<Customer> list= query.list();
    				
    				for(Customer customer:list) {
    					System.out.println(customer.getCid()+"::::"+customer.getCustName());
    				}
                
            5.投影查询
                查询的不是所有字段值,而是部分字段的值
                sql:select custName FROM customer
                hql:select 实体类属性名称1,实体类属性名称2 from 实体类名称
                **select 后面不能写*,不识别
                eg:
                    Query<Object> query=session.createQuery("select cid from Customer");
    				List<Object> list=query.list();
    				for(Object object : list) {
    					System.out.println(object);
    				}
            6.聚集函数的使用:
                (1)常用的聚集函数:count、sum、avg、max、min
                (2)hql聚集函数语句写法
                    1.查询表记录数
                        select count(*) from 实体类名称
                        eg:
                           Query<Object> query=session.createQuery("select count(*) from Customer");
            				Long long1=(Long)query.uniqueResult();
            				int count=long1.intValue();
            				System.out.println(count);
            7.HQL多表查询
                1.HQL内连接
                    (1)from Custtomer c inner join c.setLinkMan
                    eg:
                    //返回的是数组
                         Query<Object> query=session.createQuery("from Customer c inner join c.setLinkMan");
		                List<Object> list= query.list();
		        2.迫切内连接
		            和HQL内连接区别:
		                使用内连接返回list中每部分是数组,破解内连接返回list是对象
                    from Custtomer c inner join fetch c.setLinkMan
                3.HQL左外连接
                    from Custtomer c left outer join c.setLinkMan
                4.迫切左外连接
                    from Custtomer c left outer join fetch c.setLinkMan
                    迫切的左外连接返回list每部分是对象

        (3)使用hql查询操作需要使用Query对象
            1.创建一个Query对象,写hql语句
            2.调用query对象里面的方法得到结果
    
    
    4、QBC查询  
        eg:Criteria对象
        (1)查询所有
            //1创建Criteria对象
			Criteria criteria=session.createCriteria(Customer.class);
			
			List<Customer> list=criteria.list();
			
			for (Customer customer : list) {
				System.out.println(customer.getCid()+":::"+customer.getCustName());;
			}
		(2)条件查询
		    eg:
		        //QBC条件查询
				//1创建Criteria对象
				Criteria criteria=session.createCriteria(Customer.class);
				//2使用方法设置条件值
				//首先使用add方法,表示设置条件值
				//在add方法里面使用类的方法实现条件设置
				criteria.add(Restrictions.eq("cid", 3));
				List<Customer> list=criteria.list();
				
				for (Customer customer : list) {
					System.out.println(customer.getCid()+":::"+customer.getCustName());;
				}
				criteria.add(Restrictions.like("custName", "%2%"));
				
        (3)排序查询
            eg:
                criteria.addOrder(Order.asc("cid"));//升序
        (4)分页查询
            **开始位置计算公式:(当前页-1)*没页记录数
            eg:
                //设置分页数据
				criteria.setFirstResult(0);
				//设置开始位置
				criteria.setMaxResults(3);
				//每页显示记录数
        (5)统计查询
               eg:
              criteria.setProjection(Projections.rowCount());//设置参数
				Object object= criteria.uniqueResult();
				Long long1=(Long)object;
				int count=long1.intValue();
				
        (6)离线查询
            eg:
                //创建对象
				DetachedCriteria detachedCriteria=DetachedCriteria.forClass(Customer.class);
				//最终执行时候才需要session
				Criteria criteria=detachedCriteria.getExecutableCriteria(session);
				
				List<Customer> list=criteria.list();
				
				for (Customer customer : list) {
					System.out.println(customer.getCid()+":::"+customer.getCustName());;
				}
				
                
    5、本地sql查询    
        eg:用SQLQuery对象,使用普通sql实现查询
Hibernate检索策略
    检索策略的概念
        (1)立即查询
            根据id查询,调用get方法,一调用get方法马上发送语句查询数据库
            eg:Customer customer=session.get(Customer.class, 2);
        (2)延迟查询
            根据id查询,还有load方法,调用load方法不会马上发送语句查询数据。
            只有得到对象里面的值的时候才会发送语句查询数据库
            eg:Customer customer=session.load(Customer.class, 1);
                //调用Load方法之后,不会马上发送sql语句,得到对象里面不是id的其他值的时候才会发送语句
            eg:
                //根据cid=1客户查询该客户里面所有联系人
				Customer customer=session.load(Customer.class, 1);
				//Customer customer=session.get(Customer.class, 2);
				//再查询这个客户里面所有联系人
				//直接得到客户里面联系人的set集合
				//得到set集合 没有发送语句
				
				Set<LinkMan> linkMans=customer.getSetLinkMan();
				//发送语句
				System.out.println(linkMans.size());
				
            延迟查询分成两类
                1.类级别延迟
                    根据id查询返回实体类对象,调用load方法不会马上发送语句
                2.关联级别延迟
                    查询某个客户,再查询该客户所有联系人。
                    查询客户的所有联系人的过程是否需要延迟。
                    这个过程就是关联级别延迟
            
            关联级别延迟操作
                在映射文件中进行配置实现 
                    在set标签上使用属性:
                    (1)fetch:值select
                    (2)lazy:值
                        -true:延迟(默认)
                        -false:不延迟
                            调用get之后,2条sql语句
                        -extra:及其延迟
                            要什么值给什么值的查询,不做多余查询
Hibernate批量抓取
场景:要查询所有客户,返回list集合,我想得到每个客户中的联系人。
在客户的映射文件中,set标签配置
batch-size值,值越大发送sql语句越少
<set batch-size="10">
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值