Hibernate快速笔记1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28666193/article/details/85255043

视频:Hibernate
资料与文档:领取 提取码:p3es

路线:

  1. Hibernate的概述,原理,简单的API使用
  2. 一级缓存和其他API
  3. 1vN和NvN的配置
  4. Hibernate的查询方式和抓取策略
  5. CRM案例

引入:CRM系统【百度百科】

  1. 客户关系管理系统(CRM)是以客户数据的管理为核心,利用信息科学技术,实现市场营销、销售、服务等活动自动化,并建立一个客户信息的收集、管理、分析、利用的系统,帮助企业实现以客户为中心的管理模式。客户关系管理既是一种管理理念,又是一种软件技术。

    客户关系管理系统主要有高可控性的数据库、更高的安全性、数据实时更新等特点,提供日程管理、订单管理、发票管理、知识库管理等功能。

  2. 客户关系一对一理论。满足每个客户的特殊需求,同每个客户建立联系,通过同客户的联系来了解客户的不同需求,并在此基础上进行"一对一"个性化服务。

  3. 从新客户接入到老客户维护和营销的每一个环节。与销售、营销、推广、策划、人事等多部门业务对接。优化各业务环节,减少各环节客户流失,和公司成本。----------市场营销、数据分析、掌控能力等

CRM系统是一种综合性的概念,这样的系统一般就是面向客户的数据信息,可以分为若干模块。如客户信息管理、联系人管理、统计分析、综合查询等。

简单解释,销售方业务员工(用户)使用这种系统,先去找到客户方的某些代表的联系人(联系人管理),通过他们开发成客户,并记录这个过程中的信息(客户拜访管理),然后把客户的资料录入系统(客户信息管理),然后可以随时通过系统查询上述这些所有的信息(综合查询),进而进行一些相应的分析处理(统计分析)。 另外,这个系统本身还有一些基本的管理和使用,比如账户、日志等(系统管理)。

本案例仅涉及CRM中客户信息管理的CRUD操作及配置


Hibernate是什么?怎么用?

框架是一种软件的半成品,未完全加工。

经典的JAVA EE(服务端)分为Web、业务、持久三层结构。不同的技术和框架对应着不同的层次,这是在长期经验下的产物,或者说建议。使用传统的 Servlet + Jsp + JavaBean + JDBC 可以完成开发,但是框架的好处是加快快发效率,性能更加优越。

常用架构对应的分层示意图:![图一 EE的三层结构](assets/图一 EE的三层结构2.bmp)

总结:持久层中的ORM框架,对JDBC进行了轻量级封装,自动化。ORM也就是对象关系映射,将Java中的对象和数据库的表通过xml做映射,达到操作对象就是直接操作表的目的。

优点:1)对JDBC的轻量级封装,简化数据访问层的重复性代码,减少内存消耗,提高效率
2)框架,优秀的ORM实现,简化DAO(Data Access Object)层的实现
3)性能强,扩展性强——多种RDB,多种ER关系映射;可拓展,多种API,开源。【注】:性能高是相对的,一般来说越底层的访问速率是越快的,而上层的提供了许多方便的拓展使用方法,进行了一些优化,达到提升性能的结果。
 

版本:3.x(5.x类似,兼容),4.x
使用
  • [下载](<https://sourceforge.net/projects/hibernate/files/hibernate-orm/5.0.7.Final/)文件,解压;
  • 解压文件目录中包含doc(文档),lib(库),project(预设项目);其中lib中含有必须和非必须的各种库文件(jar包)
  • 创建Java项目或者WEB项目时均可引用,使用的方式就是导JAR包;
    • 数据库操作的JAR包:数据库驱动如 MySQL,JDBC/C3P0等
    • lib中的required中的包
    • 日志记录包log4j——便于开发

方式

  1. 创建数据表

  2. 创建实体类

  3. 使用hbm.xml(命名随意,但约定后缀),配置映射关系

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 建立类与表的映射 -->
    	<class name="com.itheima.hibernate.demo1.Customer" table="cst_customer">
    		<!-- 建立类中的属性与表中的主键对应 -->
    		<id name="cust_id" column="cust_id" >
    			<generator class="native"/>
    		</id>
    		
    		<!-- 建立类中的普通的属性和表的字段的对应 -->
    		<property name="cust_name" column="cust_name" length="32" />
    		<property name="cust_source" column="cust_source" length="32"/>
    		<property name="cust_industry" column="cust_industry"/>
    		<property name="cust_level" column="cust_level"/>
    		<property name="cust_phone" column="cust_phone"/>
    		<property name="cust_mobile" column="cust_mobile"/>
    	</class>
    </hibernate-mapping>
    
  4. Hibernate的全局配置cfg.xml,配置的说明在解压文件下l\project\etc\hibernate.properties中有示例

    • 配置数据库:驱动,服务器,端口号,数据库
    • Hibernate方言
    • 数据库连接池
    • 导入映射文件

配置文件

  1. 映射配置文件 ------xxx.hbm.xml
    • <hibernate-mapping>下配置所有

    • <class>/<id>/<property>标签

    • 字段:name,column等,length在hibernate自动建表时使用

    • 【class标签的配置】

      • 标签用来建立类与表的映射关系

      • 属性:

        • name :类的全路径

        • table :表名(类名与表名一致,table可以省略

        • catalog :数据库名

      【id标签的配置】

      • 标签用来建立类中的属性与表中的主键的对应关系

      • 属性:

        • name :类中的属性名

        • column :表中的字段名(类中的属性名和表中的字段名如果一致,column可以省略

        • length :长度

        • type :类型

      【property标签的配置】

      • 标签用来建立类中的普通属性与表的字段的对应关系

      • 属性:

        • name :类中的属性名

        • column:表中的字段名

        • length :长度

        • type :类型

        • not-null :设置非空

        • unique :设置唯一

  2. hibernate核心配置 hibernate.cfg.xml
    • <hibernate-configuration>下配置所有,注:配置同样可以使用properties文件配置,但是这样加载不了映射文件
    • <session-factory>配置会话工厂,相当于配置不同的连接容器,用来解析后创建不同的连接池,包含多个连接,也就是session
    • 数据库的配置(驱动,DB,账户,密码等) 【必须】
    • 方言配置——控制不同的数据库会话 【必须】
    • 映射文件<mapping> , 也可以使用手动加载
    • 【可选】SQL语句的打印(console)与格式化,自动创建表——用作测试和验证
      • 显示SQL :hibernate.show_sql
        格式化SQL :hibernate.format_sql
        自动建表 :hibernate.hbm2ddl.auto
        • none:不使用hibernate的自动建表
        • create:如果数据库中已经有表,删除原有表,重新创建,如果没有表,新建表。(测试)
        • create-drop :如果数据库中已经有表,删除原有表,执行操作,删除这个表。如果没有表,新建一个,使用完了删除该表。(测试)
      • update:如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
      • validate :如果没有表,不会创建表。只会使用数据库中原有的表。(校验映射和表结构)。

核心API (几个对象)

  • Configuration: 加载核心配置文件,映射配置文件(手动加载);用来配置Hibernate,启动Hibernate;启动时映射到不同的xml文件,然后创建SessionFactory对象。

  • SessionFactory:初始化hibernate,数据源的代理(相当于连接池),session的工厂,使用Configuration创建;维护hibernate的数据库连接池和二级缓存(已基本弃用);线程安全的,一个项目只需一个;也可以手动配置另外的如C3P0连接池(需导入相应的jar包)

    • 于是,可以在一个项目中,使用一个工具类,抽取出相应的Session工厂;
    • 同一个项目使用一个工厂即可,用来返回不同的session
  • Session:Session代表的是Hibernate与数据库的链接对象,类似于connection。不是线程安全的,所有一般会获取多个,单独使用。与数据库交互的桥梁。具有一批方法,来进行CRUD操作:

    • 保存:Serializable save(Object obj); 返回序列化的键——序号

    • 查询:T get(Class c,Serializable id); T load(Class c,Serializable id);

      get和load的区别:get是立即执行发送SQL,返回查询到的对象或者null;load懒加载,使用对象的时候才执行查询的SQL(除了ID可以直接获取外);

      get返回是真实对象,load返回的是代理对象(javassist),对象不存在的时候报错

    • 修改:void update(Object obj);直接修改(相同ID的新对象替代),先查询再修改

    • 删除:void delete(Object obj);根据删除(相同ID序号的新对象),先查询再删除,支持Hibernate的级联删除

    • 【不常用】保存或更新:void saveOrUpdate(Object obj)

    • 【不常用】查询所有: Query createSQLQuery(String sql) 同样支持HQL createQuery()

  • Transaction:事务对象,commit、rollback


基础笔记(案例一、基于Hibernate的DAO操作)

  1. 持久化与持久化类

    Hibernate是持久层的ORM映射框架,专注于数据的持久化工作——也就是内存数据永久性地写入到数据库中。Java中与数据库表中完成对应的映射类文件,称为持久化类——或者说带有映射文件的Java类对象。

    • 持久化类的规则
      1. 必须有一个无参的构造函数:Hibernate使用反射来生成实例对象,类的class字节码需要;
      2. 私有属性必须有get/set方法,Hibernate设置对象的值
      3. 类中必须一个和表主键对应的属性——唯一性
      4. 类中属性尽量使用包装类型,如Integer,Long——基本数据类型的默认值是0,存在歧义,例如int型的年龄,入DB的是0,是0还是忘了插入?
      5. 类不用final进行修饰——与延迟加载有关,延迟加载是Hibernate的一种优化,返回的是代理对象,其底层用到了继承,这样一来会使延迟加载失效,而返回真实对象
  2. Hibernate主键生成策略
    • 自然主键:表本身中的一个字段,具有实际意义,如身份证号,手机号
    • 代理主键:表本身不是必须的,与个体的属性没有太大关联,如序列号,Cid,Sid等;【推荐使用
    • 原则:开闭原则,对拓展是开放的,对修改时封闭的
    • 生成策略:Hibernate提供多种主键的生成策略,不需要用户自己操作
      • increment:Hibernate的自增长,适用于short、int、long等类型主键,单线程使用;select max(ID) from 表,然后加1作为下一条记录,存在线程安全问题
      • identity:数据库底层的自增长,不会产生线程安全问题,适用于short/int/long等,适用于有自增长的数据库产品,oracle不行
      • sequence:适用于short、int、long等类型主键,适用含有序列的数据库,MySQL不支持
      • uuid:字符串类型主键,Hibernate随机生成
      • native:本地策略,可以视作在identity和sequence自动切换
      • assigned:Hibernate不设置主键,需要手动插入
      • foreign:外部,一对一的一种关联情况下使用
  3. 持久化类的三种状态
    • 瞬时态:没有唯一的标识OID,没有被session管理
    • 持久态:有唯一标识OID,被session管理
    • 脱管态:有唯一标识OID,不被session管理;new 对象后,设置ID即可;将ID置为null,则转为瞬时态;

    在这里插入图片描述

    • 持久化类:**可以自动更新数据库;**Hibernate的一级缓存,也就是数据库数据的备份,存储在内存中
      • 一级缓存,和session控制,生命周期与session一致;Hibernate默认自带与开启;用于减少对数据库的访问;调用session集合中的方法时,先访问缓存,没有则访问数据库,然后将其加载到一级缓存中。调用close()时,关闭session的缓存内容,clear()情况所有缓存,evict(object)清楚单个对象
      • 二级缓存,需要手动开启,暂时不常用;
      • 自动更新数据库:通过Hibernate缓存和快照实现,如果缓存和快照区数据不同了,那么就会将缓存更新到数据库中(事务提交时)。
  4. 事务

    事务ACID,由隔离性引发的问题——读和写。

    读问题:脏读、不可重复读、幻(虚)读

    写问题:引发两类丢失更新

    1. 事务隔离级别

      • read-un-commit: 未提交读
      • read-commited:读已提交 Oracle默认
      • repeatable read:重复读 MySQL默认
      • Serializable:序列化
    2. Hibernate的隔离级别配置:核心配置文件cfg.xml中,<property name="hibernate.connection.isolation">1/2/4/8</property>

    3. 在开发中,DAO层负责单个的执行逻辑,对业务而言,service层才是处理事务的逻辑;这需要在事务的处理过程中,多个DB操作使用的是同一个连接对象(connection/session)。两种解决方法:1.向下传递同一个session对象;2. 使用ThreadLocal线程进行事务操作的绑定。

      Hibernate的事物线程绑定,需要配置<property name="hibernate.current_session_context_class">thread/jta等</property>;配置完后即可在service包含的多个DAO操作中,通过获取当前线程中已绑定的session对象,完成;

      绑定线程后的session不需要再进行手动关闭,线程结束后自动关闭;

  5. 其他API
    1. query:查询操作,接受HQL,查询多个对象,返回唯一结果等

      示例:

      public void demo4() {
      		//Query		
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction transaction = session.beginTransaction();
      		//查询所有
      		String hql = "from Customer";
      		Query query = session.createQuery(hql);
      		List<Customer> list = query.list();
      		
      //		for (Customer customer : list) {
      //			System.out.println(customer);
      //		}
      		//条件查询
      //		String hql2 = "from Customer where cust_name like ?";
      //		Query query2 = session.createQuery(hql2);
      //		query2.setParameter(0, "1%");
      //		list = query2.list();
      //		for (Customer customer : list) {
      //			System.out.println(customer);
      //		}
      		
      		//分页查询
      		String hql3 = "from Customer";
      		Query query3 = session.createQuery(hql3);
      		//起点
      		query3.setFirstResult(2);
      		//size
      		query3.setMaxResults(1);
      		list = query3.list();
      		for (Customer customer : list) {
      			System.out.println(customer);
      		}
      		
      		transaction.commit();
      	}
      
    2. Criteria:面向对象查询,QBC查询

      public void demo() {
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction transaction = session.beginTransaction();
      		//查询所有
      		Criteria criteria = session.createCriteria(Customer.class);
      		List<Customer> list = criteria.list();
      		//条件查询
      		//criteria.add(Restrictions.like("cust_name", "1%"));
      		List<Customer> list2 = criteria.list();
      		//分页
      		criteria.setFirstResult(0);
      		criteria.setMaxResults(2);
      		List<Customer> list3 = criteria.list();
      		for (Customer customer : list3) {
      			System.out.println(customer);
      		}
      		transaction.commit();		
      	}
      
    3. SQLQuery:SQL的查询,一般不常用

 

一对多的关系

案例:CRM中的客户和联系人

  • 配置:一端和多端的实体都要使用实体对象的引用进行关系的关联;在各自的映射配置文件中,也需要使用关联的配置
  • 级联操作:测试中,1的对象需要添加多的引用,多的集合要将1添加进来;没有在配置文件中配置级联保存或更新,则需要两端同时保存;否则保存了主体对象即可,也不需要配置双向的关联关系。
  • 级联删除:删除1,多方参考的外键置为null(默认);设置了1的级联删除,则删除时同时删除关联的多方;也可以设置多方的级联,删除时同时删除关联的1方数据,且和1方关联的多方的其他数据也会删除(基本不用)
  • cascade和inverse的区别:前者设置的是对象间的关联关系,后者管理的是键的管理关系;默认一方的inverse为false,表示不放弃外键的管理权。置为True后,保存1方的对象,会保存其关联(cascade)的多方对象入库,但是却没有外键

多对多的关系

  • 多对多的关系,需要配置两个实体外,还需要一个关联表
  • 如果进行的是双向关联,二者必须有一个放弃外键的控制,否则关联表中将会出现主键重复的冲突;非双向关联则不会出现错误
  • 级联保存或更新:设置后可以只保存主体一方,否则出现瞬时对象异常;设置级联后不需要双向关联
  • 级联删除:【基本不用】没有设置级联删除时,只会删除本表和关联表;设置cascade后,会将关联的表中数据一并删除

一对一的关系

  • 一般转化为唯一外键对应
  • 或直接主键对应

猜你喜欢

转载自blog.csdn.net/qq_28666193/article/details/85255043
今日推荐