Hibernate二

来源:互联网 发布:zbrush for mac 编辑:程序博客网 时间:2024/04/28 10:10

Hibernate框架常用知识点总结

标签: hibernate框架
19人阅读 评论(0)收藏举报
本文章已收录于:
分类:
作者同类文章X

    目录(?)[+]

    1. Hibernate
      1. 概念
      2. 框架搭建
      3. 配置详解
        1. 映射文件
          1. hibernate-mapping
          2. class属性
          3. id属性映射主键
          4. property属性映射普通列
        2. 主配置文件
      4. API详解
        1. configuration
        2. SessionFactory
        3. Session
        4. Transaction
      5. 创建实体对象规则
      6. 对象的三种状态
        1. 一级缓存
      7. hibernate中的事务管理
        1. 设置事务隔离级别
        2. hibernate中事务的应用
      8. 一对多多对一关系
        1. ORM
        2. 应用
          1. Cascase属性级联操作
          2. inverse属性是否放弃维护关系
        3. 多对多关系
          1. ORM
          2. 应用
            1. Cascade属性级联操作
            2. inverse属性是否放弃维护关系
          3. Hibernate中的查询
            1. HQL
              1. 语法
            2. Criteria查询
              1. 语法
              2. 离线Criteria查询对象
            3. 原生SQL
              1. 语法
            4. 查询策略
              1. 类级别查询策略
              2. 关联级别查询策略
              3. 两个问题

    Hibernate

    概念

    • 用于操作数据库
    • hibernate可以用面向对象的方式操作数据库
    • ORM框架-将对象与表的关系使用配置文件映射

    框架搭建

    1. 导包
      导入lib下的required下的包
    2. 准备实体&映射文件
      在实体所在包下新建映射文件(名称:类名.hbm.xml),导入dtd约束(在hibernate-mapping-3.0.dtd)

      <hibernate-mapping>    <class name="类名" table="表名">        <!--配置主键-->        <id name="主键对应的属性名" column="表的主键名" >            <!--配置id生成策略-->            <generator class="native"></generator>        </id>        <!--配置其他属性-->        <property name="属性名" column="表的字段"></property>    </class></hibernate-mapping>
    3. 准备主配置文件
      在src目录下,新建hibernate.cfg.xml主配置文件,导入dtd约束(在hibernate-configuration-3.0.dtd)

      <session-factory>    <!--5个必选项-->    <proprrty name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>    <proprrty name="hibernate.connection.url">jdbc:mysql:///test</property>    <proprrty name="hibernate.connection.username">root</property>    <proprrty name="hibernate.connection.password">123</property>    <!--mysql方言,选择最短的选项-->    <proprrty name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>    <!--3个可选项-->    <!--选择标准的sql打印在控制台-->    <property name="hibernate.show_sql" >true</property>    <property name="hibernate.format_sql" >true</property>    <!--自动建表-->    <property name="hibernate.hbm2ddl.auto">update</property>    <!--引入映射文件-->    <mapping resource="cn/it/domain/User.hbm.xml" /></session-factory>
    4. 书写代码

    配置详解

    映射文件

    hibernate-mapping

    package属性:填写一个包名,后续配置中默认类所在包即为package属性填写的包

    class属性

    映射表与类的对应
    name属性:类名
    table属性:表名

    id属性(映射主键)

    name属性:类中主键属性名
    column属性:表中主键名,默认列名为属性名
    length属性:当前列的长度,默认数据库对于类型最大长度
    type属性:当前列的类型,默认自动检测属性

    generator属性:主键生成策略

    代理主键:
    increment:先查询表中主键最大值,加1作为新的主键值.
    identity:依赖于数据库的主键自增
    sequence:使用数据库中的序列
    hilo:hibernate自己用高低位算法完成主键自增
    uuid:生成随机字符串作为主键(长度应大于32位)
    native(常用):自动根据数据库 三选一.(identity|sequence|hilo)

    自然主键:
    assigned:hibernate不生成主键.由开发人员自己设置主键值.

    property属性(映射普通列)

    name属性:类中主键属性名
    column属性:表中主键名,默认列名为属性名
    length属性:当前列的长度,默认数据库对于类型最大长度
    type属性:当前列的类型,默认自动检测属性

    主配置文件

    整体结构在框架搭建的主配置文件中。

    自动建表(hibernate.hbm2ddl.auto)
    create:自动建表,每次启动hibernate都会自动建表,即使表已经存在,仍然会删除重新建。
    create-drop:自动建表,每次启动hibernate都会自动建表,每次运行完成后会将表删除。
    update:自动建表,如果有表,就不在重新创建,如果配置改变,自动更改表结构。
    validate:不会自动创建表结构,只负责在启动时检验表结构,检出问题后会抛出异常。

    API详解

    configuration

    config,读取配置文件buildSessionFactory,创建sessionFactoryConfiguration conf = new Configuration().config;SessionFactory sf = conf.buildSessionFactory;

    SessionFactory

    根据配置信息创建session对象。
    1. SessionFactory创建需要消耗较多的内存资源。
    2. SessionFactory是线程安全的设计。
    结论:在一个web项目中确保只有一个SessionFactory存在。

    //获得一个全新的sessionSession session = sf.openSession();//获得与线程绑定的session,使用需要两个条件:1.在主配置文件中配置2.不需手动关闭sessionSession session = getCurrentSession

    Session

    hibernate中操作数据库的核心对象。
    1. 操作增删改查
    2. 获得事务操作对象

    beginTransaction|getTransaction 获得事务对象,第一个还具有开启事务的功能。get|load   根据给定标识和实体类返回持久化对象的实例save    增delete  删update  改saveOrUpdate 根据给定的实例的标识属性的值来决定执行增或改的操作。createQuery 根据给定的HQL查询条件创建一个新的Query实例。createCriteria  根据给定的实体的名称,创建一个新的Criteria实例。createSQLQuery 根据给定的SQL查询条件创建一个新的SQLQuery实例。get方法不会应用类级别加载策略,立即加载。load方法会应用类级别加载策略,load方法调用时,不会发送任何sql语句,返回一个代理对象,使用对象时才执行查询加载数据。

    Transaction

    用于操作事务的对象

    tx.tx.begin();//开启事务tx.commit();//提交事务tx.rollBack();//回滚事务

    创建实体对象规则

    1. public的空参构造
    2. 准备属性,public的set/get方法
    3. 提供oid,映射主键字段
    4. 标识属性尽量使用基本数据类型的包装类
    5. 类不能被final修饰

    对象的三种状态

    瞬时 没id,没关联

    持久 有id,有关联

    游离 有id,没关联

    持久化状态:持久化状态对象会在事务提交时会持久化到数据库,我们需要将对象持久化到数据库,就需要把对象转换为持久化状态。

    一级缓存

    一级缓存:也称为session缓存.属于线程级别缓存. 该缓存本质其实就是一个集合.该集合被放置到了session对象中.所以也叫session缓存.因为session是线程级别的.所以该缓存属于线程级别缓存.
    缓存的作用:提高查询、修改效率。

    查询:
    1. 根据id查询对象
    2. ResultSet会被封装成对象,放入缓存以及返回程序。如果缓存中存在要查id的对象,返回缓存中的对象。

    修改:
    1. 根据id查询对象
    2. ResultSet会被封装成对象,一式两份,分别放入session缓存以及缓存快照中
    3. 事务在提交时,会比对session缓存中的以及快照中的对象是否发生变化。如果发生变化执行修改。

    hibernate中的事务管理

    设置事务隔离级别

    <!--数值可设置为1、2、4、8--><property name="hibernate.connection.isolation">4</property>

    hibernate中事务的应用

    1. 事务在service层管理。
    2. 确保service层和dao层使用的时同一个Connection,调用getCurrentSession方法是从ThreadLocal中获得与线程绑定的session。
    3. getCurrentSession必须配置才能使用

      <!--指定getCurrent获得session与当前线程绑定--><property name="hibernate.current_session_context_class">thread</property>
    4. getCurrentSession方法获得的session对象,会在事务提交时自动关闭,不用手动关闭。

    一对多|多对一关系

    ORM

    ORM:对象关系映射

    • o:一的一方使用集合,多的一方直接引用一的属性
    • r:多的一方使用外键引用一的一方
    • m:一对多关系映射,多对一关系映射

      <!--配置一对多关系--><set name="集合属性名">    <key column="外键名"></key>    <one-to-many class="多的一方对应的类名" /></set><!--配置多对一关系--><many-to-one name="引用一的属性名" column="外键名" class="一的一方对应的类名"><many-to-one>

    应用

    Cascase属性:级联操作

    • none:默认值,不级联
    • save-update:级联保存或级联更新
    • delete:级联删除
    • all:save-update+delete

    结论:Cascase属性的性质属于减少开发时书写代码量的配置,可以不用靠写代码代替,级联操作尤其级联删除配置使用风险大,不建议使用。

    inverse属性:是否放弃维护关系

    inverse属性:
    - true:放弃
    - false(默认):维护

    一对多中可以使用Inverse属性放弃维护关系,多对一中不能放弃维护关系。

    <set name="linkMen" inverse="true">    <key column="lkm_cust_id"></key>    <one-to-many class="LinkMan"></one-to-many></set>

    结论:为了避免维护关系SQL打印冗余,可以在一的一方放弃维护。配置后注意,表达关系只能通过多的一方来维护。

    多对多关系

    ORM

    ORM:对象关系映射

    • r:使用第三张表,该表至少两列,两列都是外键
    • o:两方都用集合来表达引用多个对方
    • m: 多对多映射文件




    应用

    Cascade属性:级联操作

    与一对多|多对一关系中相同的操作

    不推荐使用delete

    inverse属性:是否放弃维护关系

    inverse属性:

    • true:放弃
    • false(默认):维护

    结论:为了避免维护关系重复造成异常抛出,根据业务需要由一方放弃维护。放弃的规则:谁不依赖,谁放弃。例如:订单和商品,商品不依赖订单的存在,商品放弃维护。

    Hibernate中的查询

    • 根据OID查询
    • 对象属性导航
    • HQL查询
    • Criteria查询
    • 原生SQL查询

    HQL

    Hibernate Query Language:hibernate查询语言
    该查询语言是面向对象的查询语言.
    HQL语句中绝对不可能出现与数据库相关的信息.
    该语言是Hibernate独有的语言.只能在Hibernate中使用

    语法

    一. 基础语法

        //1.书写sql    //String hql = "select c from cn.it.domain.Customer c";//完整写法    String hql = "from Customer";//简写    //2.创建查询对象    Query query = session.createQuery(hql);    //3.执行查询    List<Customer> list = query.list();

    二. 投影查询

    查询一个属性

        String hql = "select c.id from Customer c";    Query query = session.createQuery(hql);    List<String> list = query.list();

    查询两个属性

        String hql = "select c.id,c.name from Customer c";    Query query = session.createQuery(hql);    List<Object[]> list = query.list();

    查询多个对象,并封装到对象中

        String hql = "select new Customer(c.id,c.name,c.password) from Customer c";    Query query = session.createQuery(hql);    List<Customer> list = query.list();

    三. 条件查询

    问号占位符

    String hql = "from Customer c where c.name=?";Query query = session.createQuery(hql);query.setParameter(0,"张%");//从0开始List<Customer> list = query.list();

    命名占位符

    String hql = "from Customer c where c.id between :low and :high";Query query = session.createQuery(hql);query.setParameter("low",2);query.setParameter("high",5);List<Customer> list = query.list();

    四. 分页查询

    String hql = "from Customer";Query query = session.CreateQuery(hql);query.setFirstResult(2);//startIndexquery.setMaxResults(2);//pageSizeList<Customer> list = query.list();

    五. 排序
    desc降序,asc升序

    String hql = "from Customer c order by c.id desc ";Query query = session.createQuery(hql);List<Customer> list = query.list();

    六. 聚合函数查询
    Count、Max、Min、Sum、Avg

    String hql = "select count(c) from Customer c";Query query = session.createQuery(hql);Long count = (Long)query.uniqueResult();

    七. 多表查询

    内连接

    String hql = "from Customer c inner join c.linkMen";Query query = session.createQuery(hql);List<Object[]> list = query.list();

    迫切内连接

    String hql = "from Customer c inner join fetch c.linkMen";Query query = session.createQuery(hql);List<Customer> list = query.list();

    左外连接

    String hql = "from Customer c left join c.linkMen";Query query = session.createQuery(hql);List<Object[]> list = query.list();

    左外迫切连接

    String hql = "from Customer c left fetch c.linkMen";Query query = session.createQuery(hql);List<Customer> list = query.list();

    右外连接、右外迫切连接在左的基础上把left换为right即可。

    结论:HQL适用于单表或简单多表,业务逻辑较为复杂的多表仍然需要使用原生SQL书写.

    Criteria查询

    hibernate框架中独有的查询方式.
    Criteria是无语句面向对象查询.
    Criteria一般用于单表查询.

    语法

    一、基础查询

    //1.创建查询对象Criteria c = session.createCriteria(Customer.class);//2.执行查询List<Customer> list = c.list();

    二、条件查询

    Criteria c = session.createCriteria(Customer.class);//设置查询参数c.add(Restrictions.and(Restrictions.between("id",2,5),Restrictions.like("name","李%")));//查询List<Customer> list = c.list();

    三、分页查询

    Criteria c = session.createCriteria(Customer.class);c.setFirstResult(2);c.setMaxResults(2);List<Customer> list = c.list();

    四、排序查询

    Criteria c = session.createCriteria(Customer.class);c.addOrder(Order.asc("age"));List<Customer> list = c.list();

    五、聚合查询

    Criteria c = session.createCriteria(Customer.class);c.setProjection(Projections.Count("id"));Long count = (Long)c.uniqueResult();

    离线Criteria查询对象

    离线Criteria:不需要session就可直接创建

    //获得离线查询对象DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);//设置条件dc.add(Restrictions.like("name","王%"));//将离线查询对象与session关联Criteria c = dc.getExecutableCriteria(session);//执行操作List<Customer> list = c.list(); 

    结论:适合单表

    原生SQL

    语法

    一、基本查询

    String sql = "select * from t_customer";//创建查询对象Query query = session.createSQLQuery(sql);List<Object[]> list = query.list();

    将指定结果封装到对象中

    String sql = "select * from t_customer";Query query = session.createSQLQuery(sql);//指定将结果封装到对象中query.addEntity(Customer.class);List<Customer> list = query.list();

    二、条件查询

    参数查询:可以用问号|命名占位符

    String sql = "select * from t_customer where name like ?";Query query = session.createSQLQuery(sql);query.setParameter(0,"陈%");query.addEntity(Customer.class);List<Cutomer> list = query.list();

    三、分页查询

    String sql = "select * from t_customer limit ?,?";Query query = session.createSQLQuery(sql);query.setParameter(0,2);//设置起始页query.setParameter(1,3);//设置每页封装数量query.addEntity(Customer.class);List<Customer> list = query.list();

    用于复杂业务查询

    查询策略

    类级别查询策略

    lazy属性:是否懒加载|延迟加载

    • true(默认值):懒加载|延迟加载
    • false:立即加载

      <!--配置类级别查询策略--><class name="User" table="cn.it.domain.User" lazy="true"></class>

    原理:懒加载时,load方法不会立即查询,会返回要查询的对象的代理对象,这个代理对象对当前操作的session进行封装,在获得对象的属性时,能够根据关联的session加载数据。

    注意事项:返回对象的初始化操作一定要在session关闭之前完成,否则会抛出no-session异常。

    关联级别查询策略

    集合加载策略(一对多|多对多)

    lazy属性:决定集合加载策略

    • true(默认值):懒加载|延迟加载
    • false:立即加载
    • extra:极其懒惰,在查询数量时,只查询数量,不查询内容。

    fetch属性:指定集合的加载方式

    • select(默认值):加载集合时使用单表查询加载
    • join:加载集合时使用左外连接查询(使用改属性,lazy属性会失效)
    • subselect:使用子查询加载多个集合,如果只加载一个,效果和select相同。

      <set name="linkMen"  inverse="true" lazy="true" fetch="subselect" >    <key column="lkm_cust_id"></key>    <one-to-many class="LinkMan"></one-to-many></set>

    属性加载策略(多对一)

    lazy属性:决定属性加载策略

    • proxy(默认值):由对方类级别策略代我决定
    • false:立即加载

    fetch属性:指定属性的加载方式

    • select(默认值):单表查询加载数据
    • join:使用多表查询同时加载数据(使用改属性,lazy属性会失效)

      <many-to-one name="customer" column="lkm_cust_id" class="Customer" lazy="proxy" fetch="select"></many-to-one>

    查询策略结论:查询策略中涉及的所有属性都使用默认值

    两个问题

    问题一:sql语句打印n+1问题

    batch-size属性:一次加载几个客户的集合,默认值为1.使用该属性选择一次加载几个客户的集合来缓解n+1问题

    <set name="linkMen" batch-size="5" >    <key column="lkm_cust_id"></key>    <one-to-many class="LinkMan"></one-to-many></set>  

    问题二:dao返回的代理对象,service中关闭了session。在web层使用代理对象时,session已经关闭。会抛出no-session异常。

    解决方案:
    1. 不使用getCurrentSession,自己将session与现程绑定。
    2. 使用过滤器,由过滤器中后处理代码将session关闭。

    上述操作,交由spring管理。

    0
    0
     
     

    我的同类文章

    http://blog.csdn.net
    • 自定义BeanUtils处理时间格式转换2017-01-26
    • java制作验证码并进行验证2017-01-25
    • Struts2框架搭建、标签、Action以及拦截器总结2017-01-17
    • Spring框架(二)整合Junit4、AOP开发、AOP事务管理详解2017-01-12
    • Struts2框架(二)参数封装、OGNL表达式、拦截器详解2017-01-09
    • java发送邮件工具类2017-01-26
    • Spring框架之IOC、AOP详解2017-01-18
    • Spring(三)Spring整合Struts2、Hibernate2017-01-14
    • Spring框架(一)环境搭建、配置(xml、注解)、整合JDBC以及项目详解2017-01-11
    • Struts2框架(一)架构、文件配置、核心API详解2017-01-08
    更多文章
    0 0