• hibernate


    什么是Hibernate框架:
    1、hibernate框架应用在javaee三层结构中dao层框架
    2、在dao层里面做对数据库crud操作,使用hibernate实现crud操作。hibernate底层代码就是jdbc,hibernate对jdbc进行封装,使用hibernate好处就是不需要写复杂的jdbc代码了,不需要写sql语句实现
    3、hibernate开源的轻量级框架
    ORM思想
    hibernate使用orm思想对数据库进行crud操作
    orm:object relational mapping 对象关系映射
    让实体类和数据库表进行一一对应关系
    让实体类首先和数据库表对应
    让实体类属性和表里面字段对应
    不需要直接操作数据库表而操作表对应实体类对象
    搭建hibernate环境
    1、导入jar包,lib目录下的required文件夹、mysql驱动、和外部日志jar包
    2、创建实体类

    public class User(){
    	/*hibernate要求实体类要有一个属性唯一的*/
    }
    

    3、使用hibernate不需要自己手动建表,hibernate会自动建表
    4、配置实体类和数据库一一对应关系(映射关系)

    使用配置文件实现映射关系
    1、创建XML格式的配置文件:映射配置文件名称和位置没有固定要求,一般建议在实体类所在的包里面创建,名字:实体类名称.xml
    2、配置文件是xml格式,在配置文件中首先引入xml约束

    <!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
    

    3、配置映射关系

    <hibernate-mapping>
    	<!--配置类和表对应
    		class标签
    		name属性:实体类全路径
    		table属性:数据库表名
    	-->
    	<class name="  " table="t_user">
    		<!--配置实体类id和表id对应
    			hibernate要求实体类有一个属性唯一值
    			hibernate要求表有字段作为唯一值
    		-->	
    		<!--id标签
    			name属性:实体类里面id属性名称
    			column属性:生成表字段名称
    		-->	
    		<id name="uid" column="uid">
    			<!--设置数据库表id增长策略
    				native:生成表id值是主键自动增长
    			-->
    			<generator class="native"></generator>
    		</id>
    		<!--配置其他属性和表字段对应
    			name属性:实体类属性名称
    			column属性:生成表字段名称
    		-->
    		<property name="属性名" column="生成表字段名称"></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-configuration>
    	<session-factory>
    		<!--配置数据库信息-->
    		       <!-- property 元素用于配置Hibernate中的属性
                键:值 
              -->
            <!-- hibernate.connection.driver_class : 连接数据库的驱动  -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <!-- hibernate.connection.username : 连接数据库的用户名 -->
            <property name="hibernate.connection.username">root</property>
            <!-- hibernate.connection.password : 连接数据库的密码 -->
            <property name="hibernate.connection.password">123</property>
            <!-- hibernate.connection.url : 连接数据库的地址,路径 -->
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedemo</property>
    		<!--配置hibernate信息,这部分是可选的-->
    		 <!-- show_sql: 操作数据库时,会 向控制台打印sql语句 -->
            <property name="show_sql">true</property>
            <!-- format_sql: 打印sql语句前,会将sql语句先格式化  -->
            <property name="format_sql">true</property>
            <!-- hbm2ddl.auto: 生成表结构的策略配置
                 update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构. 
                         如果存在表结构,并且表结构与实体一致,那么不做修改
                         如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
                 create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
                 create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
                 validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
              -->
            <property name="hbm2ddl.auto">update</property>
            <!-- 数据库方言配置 
             org.hibernate.dialect.MySQLDialect (选择最短的)
             -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            <!-- hibernate.connection.autocommit: 事务自动提交  -->
            <property name="hibernate.connection.autocommit">true</property>
            <!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
            <property name="hibernate.current_session_context_class">thread</property>
    		<!--把映射文件放到核心配置文件中-->
    		<mapping resource="com/it/a_hello/User.hbm.xml"/>
    	</session-factory>
    </hibernate-configuration>
    

    实现添加操作
    1、加载hibernate核心配置文件

    Configuration sfg = new Configuration();
    cfg.configure();
    

    2、创建SessionFactory对象

    SessionFactory sf = sfg.buildSessionFactory();
    

    3、使用SessionFactory创建session对象

    Session s = sessionFactory.openSession();
    

    4、开启事物

    Transation tx = s.beginTransation();
    

    5、写具有逻辑curd操作

    User user = new User();
    user.setUsername();
    user.setUserage();
    user.setUseradd();
    //调用session的方法实现添加
    s.save(user);
    

    6、提交事物

    tx.commit();
    

    7、关闭资源

    session.close();
    sessionFactory.close();
    

    Hibernate配置文件详解
    映射配置文件
    1、名称和位置没有固定要求
    2、映射问价那种,标签name属性值写实体类相关内容:class标签name属性值实体类全路径,id标签和property标签name属性值实体类属性名称
    3、id标签和property,column属性可以省略,省略默认的值和name的值一样
    4、property标签type属性,设置生成表字段的类型,自动生成对应类型
    核心配置文件
    1、核心配置写位置要求
    2、数据库部分必须的,hibernate部分可选,映射文件必须的
    3、位置.src下,文件名hibernate.cfg.xml
    hibernate核心api
    Configuration
    1、到src下面找到名称hibernate.cfg.xml文件,并加载
    SessionFactory
    Session
    Transation
    实体类的编写
    1、实体类里的属性是私有的
    2、私有属性要使用公开的get和set方法
    3、要求实体类有属性作为唯一值(一般用id值)
    4、实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类。
    Hibernate主键生成策略:
    1、要求实体类有一个属性作为唯一值,对应表主键,主键可以有不同生成策略
    2、主键生成策略有很多的值
    3、在class属性里面由值

    native:根据使用的数据库选择哪个值
    uuid:之前web阶段写代码生成uuid,hebernate会自动帮我生成uuid值
    使用uuid生成策略,实体类id属性必须是字符串类型
    

    实体类操作
    1、调用session的save方法实现添加
    2、根据id查询

    //调用session里面的get方法实现
    //调用工具类得到sessionFactory
    SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    //获取session
    Session session = sessionFactory.openSession();
    //开启事物
    Transaction tx = session.beginTransaction();
    //根据id查询
    User user = session.get(实体类的class, id的值);
    //提交事物
    tx.commit();
    //关闭
    session.close();
    sessionFactory.close();
    

    修改操作

    1、先根据id查找值
    //调用session里面的get方法实现
    //调用工具类得到sessionFactory
    SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    //获取session
    Session session = sessionFactory.openSession();
    //开启事物
    Transaction tx = session.beginTransaction();
    //修改操作
    //先根据id查询
    User user = session.get(实体类的class, id的值);
    //向返回的的user对象里面修改值
    user.setUsername();
    //调用session的update方法修改
    session.update(user);
    //提交事物
    tx.commit();
    //关闭
    session.close();
    sessionFactory.close();
    

    删除操作

    1、先根据id查找值
    //调用session里面的get方法实现
    //调用工具类得到sessionFactory
    SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    //获取session
    Session session = sessionFactory.openSession();
    //开启事物
    Transaction tx = session.beginTransaction();
    //修改操作
    //先根据id查询
    User user = session.get(实体类的class, id的值);
    //调用session的delete删除
    ---------------
    //方法一:根据id删除
    session.delete(user);
    //方法二:
    User user = new User();
    user.setUid(3);
    session.delete(user);
    -------------------
    //提交事物
    tx.commit();
    //关闭
    session.close();
    sessionFactory.close();
    

    实体类状态:
    1、瞬时态:对象没有id值,对象与session没有关联
    2、持久态:对象有id值,对象与session有关联
    3、托管态:对象有id值,但是与session没有关联
    实体类对象的方法:
    saveOrUpdate方法:实现添加、修改。实体类对象是瞬时态,做添加操作;托管态,做修改操作;持久态,做修改操作
    Hibernate的一级缓存:
    数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高。把数据存到内存中,不需要使用流方式,可以直接读取内存中的数据,提高读取效率。
    Hibernate框架提供了很多优化方式,hibernate缓存就是一个优化方式
    hibernate缓存特点:
    1、hibernate的一级缓存

    1、hibernate的一级缓存默认是打开的
    2、hibernate的一级缓存使用范围,是session范围,从session创建d到session关闭范围
    3、hibernate的一级缓存中,存储数据必须是持久态数据
    

    2、hibernate的二级缓存

    目前已经不使用了,替代技术:redis
    二级范围默认不是打开的,需要打开
    使用范围是sessionFactory范围
    

    hibernate事务操作
    什么是事务?
    事务特性
    不考虑隔离性产生问题:
    1、脏读
    2、不可重复读
    3、虚读
    事务隔离级别:mysql默认隔离级别:repeatable read
    Hibernate事务代码规范写法:

    代码结构:
    SessionFactory sessionFactory = null;
    Session session = null;
    Transation tx = null;
    try{
    	sessionFactory = HibernateUtils.getSessionFactory();
    	session = sessionFactory.openSession();
    	//开启事务
    	tx = session.beginTransation();
    	//增删改操作
    	//...
    	//提交事务
    	tx.commit();
    }catch(){
    	//回滚事务
    	tx.rollback();
    }finally{
    	//关闭
    }
    

    Hibernate绑定session
    1、session类似jdbc的connection
    2、帮实现与本地线程绑定session
    3、获取与本地线程session

    1、在hibernate核心配置文件中配置
    <property name="hibernate.current_session_context_class">thread</property>
    2、调用sessionFactory中的方法得到
    sessionFactory.getCurrentSession();
    
    得到与本地线程绑定的session
    session = HibernateUtils.getSessionobject();
    获取与本地线程绑定session的时候,关闭session报错,这个时候不需要手动关闭
    

    查询所有
    Query对象

    使用query对象,不需要写sql语句,但是写hql语句(hibernate query language Hibernate提供查询语句,这个hql语句和普通sql语句很相似)
    使用普通sql操作表和表字段,hql操作的是实体类和属性
    查询所有hql语句:form 实体类名称
    query对象使用:
    1、创建Query对象
    Query query = session.createQuery("from 实体类名");
    2、调用query对象里面的方法得到结果
    List<实体类名> list = query.list();
    

    Criteria对象

    使用这个对象查询操作,这个对象不需要写语句
    实现过程:
    1、创建Criteria对象
    Criteria c = session.createCriteria(实体类.class);
    2、调用方法得到结果
    List<...> list = c.list();
    

    SQLQuery对象

    使用hibernate也能调用底层sql实现
    SQLQuery sq = session.createSQLQuery("普通sql语句");
    //默认里面每部分数组结构
    List<Object[]> list = sq.list();
    //上面这种形式每部分是数组,现在想返回每部分是对象
    //返回每部分是对象形式,步骤如下:
    sq.addEntity(实体类名.class);
    List<实体类名> list = sq.list();
    

    多表操作
    表与表之间的关系
    1、一对多

    一对多映射配置
    	第一步:创建两个实体类(客户、联系人)
    	第二步:让这两个实体类之间互相表示
    			1、在客户实体类里面表示多个联系人 ,hibernate表示一个客户有多个联系人要求使用集合表示多的数据,使用set集合
    			2、在联系人实体类里面表示所属客户
    	第三步:配置映射关系
    			1、一般一个实体类对应一个映射文件
    			客户配置:
    			联系人配置:
    			2、把映射基本的配置完成
    			3、在映射文件中,配置一对多关系
    				在客户的映射文件中,表示所有联系人
    				<!--使用set属性表示所有联系人,name属性写实体类里面表示联系人set集合的名称-->
    				<set name="set集合名">
    					<!--一对多建表,有外键,hibernate机制,双向维护外键,在一和多那一方都配置外键-->
    					<key column="外键名"></key>
    					<one-to-many class="联系人实体类完整路径"/>
    				</set>
    				联系人映射文件中,表示所属客户
    				<many-to-one name="客户实体类名称" class="客户实体类全路径" colum="外键,和客户配置中key值一致"></many-to-one>
    	第四步:创建核心配置文件,把创建的配置文件引入到核心配置文件中
    
    ----------------------------------------------------------------------------------------------------------------------------------
    一对多级联操作
    级联保存
    	添加一个客户,为这个客户添加多个联系人
    	方式一:
    	1、创建客户和联系人对象
    	2、创建对象和联系人对象关系,把客户放联系人里面,把联系人放客户中
    	3、保存到数据库 session的save方法
    	方式二:
    	一般根据客户添加联系人
    	1、在客户映射文件进行配置
    		在set标签上进行配置,cascade属性代表级联保存
    		<set name="" cascade="save-update">
    	2、创建客户和联系人对象,只需要把联系人放到客户里面,最后只需要保存客户就可以
    级联删除
    	删除某一个客户,这个客户里面多有联系人删除	
    	删除某个客户,把客户里面所有联系人删除
    	1、在客户的映射文件set标签,进行配置
    	<set name="" cascade="delete">
    		如果级联保存的时候已经进行了配置,这个时候有多个值,多个值之间用英文逗号隔开delete,save-update
    	2、在代码中直接删除客户
    		根据id查询对象,根据session的delete删除
    一对多修改操作
    	1、根据id查询联系人,根据id查询客户
    	2、设置持久态对象值,把客户放联系人里面,把联系人放客户中
    inverse属性
    	因为hibernate是双向维护外键,在客户和联系人里面都需要维护外键,对性能有损耗,可以让其中一方不维护外键。
    	一对多里面,让其中一方放弃外键维护,让其中一的那方放弃维护
    	在set标签使用inverse属性配置
    	默认false代表不放弃关系维护,true放弃关系维护
    	<set inverse="true">
    

    2、多对多

    多对多映射配置
    	以用户和角色为例
    	1、创建实体类:用户和角色
    	2、让两个实体类互相表示
    		用户里面表示所有角色,使用set集合
    		一个角色有多个用户,使用set集合
    	3、配置映射关系
    		基本配置
    		配置多对多关系
    			在用户里面表示所有角色,用set标签
    			<set table="第三张表的名称">
    				<key column="配置当前映射文件在第三张表外键的名称"></key>
    				<many-to-many class="" column="角色在第三张表中外键名称"></many-to-many>
    			</set>
    			在角色里面表示所有用户,用set标签
    			<set table="第三张表的名称">
    				<key column="配置当前映射文件在第三张表外键的名称"></key>
    				<many-to-many class="" column="角色在第三张表中外键名称"></many-to-many>
    			</set>
    
    	4、在核心配置文件中引入映射文件
    
    多对多级联保存
    	1、在用户配置文件中set标签进行配置,cascade值save-update
    	2、创建用户和角色对象,把用户方用户里面,最终保存用户就可以
    多对多级联删除
    	1、在set标签进行配置,cascade值delete	
    	2、先查再删,session.delete();
    维护第三张表关系
    	用户和角色多对多关系,维护关系通过第三张表维护
    	让某个用户有某个角色
    	1、根据id查询用户和角色
    	2、把角色放到用户里面
    		把角色对象放到用户set集合
    	让某个用户没有某个角色
    	1、根据id查询用户和角色
    	2、从用户对象删除角色
    		在用户set集合删除角色对象
    

    3、一对一
    Hibernate查询方式
    1、对象导航查询
    根据id查询某个客户,再想查询客户里面所有的联系人

    SessionFactory sessionFactory = null
    Session session = null;
    Transaction tx = null;
    try{
    	sessionFactory = HibernateUtils.getSessionFactory();
    	session = sessionFactroy.openSession();
    	tx = session.beginTransaction();
    
    	//查询cid=1的客户,再查询这个客户里面所有联系人
    	Customer customer = session.get(Customer.class, 1);
    	//直接得到客户里面所有联系人的set集合
    	ser<linkMan> linkman = customer.getSetLinkMan();
    
    	tx.xommit();
    }catch(Exception e){
    	tx.rollback();
    }finally{
    	session.close();
    	sessionFactory.close();
    }
    

    2、OID查询
    根据id查询某一条记录,返回对象

    根据id查询记录,调用session里面的get方法
    	Customer customer = session.get(Customer.class, 1);
    

    3、hql查询
    Query对象,写hql语句实现查询

    hql:hibernate query language
    区别:普通sql操作数据库表和字段,hql操作实体类和属性
    常用的hql语句
    ·查询所有
    	Query query= session.createQuery("from 实体类名称");
    	List<实体类名称> list = query.list();
    ·条件查询
    	hql支持 实体类别名.实体类属性 的格式
    		from 实体类名称 实体类别名 where 实体类别名.实体类属性名称=? and 实体类别名.实体类属性名称=?
    	from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?
    	Query query = session.createQuery("...");
    	//设置条件值
    	query.setParameter(int i, Object obj);
    	//第一个参数是问号的位置,第二个参数具体参数值,问号的位置是0开始的
    
    	条件查询模糊查询
    	from Customer c where c.custName like ? //c是别名
    	_值_
    	%值
    
    ·排序查询
    	Query query = session.createQuery();
    	from 实体类名称 orber by 实体类属性名称 asc/desc
    
    ·分页查询
    	Query对象封装了两个方法实现分页操作:
    	//查询所有
    	Query query = session.createQuery("from Customer");
    	//设置分页数据
    	设置开始位置:
    	query.setFirstResult(0);
    	//设置每页显示的记录数
    	query.setMaxResult(4);
    	//调用方法调用最终的结果
    	List<Customer> list = query.list();
    
    ·投影查询
    	select 实体类属性名1,实体类属性名2 from 实体类名称
    	select后面不支持 * 号
    	Query query = session.createQuery();
    
    ·聚集函数使用
    	select count(*) from Customer
    	select sum(*) from Customer
    	select avg(*) from Customer
    	select max(*) from Customer
    	select min(*) from Customer
    	Query query = session.createQuery("");
    	调用方法得到结果
    	Object obj = query.uniqueResult();//注意,这个返回的Object类型实际是long类型,如果要转换成int类型,先要强转long类型,再转int类型
    	
    使用hql查询操作时候,使用Query对象实现
    1、创建Query对象,写hql语句
    2、调用query对象方法得到结果
    
    ·多表查询
    内连接查询hql语句写法
    	以客户和联系人为例
    	form 客户实体类 别名 inner join 别名.setLinkMan集合 //别名可以不要
    	from Customer c inner join c.setLinkMan;	
    
    左外连接
    	from Customer c left outer join c.setLinkMan
    	迫切左外连接:from Customer c left outer join fetch c.setLinkMan
    

    4、QBC查询
    Criteria对象

    使用qbc时候,不需要写语句,写方法就可以,使用qbc时候,操作实体类和属性
    1、创建Criteria对象
    2、调用方法
    
    ·查询所有
    	Criteria c = session.createCriteria(Customer.class);
    	List<Customer> list = c.list();
    
    ·条件查询
    	Criteria c = session.createCriteria(Customer.class);
    	//使用add方法,,表示设置条件值
    
    	方法(属性,条件值)
    	Restrictions.eq 等于
      Restrictions.allEq 使用Map,使用key/value进行多个等于的比对
      Restrictions.gt 大于 >
      Restrictions.ge 大于等于 >=
      Restrictions.lt 小于 <
      Restrictions.le 小于等于 <=
      Restrictions.between 对应SQL的BETWEEN子句
      Restrictions.like 对应SQL的LIKE子句
      Restrictions.in 对应SQL的in子句
      Restrictions.and and关系
      Restrictions.or or关系
    	
    	多个条件
         //业务:查询出id大于1,名字中带ji的用户
         criteria.add(Restrictions.like("name","%ji%"))
    	 criteria.add(Restrictions.gt("id", 1));
    	
    	
    ·排序查询
    	criteria.addOrder(Order.desc("id"))
    ·分页查询
    	Criteria中提供了两个方法,setFirstResult方法和setMaxResults,一个是数据的开始位置0表示第一条记录,一个是返回的记录数。
    	Criteria crit = session.createCriteria(Conft.class);  
        crit.setFirstResult(0);  
        crit.setMaxResults(10);  
        List<Conft> list = crit.list();
    
    ·统计查询
    	Criteria crit = session.createCriteria(Conft.class); 
    	//设置操作 
    	crit.setProjection(Projections.rowCount());
    	//调用方法得到结果
    	Object obj = crit.uniqueResult();//实际是long类型
    
    ·离线查询
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
        // 设置查询条件
        criteria.add(Restrictions.eq("lkm_gender", "男"));
        // 查询数据
        List<Linkman> list = criteria.getExecutableCriteria(session).list();
        for (Linkman linkman : list) {
            System.out.println(linkman);
        }
        tr.commit();
    

    5、本地sql查询
    SQLQuery对象,使用普通sql实现查询

    hibernate检索策略
    hibernate检索分为两类
    1、立即查询:根据id查询,调用get方法,一调用get方法马上发送查询数据库
    2、延迟查询:根据id查询,还有load方法,调用load方法不会马上查询,只有得到对象里面的值的时候才会发送语句查询数据库

  • 相关阅读:
    TCP通过哪些措施,保证传输可靠
    http协议---简述
    单播、广播、组播、多播
    axios 设置超时时间 timeout
    axios 处理并发请求
    vue 模板语法
    vue keep-alive
    v-if 条件渲染分组
    debounce 防抖动函数
    vue scoped 深度作用选择器
  • 原文地址:https://www.cnblogs.com/changzuidaerguai/p/7243309.html
Copyright © 2020-2023  润新知