天天看点

Hibernate框架第1章Hibernate第2章Hibernate第3章Hibernate第4章Hibernate

第1章Hibernate

      1. CRM的概述
        1. 什么是CRM

CRM(Customer Relationship Management)客户关系管理,是利用相应的信息技术以及互联网技术来协调企业与顾客间在销售、营销和服务上的交互,向客户提供创新式的个性化的客户交互和服务的过程。其最终目标是将面向客户的各项信息和活动集成起来,组建一个以客户为中心的企业,实现对面向客户的活动的全面管理。

        1. CRM的功能模块

       CRM系统实现了对企业销售、营销、服务等各阶段的客户信息、客户活动进行统一管理。

CRM系统功能涵盖企业销售、营销、用户服务等各各业务流程,业务流程中与客户相关活动都会在CRM系统统一管理,下边列出一些基本的功能模块,包括:客户信息管理、联系人管理、商机管理、统计分析等。

  • 客户信息管理

对客户信息统一维护,客户是指存量客户或拟营销的客户,通过员工录入形成公司的“客户库”是公司最重要的数据资源。

  • 联系人管理

对客户的联系人信息统一管理,联系人是指客户企业的联系人,即企业的业务人员和客户的哪些人在打交道。

  • 客户拜访管理:

业务员(用户)要开发客户需要去拜访客户,客户拜访信息记录了业务员与客户沟通交流方面的不足、采取的策略不当、有待改进的地方或值得分享的沟通技巧等方面的信息。

  • 综合查询

客户相关信息查询,包括:客户信息查询、联系人信息查询、商机信息查询等。

  • 统计分析

按分类统计客户信息,包括:客户信息来源统计、按行业统计客户、客户发展数量统计等。

  • 系统管理

系统管理属于crm系统基础功能模块,包括:数据字典、账户管理、角色管理、权限管理、操作日志管理等。

        1. EE开发三层结构
      1. Hibernate的概述
        1. 什么是框架

框架是软件的半成品,已经完成了相应部分的内容了.只需要实现自己业务即可.

        1. 什么是Hibernate

Hibernate就是一个持久层的ORM的框架.

ORM :Object Relational Mapping.对象关系映射.

        1. Hibernate的优点
  1. 简化JDBC的编程.
  2. 修改了实体类,不需要修改源代码.
  3. 轻量级的框架.
      1. Hibernate的入门:
        1. 创建表

Create database hibernate_day01;

Use hibernate_day01;

CREATE TABLE `cst_customer` (

  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',

  `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',

  `cust_user_id` bigint(32) DEFAULT NULL COMMENT '负责人id',

  `cust_create_id` bigint(32) DEFAULT NULL COMMENT '创建人id',

  `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',

  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',

  `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',

  `cust_linkman` varchar(64) DEFAULT NULL COMMENT '联系人',

  `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',

  `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',

  PRIMARY KEY (`cust_id`)

) ENGINE=InnoDB AUTO_INCREMENT=94 DEFAULT CHARSET=utf8;

        1. 引入Hibernate的开发包

数据库驱动包:

Hibernate/lib/required

    public void demo1(){

        // 1.加载配置文件:

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

        // 2.创建一个SessionFactory:

        SessionFactory sessionFactory = cfg.buildSessionFactory();

        // 3.创建Session对象.Session对象 类似Connection.

        Session session = sessionFactory.openSession();

        // 4.开启事务:

        Transaction tx = session.beginTransaction();

        // 5.执行相关操作

        Customer customer = new Customer();

        customer.setCust_name("小王");

        customer.setCust_source("小广告");

        session.save(customer);

        // 6.事务提交

        tx.commit();

        // 7.释放资源

        session.close();

    }

}

      1. Hibernate的常见配置:
        1. 映射文件的配置

是一个XML文件即可,通常命名 类名.hbm.xml

<class>标签

<id>标签:

<property>标签

        1. 核心配置

* 扩展:Hibernate的核心配置有两种方式:

    * 1.属性文件的方式:hibernate.properties

        * 属性文件的方式不能配置映射:

        * 通过手动编写代码方式加载映射:

    * 2.XML文件的方式:hibernate.cfg.xml

        * 一块:必须的配置:

            * 数据库连接信息:

            * 数据库方言:

        * 二块:可选的配置:

            * 显示SQL

            * 格式化SQL

            * hbm2ddl.auto

                * none            

                * create           :数据库有表,每次都会创建一个新的表.(测试时候)

                * create-drop      :每次都会创建一个新的表,用完之后就删除掉.(测试时候)

                * update           :如果数据库没有表,创建一个新表,如果有表,使用原有表.更新表结构

                * validate     :使用原有表,进行校验.

       * 三块:加载映射:

             <mapping resource="com/it/domain/Customer.hbm.xml"/>

      1. Hibernate的相关API:
        1. Configuration:加载配置文件.
        1. SessionFactory

工具类:

public class HibernateUtils {

    private static final Configuration cfg;

    private static final SessionFactory sessionFactory;

    static{

        cfg = new Configuration().configure();

        sessionFactory = cfg.buildSessionFactory();

    }

    // 提供一个静态的方法获得session对象.

    public static Session openSession(){

        return sessionFactory.openSession();

    }

}

        1. Session:

Session不是线程安全的.

是与数据库交互的桥梁:完成CRUD的操作:常用的方法:

* save(Object obj);

* update(Object obj);

* delete(Object obj);

* T get(Class c,Serializable s);

* T load(Class c,Serializable s);

* saveOrUpdate(Object obj);

        1. Transaction

* commit();

* rollback();

* wasCommitted(); // Hibernate3中提供了该方法.判断事务是否已经提交了.

第2章Hibernate

    1. 相关知识点:
      1. 持久化对象的三种状态

Hibernate管理对象包括三种状态:瞬时状态(Transient)、持久状态(Persistent)、托管状态(Detached),如下图:

1、transient 瞬时状态

new一个新的对象即为瞬时状态,瞬时状态和session没有关联,一个瞬时对象和数据库记录不对应。

瞬时对象--->save或saveOrUpadate---->持久对象。

2、persistent 持久状态

持久状态对象和session有关联,持久对象和数据库记录存在对应,持久对象属性值变更可以持久到数据库中。

执行Get查询可以得到一个持久对象。

持久对象--->delete删除--->瞬时对象

持久对象-->session.close(session关闭)--->托管对象

3、detached 托管状态

托管对象和session没有关联,它和瞬时对象的区别在于托管对象可能会和数据库记录存在对应。

托管对象------>update或saveOrUpdate --->持久对象

      1. 一级缓存
        1. 什么是一级缓存

Hibernate框架中共有两级缓存. Session级别的缓存是属于一级缓存,SessionFactory级别的缓存是二级缓存.

缓存:将数据库或硬盘中的数据,存入到内存中.当下次使用的时候可以从内存中获得,减少数据库访问次数.(优化)

一级缓存:生命周期与session一致.

在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期.

当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图get()、 load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库。没有再查询数据库

        1. 测试一级缓存:

    @Test

    // 证明一级缓存的存在.

    public void demo2() {

        // 创建session

        Session session = HibernateUtils.openSession();

        // 开启事务

        Transaction tx = session.beginTransaction();

        // 调用get方法的时候,查询.将查询的结果放入到一级缓存中.

        Customer c1 = (Customer) session.get(Customer.class, 1); // 发出sql语句,数据翻入一级缓存

        //

        Customer c2 = (Customer)session.get(Customer.class, 1); // 不会发出sql,从一级缓存中获得对象.

        // session缓存对象的时候,缓存对象的地址.

        System.out.println(c1 == c2);

        tx.commit();

        session.close();

    }

        1. 一级缓存的深入:

持久化对象的更新会同步到数据库.

      1. 事务控制
        1. 什么是事务(了解)

什么是事务?

    当多个操作有这样的要求时:要么都成功要么都失败,这说明这多个操作必须在一个事务中,事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。

事务的四个特性?

  1. A:原子性(Atomicity) 

事务中包括的诸操作要么全成功,要么全失败。

  1. B:一致性(Consistency)     

事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。

也就是说事务执行之前数据库数据处于正确状态,执行之后也处理正确状态,如果有些事务运行中发生故障,这些事务对数据库所做的修改有一部分已写入数据库,这时数据库就处于不正确的状态即不一致的状态。

一致性与原子性是密切相关的,如果事务没有原子性的保证,那么在发生系统故障的情况下,数据库就有可能处于不一致状态。

  1. C:隔离性(Isolation)    

 一个事务的执行不能被其他事务干扰。解决多个线程并发操作事务情况,每个事务互相不影响

  1. D:持续性/永久性(Durability)

一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

        1. 隔离级别(了解)

       ANSI SQL 标准定义了隔离级别,但并不是SQL数据库独有.JTA也定义了同样的隔离级别.级别越高,成本越高。

由事务隔离性引发几种问题 ?

       脏读、 不可重复读 、虚读 、 丢失更新

  1. 脏读: 一个事务读取到另一个事务 未提交数据
  2. 不可重复读: 一个事务中,先后读取两次,两次读取结果不同,读取到了另一个事务已经提交的数据,此问题针对update更新来说。
  3. 虚读: 一个事务,先后读取两次,结果不同,读取到了另一个事务已经提交的数据 ,此问题针对insert插入来说。
  4. 丢失更新: 两个事务 同时修改一条数据,后提交事务,覆盖了之前提交事务结果
隔离级别 含义
READ_UNCOMMITTED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

事务的隔离级别 ,是由数据库提供的 ,并不是所有数据库都支持四种隔离级别

       MySQL : READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE (默认 REPEATABLE_READ)

       Oracle : READ_UNCOMMITTED、READ_COMMITTED、 SERIALIZABLE

(默认 READ_COMMITTED )

在使用数据库时候,隔离级别越高,安全性越高 ,性能越低

       实际开发中,不会选择最高或者最低隔离级别,选择 READ_COMMITTED(oracle 默认)、REPEATABLE_READ (mysql默认)

Hibernate 如何设置隔离级别 ?

每个数据库连接都有默认的隔离级别,通常是读已提交或可重复读.可以通过数据库配置设置,也可在应用程序中设置.例如Hibernate:

hibernate.connection.isolation = 4

1—Read uncommitted isolation

2—Read committed isolation

4—Repeatable read isolation

8—Serializable isolation

在hibernate.cfg.xml中设置隔离级别:

<!-- 事务隔离级别 -->

<property name="hibernate.connection.isolation">4</property>

        1. 事务处理的场合

企业级项目采用三层结构, 在业务层进行事务管理,一个service方法的模型如下:

service(){

       session.beginTransaction;//开启事务

       try{

       调用dao方法1

       调用dao方法2

       .....

    session.getTransaction().commit();//提交事务

       }catch(Exception ex){

              session.getTransaction().rollback();//回滚事务

       }

}

        1. hibernate对 session的管理

Hibernate 5 自身提供了三种管理 Session 对象的方法

              Session 对象的生命周期与本地线程绑定

              Session 对象的生命周期与 JTA 事务绑定

              Hibernate 委托程序管理 Session 对象的生命周期

在 Hibernate 的配置文件中, hibernate.current_session_context_class 属性用于指定 Session 管理方式, 可选值包括

       thread: Session 对象的生命周期与本地线程绑定

       jta*: Session 对象的生命周期与 JTA 事务绑定

       managed: Hibernate 委托程序来管理 Session 对象的生命周期

在hibernate.cfg.xml中配置:

<!-- 配置session绑定本地线程 -->

         <property name="hibernate.current_session_context_class">thread</property>

hibernate提供sessionFactory.getCurrentSession()创建一个session和threadLocal绑定方法。

在HibernateUtil工具类中更改getCurrentSession方法:

    //获取当前线程绑定的会话

    public static Session getCurrentSession(){

         return sessionFactory.getCurrentSession();

    }

      1. Hibernate的其他API
        1. Query

Query执行HQL语句:

// 1.查询所有记录

    // 2.条件查询:

    // 3.条件查询:

    // 4.分页查询:

    Query query = session.createQuery("from Customer");

    query.setFirstResult(3);

    query.setMaxResults(3);

    List<Customer> list = query.list();

    System.out.println(list);

        1. Criteria

Criteria:用来执行条件查询

// 1.查询所有记录

    // 2.条件查询

    // 3.条件查询

    // 4.分页查询

    Criteria criteria = session.createCriteria(Customer.class);

    criteria.setFirstResult(3);

    criteria.setMaxResults(3);

    List<Customer> list = criteria.list();

    System.out.println(list);

        1. SQLQuery

        // 基本查询

        SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");

        // 封装到对象中

        sqlQuery.addEntity(Customer.class);

        List<Customer> list = sqlQuery.list();

        for(Customer customer:list){

            System.out.println(customer);

        }

第3章Hibernate

    1. 相关知识点
      1. Hibernate的一对多关联映射
        1. 创建表:

创建联系人表cst_linkman。

导入crm/sql/ crm_cst_linkman.sql

联系人表中存在外键(lkm_cust_id 即所属客户id),外键指向客户表:

ALTER TABLE cst_linkman

ADD CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION

        1. 创建类:

客户的实体:

public class Customer {

    private Long cust_id;  // OID

    private String cust_name;

    private Long cust_user_id;

    private Long cust_create_id;

    private String cust_source;

    private String cust_industry;

    private String cust_level;

    private String cust_linkman;

    private String cust_phone;

    private String cust_mobile;

    // 一个客户对应多个联系人:放的是联系人的集合.(Hibernate默认使用的集合是Set集合.)

    private Set<LinkMan> linkMans = new HashSet<LinkMan>();

}

联系人的实体:

public class LinkMan {

    private Long lkm_id;

    private String lkm_name;

    private String lkm_gender;

    private String lkm_phone;

    private String lkm_mobile;

    private String lkm_email;

    private String lkm_qq;

    private String lkm_position;

    private String lkm_memo;

    // 联系人关联的客户对象:

    private Customer customer;// ORM框架 Object

}

        1. 创建映射:

【客户的映射】

<hibernate-mapping>

    <class name="cn.it.hibernate.domain.Customer" table="cst_customer">

        <id name="cust_id">

            <generator class="native"/>

        </id>

        <property name="cust_name" length="32"/>

        <property name="cust_user_id" column="cust_user_id"/>

        <property name="cust_create_id" column="cust_create_id"/>

        <property name="cust_source" column="cust_source"/>

        <property name="cust_industry" column="cust_industry"/>

        <property name="cust_level" column="cust_level"/>

        <property name="cust_linkman" column="cust_linkman"/>

        <property name="cust_phone" column="cust_phone"/>

        <property name="cust_mobile" column="cust_mobile"/>

        <!-- 配置关联对象 -->

        <!--

            set标签:

                * name属性:多的一方的集合的属性名称.

         -->

        <set name="linkMans">

            <!--

                key标签 :

                    * column属性:多的一方的外键的名称.

            -->

            <key column="lkm_cust_id"></key>

            <!--

                one-to-many标签:

                    * class属性:多的一方的类全路径

             -->

             <one-to-many class="cn.it.hibernate.domain.LinkMan"/>

        </set>

    </class>

</hibernate-mapping>

【联系人映射】

<hibernate-mapping>

    <class name="cn.it.hibernate.domain.LinkMan" table="cst_linkman">

        <id name="lkm_id" column="lkm_id">

            <generator class="native"/>

        </id>

        <property name="lkm_name"/>

        <property name="lkm_gender"/>

        <property name="lkm_phone"/>

        <property name="lkm_mobile"/>

        <property name="lkm_email"/>

        <property name="lkm_qq"/>

        <property name="lkm_position"/>

        <property name="lkm_memo"/>

        <!-- 配置关联对象: -->

        <!--

            many-to-one:标签.代表多对一.

                * name      :一的一方的对象的名称.

                * class     :一的一方的类的全路径.

                * column :表中的外键的名称.

         -->

        <many-to-one name="customer" class="cn.it.hibernate.domain.Customer" column="lkm_cust_id"/>

    </class>

</hibernate-mapping>

        1. 将映射添加到配置文件

<mapping resource="com/it/domain/LinkMan.hbm.xml"/>

        1. 编写测试代码:

    @Test

    // 向客户 和 联系人中同时保存数据:

    public void demo1(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 创建一个客户

        Customer customer = new Customer();

        customer.setCust_name("张总");

        // 创建两个联系人:

        LinkMan linkMan1 = new LinkMan();

        linkMan1.setLkm_name("秦助理");

        LinkMan linkMan2 = new LinkMan();

        linkMan2.setLkm_name("胡助理");

        // 建立关系:

        customer.getLinkMans().add(linkMan1);

        customer.getLinkMans().add(linkMan2);

        linkMan1.setCustomer(customer);

        linkMan2.setCustomer(customer);

        session.save(customer);

        session.save(linkMan1);

        session.save(linkMan2);

        tx.commit();

    }

      1. 一对多的相关操作:
        1. 级联保存

【操作一个对象的时候,将关联对象一并操作.】

级联是有方向性:

* 保存客户的时候级联保存联系人.

    @Test

    public void demo3(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 保存客户:

        Customer customer = new Customer();

        customer.setCust_name("陈总");

        // 保存联系人:

        LinkMan man1 = new LinkMan();

        man1.setLkm_name("小花");

        // 建立关系:

        customer.getLinkMans().add(man1);

        man1.setCustomer(customer);

        // 执行保存操作:

        session.save(customer); // TransientObjectException:customer变为持久态对象,man 还是瞬时态对象.

        // session.save(man1);

        tx.commit();

    }

【保存联系人的时候级联保存客户.】

    @Test

    public void demo4(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 保存客户:

        Customer customer = new Customer();

        customer.setCust_name("肖总");

        // 保存联系人:

        LinkMan man1 = new LinkMan();

        man1.setLkm_name("小娇");

        // 建立关系:

        customer.getLinkMans().add(man1);

        man1.setCustomer(customer);

        // 执行保存操作:

        // session.save(customer); // TransientObjectException:customer变为持久态对象,man 还是瞬时态对象.

        session.save(man1);

        tx.commit();

    }

        1. 测试对象的导航的问题

    @Test

    public void demo5(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 保存客户:

        Customer customer = new Customer();

        customer.setCust_name("肖老板");

        LinkMan linkMan1 = new LinkMan();

        linkMan1.setLkm_name("大娇");

        LinkMan linkMan2 = new LinkMan();

        linkMan2.setLkm_name("中娇");

        LinkMan linkMan3 = new LinkMan();

        linkMan3.setLkm_name("小娇");

        // 设置关系:

        linkMan1.setCustomer(customer);

        customer.getLinkMans().add(linkMan2);

        customer.getLinkMans().add(linkMan3);

        // 执行如下的操作:

        // session.save(linkMan1);  // 执行几条  insert 语句. 4条.

        // session.save(customer); // 执行几条 insert 语句. 3条

        session.save(linkMan2); // 执行几条 insert语句  1条.

        tx.commit();

    }

        1. Hibernate的级联删除

【删除客户的时候同时删除客户的联系人】

    @Test

    public void demo6(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        Customer customer = session.get(Customer.class, 1l);

        session.delete(customer);

        // 不能级联删除的.

        tx.commit();

    }

【删除联系人的时候同时删除客户.】

    @Test

    public void demo7(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        LinkMan linkman = session.get(LinkMan.class, 1l);

        session.delete(linkman);

        tx.commit();

    }

        1. 双向关联产生多余的SQL语句

    @Test

    public void demo8(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        LinkMan linkman = session.get(LinkMan.class, 5l);

        Customer customer = session.get(Customer.class, 4l);

        // 双向关联:

        linkman.setCustomer(customer);

        customer.getLinkMans().add(linkman);

        tx.commit();

    }

原理:

一的一方放弃外键的维护权:

    1. 相关知识点
      1. Hibernate的多对多关联关系映射
        1. 创建表:

创建sys_user、sys_role、sys_user_role三张表。

数据模型如下:

先后导入下边的sql:

crm_sys_user.sql

crm_sys_role.sql

crm_sys_user_role.sql

        1. 创建实体

【用户实体】

public class User {

    private Long uid;

    private String username;

    private String password;

    // 一个用户有多个角色:

    private Set<Role> roles = new HashSet<Role>();

...

}

【角色实体】

public class Role {

    private Long rid;

    private String rname;

    // 一个角色中有多个所属的用户:

    private Set<User> users = new HashSet<User>();

...

}

        1. 创建映射

【用户的映射:】

<hibernate-mapping>

    <class name="com.it.domain.User">

        <id name="uid" column="uid">

            <generator class="native"/>

        </id>

        <property name="username" length="20"></property>

        <property name="password" length="20"></property>

        <!-- 配置关联关系 -->

        <!-- name:角色集合的属性名称   table:-->

        <set name="roles" table="user_role">

            <!-- 当前类中在中间表的外键的名称 -->

            <key column="uno"></key>

            <!-- class:关联的另一方的多的类全路径.column:另一方在中间表中的外键名称: -->

            <many-to-many class="com.it.domain.Role" column="rno"></many-to-many>

        </set>

    </class>

</hibernate-mapping>

【角色的映射:】

<hibernate-mapping>

    <class name="com.it.domain.Role">

        <id name="rid">

            <generator class="native"/>

        </id>

        <property name="rname" length="20"/>

        <!-- 配置角色的关联的映射 -->

        <set name="users" table="user_role">

            <key column="rno"></key>

            <many-to-many class="com.it.domain.User" column="uno"></many-to-many>

        </set>

    </class>

</hibernate-mapping>

        1. 在核心配置中加入映射文件

        <!-- 加载映射 -->

        <mapping resource="com/it/domain/User.hbm.xml"/>

        <mapping resource="com/it/domain/Role.hbm.xml"/>

        1. 编写测试类

@Test

    public void demo1(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 保存两个用户:

        User user1 = new User();

        user1.setUsername("张三");

        User user2 = new User();

        user2.setUsername("李四");

        // 保存三个角色

        Role role1 = new Role();

        role1.setRname("经理");

        Role role2 = new Role();

        role2.setRname("助理");

        Role role3 = new Role();

        role3.setRname("前台");

        // 设置关系:

        user1.getRoles().add(role2);

        user1.getRoles().add(role3);

        user2.getRoles().add(role1);

        user2.getRoles().add(role2);

        role1.getUsers().add(user2);

        role2.getUsers().add(user1);

        role2.getUsers().add(user2);

        role3.getUsers().add(user1);

        session.save(user1);

        session.save(user2);

        session.save(role1);

        session.save(role2);

        session.save(role3);

        tx.commit();

    }

      1. 多对多的相关操作
        1. 级联保存

【保存用户级联角色】

    @Test

    public void demo2(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 创建两个两个用户:

        User user1 = new User();

        user1.setUser_name("张勇");

        User user2 = new User();

        user2.setUser_name("王强");

        // 创建三个角色:

        Role role1 = new Role();

        role1.setRole_name("行政管理");

        Role role2 = new Role();

        role2.setRole_name("人事管理");

        Role role3 = new Role();

        role3.setRole_name("财务管理");

        // 建立关系:如果建立了双向的关系 一定要有一方放弃外键维护权.

        user1.getRoles().add(role1);

        user1.getRoles().add(role3);

        user2.getRoles().add(role2);

        user2.getRoles().add(role3);

        role1.getUsers().add(user1);

        role2.getUsers().add(user2);

        role3.getUsers().add(user1);

        role3.getUsers().add(user2);

        session.save(user1);

        session.save(user2);

        tx.commit();

    }

【保存角色级联用户】

    @Test

    public void demo3(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 创建两个两个用户:

        User user1 = new User();

        user1.setUser_name("张勇");

        User user2 = new User();

        user2.setUser_name("王强");

        // 创建三个角色:

        Role role1 = new Role();

        role1.setRole_name("行政管理");

        Role role2 = new Role();

        role2.setRole_name("人事管理");

        Role role3 = new Role();

        role3.setRole_name("财务管理");

        // 建立关系:如果建立了双向的关系 一定要有一方放弃外键维护权.

        user1.getRoles().add(role1);

        user1.getRoles().add(role3);

        user2.getRoles().add(role2);

        user2.getRoles().add(role3);

        role1.getUsers().add(user1);

        role2.getUsers().add(user2);

        role3.getUsers().add(user1);

        role3.getUsers().add(user2);

        session.save(role1);

        session.save(role2);

        session.save(role3);

        tx.commit();

    }

        1. 多对多的其他操作:

【删除某个用户的角色】

    @Test

    // 将2号用户中的1号角色去掉.

    public void demo6(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 查询2号用户:

        User user = session.get(User.class, 2l);

        // 查询1号角色

        Role role = session.get(Role.class, 1l);

        // 操作集合 相当于 操作中间表.

        user.getRoles().remove(role);

        tx.commit();

    }

【将某个用户的角色改选】

    @Test

    // 将2号用户中的1号角色去掉 改为3号角色

    public void demo7(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 查询2号用户:

        User user = session.get(User.class, 2l);

        // 查询1号角色

        Role role1 = session.get(Role.class, 1l);

        // 查询3号角色

        Role role3 = session.get(Role.class, 3l);

        user.getRoles().remove(role1);

        user.getRoles().add(role3);

        tx.commit();

    }

【给某个用户添加新角色】

    @Test

    // 给1号用户添加2号角色

    public void demo8(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 查询1号用户:

        User user = session.get(User.class, 1l);

        // 查询2号角色:

        Role role = session.get(Role.class, 2l);

        user.getRoles().add(role);

        tx.commit();

    }

第4章Hibernate

    1. 相关知识点
      1. Hibernate的检索方式:
        1. Hibernate检索方式的分类:

Hibernate中提供了5种检索方式:

  1. OID检索  
  2. 对象导航检索   
  3. HQL检索
  4. QBC检索
  5. SQL检索
      1. HQL检索
        1. 基本检索

    @Test

    public void demo2(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 基本查询

        // 起别名

        //Query query = session.createQuery("from Customer c");

        Query query = session.createQuery("select c from Customer c");

        List<Customer> list = query.list();

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

        1. 排序检索

    @Test

    public void demo3(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 基本查询

        Query query = session.createQuery("from Customer order by cust_id desc");

        List<Customer> list = query.list();

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

        1. 条件检索

    @Test

    public void demo4(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 按位置绑定参数

        // 按名称绑定参数

        Query query = session.createQuery("from Customer where cust_name = :name");

        query.setParameter("name", "小添添");

        Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        tx.commit();

    }

        1. 分页检索

    @Test

    public void demo5(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from LinkMan order by lkm_id desc");

        query.setFirstResult(5);

        query.setMaxResults(5);

        List<LinkMan> list = query.list();

        for (LinkMan linkMan : list) {

            System.out.println(linkMan);

        }

        tx.commit();

    }

        1. 统计检索

    @Test

    public void demo6(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("select count(*) from Customer");

        Long num = (Long) query.uniqueResult();

        System.out.println(num);

        tx.commit();

    }

        1. 投影检索

    @Test

    public void demo7(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 投影查询一列

        // 投影查询多列:

        // 投影的构造的方式查询:

        List<Customer> list = session.createQuery("select new Customer(cust_id,cust_name) from Customer").list();

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

      1. QBC检索
        1. 基本检索

@Test

    public void demo1(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 简单查询:

        Criteria criteria = session.createCriteria(Customer.class);

        List<Customer> list = criteria.list();

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

        1. 条件检索

    @Test

    public void demo2(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 条件查询:

        Criteria criteria = session.createCriteria(Customer.class);

        // 设置条件:

        // criteria.add(Restrictions.eq("cust_name", "小军军"));

        criteria.add(Restrictions.like("cust_name", "%小%"));

        criteria.add(Restrictions.gt("cust_id", 1l));

        List<Customer> list = criteria.list();

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

        1. 分页检索

    @Test

    public void demo3(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 条件查询:

        Criteria criteria = session.createCriteria(LinkMan.class);

        // 设置分页查询:

        criteria.setFirstResult(5);

        criteria.setMaxResults(5);

        List<LinkMan> list = criteria.list();

        for (LinkMan linkMan : list) {

            System.out.println(linkMan);

        }

        tx.commit();

    }

        1. 排序检索

    @Test

    public void demo4(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 排序查询:

        Criteria criteria = session.createCriteria(LinkMan.class);

        criteria.addOrder(Order.desc("lkm_id"));

        List<LinkMan> list = criteria.list();

        for (LinkMan linkMan : list) {

            System.out.println(linkMan);

        }

        tx.commit();      

    }

        1. 统计检索

    @Test

    // 统计查询:

    public void demo4(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(LinkMan.class);

        criteria.setProjection(Projections.rowCount());

        Long count = (Long) criteria.uniqueResult();

        System.out.println(count);

        tx.commit();

    }

        1. 离线条件检索

    @Test

    public void demo6(){

        // 获得一个离线条件查询的对象

        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);

        detachedCriteria.add(Restrictions.eq("cust_name","小童童"));

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        List<Customer> list = detachedCriteria.getExecutableCriteria(session).list();// 离线条件查询对象与session绑定.

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

      1. 多表查询
        1. 多表查询:

【SQL多表查询】

SQL中分成:

* 连接查询:

    * 交叉连接:

        * select * from A,B;

    * 内连接

        * 隐式内连接

            * select * from A ,B where A.id = B.id;

        * 显示内连接

            * select * from A inner join B on A.id = B.id;

            * select * from A join B on A.id = B.id;

    * 外连接

        * 左外连接

            * select * from A left outer join B on A.id = B.id;

            * select * from A left join B on A.id = B.id;

        * 右外连接

            * select * from A right outer join B on A.id = B.id;

            * select * from A right join B on A.id = B.id;

【HQL的多表查询】

HQL中分成:

* 连接查询:

     * 交叉连接:

     * 内连接:

        * 隐式内连接

        * 显示内连接

        * 迫切内连接

     * 外连接:

        * 左外连接

        * 迫切左外连接

        * 右外连接

        1. HQL连接查询

SQL连接查询:

* 隐式内连接:

SELECT * FROM cst_customer c,cst_linkman l WHERE c.cust_id = l.lkm_cust_id;

* 显示内连接:

SELECT * FROM cst_customer c INNER JOIN cst_linkman l ON c.cust_id = l.lkm_cust_id;

HQL连接的查询:

* 内连接:

List<Object[]> list = session.createQuery("from Customer c inner join c.linkMans").list();

// session.createQuery("from LinkMan l inner join l.customer");

* 迫切内连接:

    @Test

    public void demo9(){

        Session session = HibernateUtils.getCurrentSession();

        Transaction tx = session.beginTransaction();

        // 迫切内连接:

        // 迫切内连接和内连接所发送的SQL语句是一样的.fetch告诉Hibernate 封装的时候 要往对象中去封装.将客户封装到Customer中将Customer对应的联系人封装到Customer的LinMan的集合中.

        //List<Customer> list = session.createQuery("from Customer c inner join fetch c.linkMans").list();

        List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();

        // System.out.println(list.size());

        for (Customer customer : list) {

            System.out.println(customer);

        }

        tx.commit();

    }

* 内连接和迫切内连接的区别:

    * 内连接:发送就是内连接的语句,封装的时候将每条记录封装到一个Object[]数组中,最后得到一个List<Object[]>.

    * 迫切内连接:发送的也是内连接的语句,在join后添加一个fetch关键字,Hibernate会将每条数据封装到对象中,最后List<Customer>. 需要去掉重复值.

    1. 相关知识点
      1. Hibernate的抓取策略:
        1. 延迟加载的分类:

【类级别的延迟加载】:类级别的延迟一般不修改.采用默认值即可.lazy=”true”

Customer customer = session.load(Customer.class,1l); // 通过一些延迟加载的方法load方法检索某个对象.这个对象是否采用延迟.

// 默认情况下类上的延迟是 lazy=”true”

***** 如何使延迟加载失效:

      * 在<class>标签上配置lazy=”false”

      * 定义类的时候采用final修饰.

      * Hibernate.initialize(Object proxy);

【关联级别的延迟加载】

Customer customer = session.get(Customer.class,1l);

Set<LinkMan> linkMans = customer.getLinkMans(); // 通过客户关联其联系人的对象.联系人是否采用延迟.

<set>上的lazy           :

<many-to-one>上的lazy   :

        1. 抓取策略:抓取其关联对象.

<set>和<many-to-one>标签上有一个fetch=””

        1. <set>集合上的fetch和lazy:

fetch:  控制的是查询其关联对象的时候采用的SQL语句的格式.

    * select    :默认值.  发送一条select语句查询其关联对象.

    * join      :发送 一条迫切左外连接查询关联对象.

    * subselect :发送 一条子查询查询其关联对象.

lazy:   控制的是查询其关联对象的时候是否采用延迟加载的策略.

    * true      :默认值. 默认查询联系人的时候采用延迟加载.

    * false     :查询关联对象的时候 不采用延迟加载.

    * extra     :及其懒惰. 查询关联对象的时候 采用比延迟加载更懒惰的方式进行查询.

        1. <many-to-one>上的fetch和lazy:

fetch:  控制查询其关联对象的SQL语句的格式

    * select    :默认值,发送普通的select语句查询

    * join      :发送一条迫切左外连接查询.

lazy:   查询其关联对象的时候是否采用延迟加载.

    * proxy     :默认值.是否采用延迟 取决于 一的一方的class上的lazy的值.

    * false     :不采用延迟加载其关联对象.

    * no-proxy  :不用研究

说明:由于个人能力有限,所以有些地方借鉴了他人的经验,如有错误,或者涉及侵权等问题,请及时告知,我会立即修改或者删除。谢谢各位。