Hibernate 笔记

发布于 2019-01-17  622 次阅读


hilbernate 框架

Hibernate 是框架的意思:

框架是什么?

​ 框架是为了提高开发效率.

​ 框架中封装好了一些功能, 我们需要使用这些功能的时候, 直接调用即可, 不在需要自己去实现(半成品).

​ 所以框架可以理解为一个半成品的项目, 只要懂得如何驾驭这些功能即可.

一个项目 被分为3个部分组成 web层 , Service层 , dao层; Hibernate(代替dao层) 将代替JDBC , DBUtil 层 Struts2(代替web层) 将代替Servlet , JSP 层 service层里面是 javaBean Spring 将包裹上面2个框架 Spring 项目的容器, 负责管理项目中的所有对象. Spring可以理解为管家.

Hibernate 的好处, 操作数据库的时候以面向对象的方式完成, 不在需要书写SQL语句.Hibernate是一款ORM的框架, ORM : object relation mapping(对象 关系映射);ORM 分为四级: (Hibernate 属于最顶级的ORM 框架,完全属于面向对象的框架) Hibernate属于四级 , 完全"面向对象"操作数据库. (三级没有) Mybatis 属于二级 DBUtils 属于一级

Hibernate 概述:

1.什么是框架:

​ 写一个程序, 使用框架之后会帮我们实现一部分功能, 少写一部分到吗, 就能实现某种功能.

2.什么是hibernate框架(重点):

​ 1.hibernate框架应用在javaee三层结构中dao层框架. 2.在dao层里面做对数据库crud操作, 使用hibernate实现crud操作, hibernate底层代码就是JDBC,hibernate对JDBC进行封装, 使用hibernate好处, 不需要写复杂的JDBC的代码,不需要写sql语句也能实现. 3.hibernate开源轻量级框架, 免费 源代码开源 不需要引用太多的jar包和其他的引用. 4.hibernate版本 3.x 4.x(过度产品) 5.x(学习) hibernate框架包中: documentation : 文档部分 lib : hibernate相关的jar包 project : 里面的源代码部分

3.什么是orm思想:

​ 1.hibernate使用orm思想对数据库进行crud操作. 2.在web阶段学习javabean.更正确的叫法 实体类. 3.orm:对象关系映射 o: object 对象 r: relation 关系 m: mapping 映射

文字描述:

(1).让实体类和数据库表进行一一对应关系. 让实体类首先和数据库对应 让实体类属性 和 表里面字段对应.(2).不需要直接操作数据库表, 而操作表对应实体类操作.

    //JDBC代码:
                //加载驱动
                Class.forName("com.mysql.jdbc.Driver");
                //创建连接:
                Connection conn = DriverManager.getConnection(url,username,password);
                //对sql进行预编译操作:
                PreparedStatment ps = conn.preparedStatement(sql);
                //执行sql,查询sql
                String sql = "select * from user";
                ResultSet rs = ps.executeQuery();
                //遍历结果集
                ......
                //释放资源
                ......

orm思想:

​ //实体类: public class User{ private int id; private String username; private String password; //set get方法 …… }

                //表的内容
                create table t_user(
                    uid id,
                    username varchar(100),
                    password varchar(100)
                )

                //让实体类与表进行一一对应:
                类和表对应,
                类里面的属性和表里面的字段对应,
                (不需要写代码,使用配置文件完成)

                //不需要操作表, 而操作表对应的实体类对象可以了.
                hibernate封装的对象Session

                //创建实体类的对象:
                User user = new User();
                user.setUsetname("小米");
                session.save(user); 

注意: 在框架阶段会使用很多的配置文件;

Hibernate 配置文件:

hibernate配置文件详解:

hibernhate 映射配置文件:

1.映射配置文件的名称和位置没有固定要求2.映射配置文件中, 标签 name属性值写实体类相关内容; (1).class 标签name属性实体类全路径 (2).id 标签和 property 标签name属性 实体类属性名称;3..id标签和property标签, column 属性可以省略的 (1).不写值金额name属性一样的4.property标签type属性, 设置生成表字段的类型, 自动对应类型;

hibernate 核心配置文件:

1.配置写位置在<hibernate-factory>标签里面2.配置三部分要求: (1).数据库部分必须的 (2).hibernate部分可选的 (3).映射文件必须的3.核心配置文件名称和位置是固定的 (1).位置: src下面 (2).名称: hibernate.cfg.xml

Hibernate 的API的使用:

Configuration

1.代码:

Configuration cfg = new Configuration().configure();(1).到src下面找到名称hibernate.cfg.xml配置文件,创建对象, 把配置文件放到对象里面(加载核心配置文件)

SessionFactory(重要)

1.使用configuration对象创建sessionFactory对象; (1).创建sessionfactory过程中做事情 根据核心配置文件中, 有数据库配置, 有映射文件部分, 到数据库里面根据映射关系, 将表创建(注意: 在核心配置文件中必须写下面配置才能自动创建); <property name="hibernate.hbm2ddl.auto">update</property>2.创建sessionFactory过程中, 这个过程特别耗资源的 (1).在hibernate操作中,建一个项目一般创建一个sessionFactory对象.3.具体实现(写一个工具类) (1).写工具类, 写静态代码块实现 静态代码块在类加载时候执行, 执行一次. HibernateUtils.java ==> com.yao.utils.HibernateUtils

Session(重点)

1.session类似于jdbc Connection连接2.调用session里面不同的方法实现crud操作; (1).添加sace方法 (2).修改update方法 (3).删除delete方法 (4).根据id查询get()方法3.session对象单线程对象. (1).session对象不能共有, 只能自己使用

Transaction

1.事物对象: Transaction ts = session.beginTransaction();2.事物提交和回滚方法: ts.commit(); //提交 ts.rollback();//回滚3.事物概念: (1).事物的四个特性: 原子性: 一组操作, 要么都成功,只要有一个失败, 事物就无法成功 一致性: 操作之前之后, 数据要一致 隔离性: 多个事物同时操作同一组数据, 之间不会产生影响 持久性: 最终事物要commit提交, 事物生效叫做持久性

解决配置文件没有提示的问题:

1.可以上网2.把约束文件引入到eclipes 里面 window ==> 最后一个 ==> 搜索xml c (1).在配置文件中复制一句话 http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd (2).URI 将上面的路径和 mapping文件的路径复制进去.

实体类的编写规则(重点):

1.实体类的属性必须是私有的2.私有属性必须使用GetSet方法操作3.要求实体类里面要有一个属性作为一个唯一值(一般都使用id值);4.实体类属性, 建议不使用基本数据类型, 使用基本数据类型对应的包装类; (1).八个基本数据类型对应的包装类; int = Integer char = character 其他的都是首字母大写 double = Double (2).比如 表示学生的分数, 假如int score 比如这个学生得了0分, int score = 0; 比如表示学生没有参加考试, int score = 0;(不能准确表示学生是否参加考试) 解决方法: 使用包装类, Integer score = 0,(表示学生得了0分) 表示学生没有参加考试, Integer score = null;

hibernate 主键生成策略:

1.hibernate要求实体类里面有一个属性作为唯一值, 对应表主键, 主键可以不同生成策略2.hibernate 主键生成策略有很多的值. <generator class="native"></generator>3.在上面标签的class属性里面. increment: 每次自增一 identity: (在Oracle里面不能使用),代理主键, 使用条件为主键定义为自增长类型 sequence: 支持生成序列,只能在Oracle里面使用 native(重要): 根据使用的数据库,会自动帮你选择用那个值 uuid(重要): 之前web阶段,需要写代码生成uuid值, hibernate帮我们生成uuid值 (1).使用uuid生成策略, 实体类id属性 必须 字符串类型 (2).配置部分uuid值;(不写值会生成十六进制数字) assigned:

实体类操作:

1.crud操作(重点):

添加操作:

1.调用session里面的save方法实现:

User user = new User();
user.setUsername("小yooo");
user.setPassword("2333");
user.setAddress("越南");
//调用session1实现添加
session.save(user);

根据id查询:

1.调用session里面的get方法;

    //调用session里面的get方法
    //第一个参数:实体类的class
    //第二个参数: 要查询id的值
    User user = session.get(User.class, 1);
    System.out.println(user);

修改操作:

1.首先查询,再修改

(1).先根据id查询,返回对象
//4.添加操作
//第一步: 根据id查询
User user = session.get(User.class, 2);
//第二步: 向返回的user对象里面设置修改之后的值
user.setUsername("york");
//第三步:调用session里面update方法修改
//执行过程: 到user对象里面找到uid的值,根据id修改
session.update(user);

删除操作:

1.调用session里面的delete方法实现:

    //第一种方式: 根据id查询对象
    User user = session.get(User.class, 2);
    session.delete(user);
    //第二种方法:
    User user = new User();
    user.setUid(3);
    session.delete(user);   
2.实体类对象状态(概念):
1.实体类有三种状态:

(1).瞬时态

//对象里面没有id值,与session没有关联
//例:
    User user = new User();
    user.setUsername("小yooo");
    user.setPassword("2333");
    user.setAddress("越南");

(2).持久态

//对象里面有id值, 与session有关联
//例:
User user = session.get(User.class, 1); 

(3).托管态

//对象里面有id值, 与session没有关联
//例:
    User user = new User();
    user.setUid(3);
2.演示操作实体类的操作:

(1).saveOrUpdate方法: 实现添加, 实现修改.

User user = new User();
user.setUsername("jack");
user.setPassword("666");
user.setAddress("越南");  
//实体类对象状态是瞬时态, 则进行添加操作
session.saveOrUpdate(user);
​
User user = new User();
user.setUid(2);
user.setUsername("jim");
user.setPassword("2222");
user.setAddress("北京");
//实体类状态为托管态的时候, 则进行修改操作
session.saveOrUpdate(user);
​
User user = session.get(User.class, 1);
user.setUsername("tom");
//实体类为持久态的时候, 则进行修改操作
session.saveOrUpdate(user);

hibernate 的一级缓存

什么是缓存:

1.数据存到数据库里面, 数据库本身是文件系统, 使用流方式操作文件效率不是很高. (1).把数据存到内存中, 不需要使用流的方式, 可以直接读取内存中数据 (2).把数据放到内存中, 提供读取效率

hibernate 缓存

1.hibernate框架中提供了很多优化, hibernate 的缓存就是一个优化方法.2.hibernate 缓存特点: 第一类: hibernate 的一级缓存 (1).hibernate 的一级缓存默认就是打开的. (2).hibernate 的一级缓存有使用范围.是session的范围, 从session创建到session关闭范围 (3).hibernate 的一级缓存中, 存储数据必须是 持久态数据

​ 第二类: hibernate 的二级缓存 (1) 目前已经不使用了, 替代技术 redis (2)二级缓存默认不是打开的, 需要配置 (3)二级缓存使用范围, 是sessionFactory范围.

验证一级缓存存在: 1.验证方式: (1)首先根据uid=1查询, 返回对象 (2)其次再根据uid=1查询, 返回对象

//1.根据uid=1查询
            //执行了第一个get方法后是否会查询数据库, 是否发送sql语句
            User user1 = session.get(User.class, 1);
            System.out.println(user1);
            //2.再根据uid=1查询
            ////执行了第二个get方法后是否会查询数据库, 是否发送sql语句
            User user2 = session.get(User.class, 1);
            System.out.println(user2);
/*
        结果:
            Hibernate: 
                select
                    user0_.uid as uid1_0_0_,
                    user0_.username as username2_0_0_,
                    user0_.password as password3_0_0_,
                    user0_.address as address4_0_0_ 
                from
                    t_user user0_ 
                where
                    user0_.uid=?
                User [uid=1, username=小王, password=6666, address=日本]
                User [uid=1, username=小王, password=6666, address=日本]
*/

结论:

​ 第一次执行了get方法之后, 发送sql语句查询数据库 第二次执行get方法之后,没有发送sql语句查询数据库

hibernate 一级缓存执行过程

1.首先查询一级缓存, 查询一级缓存有没有数据, 没有就去查询数据库, 然后user1对象(持久态对象) 其次, 把user1持久态对象放到一级缓存中2..user2 ,再次查询, 先查询一级缓存, 发现一级缓存有相同的数据, 直接返回

hibernate 一级缓存特性:

1.持久态自动更新数据库;

//执行操作
//1.根据id查询
User user = session.get(User.class, 1);//持久态对象
//2.设置返回对象值
user.setUsername("hanmeimei");
//3.调用update方法
//session.update(user);

2.执行过程(了解):

​ 一旦创建session, 就会出现一级缓存, 而在一级缓存出现, 这会有一块对应的区域出现 快照区(副本)

hibernate事务操作

事务相关概念:

1.什么是事务

​ 要么都成功, 要么都失败;(银行转账就是最好的例子)

2.事务特性:

​ 原子性,一致性,隔离性,持久性

3.不考虑隔离性产生问题

(1).脏读(2).不可重复读(3).虚读

4.设置事物隔离级别

(1).MySql默认的隔离级别 REPEATABLE_READ (repeatable_read)

hibernate 事务代码规则写法(重点):

1.结构代码

try{ 开启事物 提交事物 }catch{ 回滚事物 }finally{ 关闭 }

@Test
public void testTx(){
    SessionFactory sessionFactory = null;
    Session session = null;
    Transaction tx = null;
    try {
        //得到sessionFactory
        sessionFactory = HibernateUtils.getSessionFactory();
        //开启session
        session = sessionFactory.openSession();
        //开启事务
        tx = session.beginTransaction();
​
        //添加
        User user = new User();
        user.setUsername("Tom");
        user.setPassword("3322");
        user.setAddress("美国");
        session.save(user);
​
        //提交事物
        tx.commit();
    } catch (Exception e) {
        e.printStackTrace();
        //出现异常回滚事务
        tx.rollback();
    }finally {
        //关闭事务
        session.close();
        sessionFactory.close();
    }
}

hibernate 绑定 session

1.session 类似与JDBC的connection, 之前web阶段学过threadLocal2.帮我们实现与本地线程绑定的session3.获取与本地线程绑定的session (1).在hibernate核心配置文件中配置 <!-- 配置与本地线程绑定的session --> <property name="hibernate.current_session_context_class">thread</property> (2).调用sessionFactory里面的方法 //提供返回与本地线连接的session方法 public static Session getSessionobject(){ return sessionFactory.getCurrentSession(); }4.获取与本地线程绑定session时候, 关闭session报错, 当获取本地session绑定的时候, 就不需要手动关闭了. 会有异常出现: Session was already closed

hibernate 其他API查询(重点):

Query对象

1.使用Query对象, 不需要使用sql语句, 但是写hql语句 (1).hql: h: hibernate; q: query; l:language; 这个hql语句和普通sql语句很相似. (2).hql和sql的区别: 使用普通的sql操作表和表字段. 使用hql操作实体类和实体类的属性. 2.查询所有hql语句 (1). from 实体类的名称;3.Query 对象的使用 (1).创建一个Query对象 (2).调用Query对象里面的方法得到结果

//1.创建Query对象
Query query = session.createQuery("from User");
//2.调用Query对象里面的方法得到结果
List<User> list = query.list();
for (User user : list) {
    System.out.println(list);
}

Criteria对象

1.使用这个对象查询到操作, 但是使用这个对象时, 不需要写语句, 直接调用方法实现2.实现过程: (1).创建criteria对象 (2).调用方法得到结果

//1.创建Criteria对象
//方法里面的参数是实体类的class
Criteria criteria = session.createCriteria(User.class);
//调用方法得到结果
List<User> list = criteria.list();
for (User user : list) {
    System.out.println(user);
}

SQLQuery对象

1.使用hibernate时候, 调用底层sql实现.2.实现过程: (1).创建SQLQuery对象 (2).调用方法得到结果

//1.创建SQLQuery对象
//参数就是普通的sql语句
SQLQuery SQLQuery = session.createSQLQuery("select * from t_user");
//调用SQLQuery里面的方法;
//返回的list集合, 默认里面每部分数组结构
List<Object[]> list = SQLQuery.list();
for (Object[] objects : list) {
    //Arrays.toString() 可以把数组作为字符串输出.
    System.out.println(Arrays.toString(objects));
}

注意: 返回的list集合是数组;

返回list中每部分是对象形式:

//1.创建SQLQuery对象
//参数就是普通的sql语句
SQLQuery SQLQuery = session.createSQLQuery("select * from t_user");
//返回的list中每部分是对象形式
//设置数据 ,放到那个实体类中
SQLQuery.addEntity(User.class);
//调用SQLQuery里面的方法
List<User> list = SQLQuery.list();
for (User user : list) {
    System.out.println(user);
}

注意: 返回的结果 是对象形式.

表与表之间关系回顾:

1.一对多

​ (1).分类和商品的关系, 一个分类里面有多个商品, 一个商品只能属于一个分类; (2).客户和联系人是一对多关系 客户: 与公司有业务往来, 百度, 新浪, 360 联系人: 公司里面的员工, 百度里面有很多的员工, 联系员工 公司和公司员工的关系. 客户是一, 联系人是多. 一个客户里面有多个联系人, 一个联系人只能属于一个客户. (3).一对多建表, 通过外键.

2.多对多

​ (1).订单和商品关系, 一个订单里面有多个商品, 一个商品属于多个订单 (2).用户和角色多对多的关系. 用户: 小王,小马,小宋. 角色: 总经理,秘书,司机,保安. 比如小王 可以是总经理, 也可以是司机 比如小宋 可以是司机, 可以是秘书, 可以是保安 比如小马 可以是秘书, 可以是总经理. 一个用户里面可以有多个角色, 一个角色里面可以有多个用户. (3)多对多, 创建第三张表来维护之间的关系 第三张表至少有两个字段作为外键, 指向两个表主键.

3.一对一

​ (1)在中国, 一个男人只能有一个妻子, 一个女人只能有一个丈夫.

(1).一对多(客户和联系人)(2).多对多(用户和角色)

hibernate 一对多操作:

(1).一对多映射配置

​ (以客户和联系人为例,客户是一,联系人是多) 第一步:导入jar包 第二步:创建实体类(两个,一个客户的,一个联系人) 第三步:让这两个实体类之间相互表示. (1).在客户实体类里面表示多个联系人. 一个客户里面多个联系人.

//在客户实体类里面表示多个联系人, 一个客户有多个联系人.
//hibernate要求使用集合表示多的数据,使用set集合.
private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();
​
public Set<LinkMan> getSetLinkMan() {
    return setLinkMan;
}
public void setSetLinkMan(Set<LinkMan> setLinkMan) {
    this.setLinkMan = setLinkMan;
}

(2).在联系人实体类里面表示所属客户.

​ 一个联系人只能属于一个客户.

//在联系人里面表示所属客户,一个联系人只能属于一个客户.
private Customer customer;
public Customer getCustomer() {
    return customer;
}
public void setCustomer(Customer customer) {
    this.customer = customer;
}

第四步: 配置映射关系:

(1).一个实体类对应一个映射文件(2).把映射最基本的配置完成(3).在映射文件中,配置一对多的关系 在客户的映射文件中,表示所有的联系人

<!-- 
      在客户的映射文件中,表示所有的联系人 
      使用set标签表示所有的联系人
      set标签里面有name属性, 属性值写在客户实体类里面表示联系人的set集合名称
     -->
<set name="setLinkMan">
    <!-- 
       一对多建表,有外键.
       hibernate机制, 双向维护外键, 在一和多那一方都配置外键.
       column属性值就是外键的名称
       -->
    <key column="clid"></key>
    <!-- 客户所有的联系人,class里面写联系人实体类的全路径 -->
    <one-to-many class="com.yao.entity.LinkMan"/>
</set>

在联系人中,表示所属的客户.

<!-- 
       表示联系人所属的客户
       name属性: 因为在联系人实体类使用customer对象表示,写customer名称
       class属性: customer全路径
       column属性: 外键的名称clid
       -->
<many-to-one name="customer" class="com.yao.entity.Customer" column="clid"></many-to-one>

第五步:创建核心配置文件, 把映射文件映入到核心配置文件中

<mapping resource="com/yao/entity/Customer.hbm.xml"/>
<mapping resource="com/yao/entity/LinkMan.hbm.xml"/>

第六步: 测试, 执行工具类

级联操作:

(2).一对多级联保存

1.级联保存 (1).添加了客户, 为这个客户添加了多个联系人

​ (添加客户,为这个客户添加一个联系人)

//添加一个客户,为这个客户添加一个联系人.
//1.创建客户跟联系人的对象
Customer customer = new Customer();
customer.setCustName("同福客栈");
customer.setCustLevel("vip");
customer.setCustSource("网络");
customer.setCustPhone("110");
customer.setCustMobilb("666");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("lucy");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("911");
//2.在客户里面表示联系人, 在联系人里面表示客户
//建立客户人对象和联系人对象的关系
//2.1 把联系人的对象放到客户实体类对象的set集合里面
customer.getSetLinkMan().add(linkMan);
//2.2 把客户对象放到联系人里面
linkMan.setCustomer(customer);
//3.保存到数据库
session.save(customer);
session.save(linkMan);
简化写法:(根据客户添加联系人)

​ 第一步: 在客户映射文件中进行配置; 在客户映射配置文件中 set标签内进行配置 属性==> cascade="save-update" <set name="setLinkMan" cascade="save-update"> 第二步:创建客户和联系人对象,只要把联系人放到客户里面就可以了,最终只需要保存客户就可以了.

//1.创建客户跟联系人的对象
Customer customer = new Customer();
customer.setCustName("龙门客栈");
customer.setCustLevel("普通客户");
customer.setCustSource("网络");
customer.setCustPhone("949");
customer.setCustMobilb("2233");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("小花");
linkMan.setLkm_gender("女");
linkMan.setLkm_phone("666");
//2.把联系人放到客户里面
customer.getSetLinkMan().add(linkMan);
//3.保存客户
session.save(customer);
session.save(linkMan);      
(3).一对多级联删除

(1).删除某一个客户, 这个客户里面的所有联系人也删除 (删除某个客户,把客户里面所有的联系人删除) 第一步:在客户映射文件set标签`,进行配置==> cascade="save-delete" (注意, 多个属性用逗号隔开) (1).使用属性cascade="save-update,delete" 第二步:在代码中直接删除客户. (1).先根据id查询对象,在调用session里面的delete方法删除

//1.根据id查询出客户对象
Customer customer = session.get(Customer.class, 2);
//2调用方法删除
session.delete(customer);   

执行过程: (1).根据id查询客户 (2).根据外键查询联系人 (3).把联系人的外键设置为null; (4).删除联系人和客户

(4).一对多修改操作

1.让lucy联系人所属客户不是同福, 而是龙门

//1.根据id查询lucy联系人, 根据id查询百度的客户
Customer Tongfu = session.get(Customer.class, 3);
LinkMan lucy = session.get(LinkMan.class, 1);
//2.设置持久态对象值
//把联系人客户里面
Tongfu.getSetLinkMan().add(lucy);
//把客户放到联系人里面
lucy.setCustomer(Tongfu);
(5).inverse属性

1.因为hibernate双向维护外键,在客户和联系人里面都需要维护外键, 修改客户的时候修改一次外键, 修改联系人的时候也修改一次外键, 造成效率问题.2.解决方式: 让其中一的一方不维护外键 一对多里面, 让其中一方放弃对外键的维护. 一个国家有总统, 国家有很多人, 总统不能这个国家所有的人, 国家所有的人认识总统.3.具体实现: 在放弃关系维护映射文件中, 进行配置, 在set标签上使用inverse属性

<!-- 
       inverse属性默认是false不放弃关系维护
              true 放弃关系维护
      -->
<set name="setLinkMan" cascade="save-update,delete" inverse="true">

hibernate 多对多操作:

(1).多对多映射配置

以用户和角色为例演示: 第一步: 创建实体类: 用户和角色 第二步: 两个实体类之间相互表示 (1).用户里面表示所有角色,使用set集合 (2).一个角色多个用户,使用set集合 第三步: 配置映射关系 (1). 基本配置 (2). 配置多对多关系 在用户里面表示所有的角色, set标签

<!-- 
        在用户里面表示所有角色, 使用set标签
         name属性, 角色set集合名称
         table属性, 第三张表的名称
        -->
<set name="setRole" table="user_role">
    <!-- key标签里面要配置当前的映射文件在第三张表中外键名称 -->
    <key column="userid"></key>
    <!-- 
         class: 角色实体类全路径
         column: 角色在第三张表外键名称
         -->
    <many-to-many class="com.yao.entity.Role" column="roleid"></many-to-many>
</set>

在角色里面表示所有的用户, set标签

    <!-- 在角色里面表示所有的用户, set标签 -->
<set name="setUser" table="user_role">
    <!-- 角色在第三张表的外键 -->
    <key column="roleid"></key>
    <many-to-many class="com.yao.entity.User" column="userid"></many-to-many>
</set>

第四步: 在核心配置文件中映入配置文件

<mapping resource="com/yao/entity/User.hbm.xml"/>
<mapping resource="com/yao/entity/Role.hbm.xml"/>

第五步: 测试 运行utils类, 查看数据库是否创建三张表.

(2).多对多级联保存(重点)

根据用户保存用户 第一步: 在用户映射配置文件中 set标签进行配置, cascade值 save-update

<set name="setRole" table="user_role" cascade="save-update">

​ 第二步: 写代码实现 (1).创建用户和角色, 把角色放到用户里面, 最终保存用户就可以了.

//添加连个用户, 为没有用户添加两个角色
User user1 = new User();
user1.setUser_name("lucy");
user1.setUser_password("123");
User user2 = new User();
user2.setUser_name("mary");
user2.setUser_password("456");
Role role1 = new Role();
role1.setRole_name("总经理");
role1.setRole_memo("总经理");  
Role role2 = new Role();
role2.setRole_name("秘书");
role2.setRole_memo("秘书");           
Role role3 = new Role();
role3.setRole_name("保安");
role3.setRole_memo("保安");
//2.建立关系,把角色放到用户里面
//user1 ==> r1/r2
user1.getSetRole().add(role1);
user1.getSetRole().add(role2);
//user2 ==> r2/r3
user2.getSetRole().add(role2);
user2.getSetRole().add(role3);
//3.保存用户
session.save(user1);
session.save(user2);

(3).多对多级联删除

​ 第一步: 在set标签里面进行配置,cascade 里面 save-update,delete

<set name="setRole" table="user_role" cascade="save-update,delete">

​ 第二步:(注意: 一般不用, 删除会将相关联的表的全部数据删除)

//级联删除
User user = session.get(User.class, 1);
session.delete(user);

(4).维护第三张表

1.用户和叫是多对多关系, 维护关系是通过第三张表维护2.让某个用户有某个角色 第一步: 先根据id查询用户和角色 第二步: 把角色对象放到用户里面 (1).把角色对象放到用户set集合

//让lucy有经纪人的角色
//1.查询lucy和经纪人
User lucy = session.get(User.class, 1);
Role role = session.get(Role.class, 4);
//2.把角色放到用户的set集合里面
lucy.getSetRole().add(role);

3.让某个用户没有某个角色. 第一步: 先根据id查询用户和角色 第二步: 从用户里面把角色去掉 (1).从set集合里面把角色移除

//让lucy有经纪人的角色
//1.查询lucy和经纪人
User lucy = session.get(User.class, 2);
Role role = session.get(Role.class, 3);
​
//从用户里面把角色去掉
lucy.getSetRole().remove(role);

hibernate 查询方式:

1.对象导航查询

(1).根据id查询某个客户, 在查询这个客户里面所有联系人.(2).查询某个客户里面所有联系人过程, 使用对象导航实现.

//根据cid=1客户, 在查询这个客户里面所有的联系人
Customer customer = session.get(Customer.class, 1);
//在查询这个客户里面所有的联系人
//直接得到客户里面联系人的set集合.
Set<LinkMan> linkMan = customer.getSetLinkMan();
System.out.println(linkMan.size());

2.OID 查询

(1).根据id查询某一条记录, 返回对象的形式(2).调用session里面的get方法;

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

3.hql 查询

(1).Query对象, 写hql语句实现查询(2).hql: hibernate query language, hibernate提供的一种语言.hql语言和普通sql相似. 区别: 普通sql操作数据库表和字段, hql操作实体类和属性.(3).常用的hql语句(4).使用hql查询操作时候, 使用query对象. (1).创建Query对象,写hql语句. (2).调用Query对象里面的而方法得到结果.(5)常用查询: 1.查询所有:(重点) (1).创建Query对象,写hql语句(from 实体类的名称) (2).调用query对象里面的方法得到结果.

//创建Query对象
Query query = session.createQuery("from Customer");
//2.调用方法得到结果
List<Customer> list = query.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + " , " + customer.getCustName());
}

​ 2.条件查询(重点)

​ (1).hql条件查询语句的写法: from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?

//1.创建Query对象
Query query = session.createQuery("from Customer where cid=? and custName=?");
//2.设置条件值
//向?里面设置值
//setParameter 方法两个参数
//第一个参数: int类型是?位置, ?位置从0开始.
//第二个参数: 具体参数值
//设置第一个?的值
query.setParameter(0, 1);
//设置第二个?的值
query.setParameter(1, "同福客栈");
//3.调用方法得到结果
List<Customer> list = query.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + " , " + customer.getCustName());
}
1.模糊查询(重点)

(1).hql语句: from 实体类名称 where 属性名称 like ? .

//1.创建Query对象
Query query = session.createQuery("from Customer where custName like ?");
//设置?的值
//_客_ %客 %客%
query.setParameter(0,"%客%");
//3.调用方法得到结果
List<Customer> list = query.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + " , " + customer.getCustName());
}
2.排序查询 (重点)

(1).hql语句: from 实体类名称 order by 实体类属性名称 desc/asc.

//1.创建Query对象
Query query = session.createQuery("from Customer order by cid desc");
//2.调用方法
List<Customer> list = query.list();
​
for (Customer customer : list) {
    System.out.println(customer.getCid() + " , " + customer.getCustName());
}
3.分页查询(重点)

(1)Mysql实现分页 关键字: limit(2).hql中实现分页 1.在hql操作中, 在语句中不能写limit, hibernate 的Query对象封装两个方法实现分页操作.

//1.创建Query对象
Query query = session.createQuery("from Customer");
//2.设置分页的那些数据
//2.1 设置开始位置
query.setFirstResult(0);
//2.2 设置每页记录数
query.setMaxResults(3);
//3.调用方法得到结果
List<Customer> list = query.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + " , " + customer.getCustName());
}
4.投影查询

(1).投影查询: 查询不是所有字段值, 而是部分字段值.(2).投影查询hq语句写法: 1. select 实体类属性名称1,实体类属性名称2 from 实体类名称 2. select 不能写*号, 不支持.

//1.创建Query对象
Query query = session.createQuery("select custName from Customer");
//2.调用方法得到结果
List<Object> list = query.list();
​
for (Object object : list) {
    System.out.println(object);
}
5.聚合函数使用

(1).常用的聚集函数 1.count(统计个数), sum(相加), avg(平均数), max(最大值), min(最小值)(2).查询表记录数: select count(*) from 实体类名称.

//1.创建Query对象
Query query = session.createQuery("select count(*) from Customer");
//2.调用方法得到结果
//Query对象里面有方法, 直接返回对象形式
Object object = query.uniqueResult();
//System.out.println(object);   
//返回int类型 有类型转换异常
//int count = (int)object;
//首先要把object变成long类型,再转化为int;
Long lobj = (Long)object;
int count = lobj.intValue();
System.out.println(count);

4.QBC 查询

1.使用hql查询的时候需要写hql语句查询, 而使用QBC查询, 不需要使用语句, 使用方法实现2.使用QBC时候, 操作实体类属性3.使用QBC, 使用Criteria对象实现4.QBC相关查询:

(1).查询所有

​ 1.创建Criteria对象 2.调用方法得到结果

//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.调用方法得到结果
List<Customer> list = criteria.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + "  ,  " + customer.getCustName());
}
(2).条件查询

1.没有语句, 使用封装的方法实现.

//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.使用criteria对象里面的方法设置条件值
//首先使用add方法,表示设置属性值
//在add方法里面使用类的方法实现条件设置;
//类似与cid=?
criteria.add(Restrictions.eq("cid", 1));
criteria.add(Restrictions.eq("custName", "同福客栈"));
//3.调用方法得到结果
List<Customer> list = criteria.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + "  ,  " + customer.getCustName());
}
(3).模糊查询
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.使用criteria对象里面的方法设置条件值
//首先使用add方法,表示设置属性值
//在add方法里面使用类的方法实现条件设置;
//类似与cid=?
criteria.add(Restrictions.like("custName", "%客栈%"));
//3.调用方法得到结果
List<Customer> list = criteria.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + "  ,  " + customer.getCustName());
}

(4).分页查询

​ 开始位置计算公式: 当前页 - 1 * 每页记录数

//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.设置分页的数据
//2.1 设置开始位置
criteria.setFirstResult(0);
//2.2 设置显示记录数
criteria.setMaxResults(3);
//3.调用方法得到结果
List<Customer> list = criteria.list();
for (Customer customer : list) {
    System.out.println(customer.getCid() + "  ,  " + customer.getCustName());
}
(5).统计查询
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.设置操作
criteria.setProjection(Projections.rowCount());
//3.调用方法得到结果
Object obj = criteria.uniqueResult();
Long lobj = (Long)obj;
int count = lobj.intValue();
System.out.println(count);
(6).离线查询

1.servlet调用service. service调用dao (1).在到里面对数据库crud操作 (2).在到里面使用hibernate框架, 使用hibernate框架时候, 调用session里面的方法实现功能.

//1.创建对象
//Criteria criteria = session.createCriteria(Customer.class);
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
//2.最终执行的时候才需要到session
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
​
List<Customer> list = criteria.list();
for (Customer customer : list) {
    System.out.println(customer);
}

HQL多表查询:

Mysql里面多表查询

​ 1.内连接查询 select * from t_customer c,t_linkman l where c.cid=l.clid; select * from t_customer c inner join t_linkman l on c.cid=l.clid; 2.左外连接 select * from t_customer c left outer join t_linkman l on c.cid=l.clid; 3.右外连接 select * from t_customer c right outer join t_linkman l on c.cid=l.clid;

HQL实现多表查询

HQL多表查询
(1).内连接

1.内连接查询hql语句写法:(以客户和联系人为例) (1).from Customer c inner join c.setLinkMan

//1.创建Query对象
Query query = session.createQuery("from Customer c inner join c.setLinkMan");
List list = query.list();
//返回list, list里面每部分是数组形式.
(2).左外连接

(1)hql语句:from Customer c left outer join c.setLinkMan; (2).左外连接返回list每部分都是数组的形式, 迫切左外连接则是对象形式.

//1.创建Query对象
Query query = session.createQuery("from Customer c left outer join c.setLinkMan");
List list = query.list();
(3).右外连接

(1)hql语句: from Customer c right outer join c.setLinkMan; (2).返回结果还是数组形式, 且没有迫切右外连接

//1.创建Query对象
Query query = session.createQuery("from Customer c right outer join c.setLinkMan");
List list = query.list();
(4).迫切内连接

(1).迫切内连接和内连接底层实现一样的(2).区别: 使用普通的内连接返回的list中每部分是数组, 迫切内连接返回list每部分是对象(3).hql语句:from Customer c inner join fetch c.setLinkMan;

//1.创建Query对象
Query query = session.createQuery("from Customer c inner join fetch c.setLinkMan");
List list = query.list();
(5).迫切左外连接

(1).from Customer c left outer join fetch c.setLinkMan;

//1.创建Query对象
Query query = session.createQuery("from Customer c left outer join fetch c.setLinkMan");
List list = query.list();

hibernate 检索策略

1.检索策略的概念:

(1)立即检索/立即查询

​ 根据id查询,调用get方法, 一调用get方法就马上发送查询语句查询数据库.

//根据cid=1客户
//get方法执行之后, 是否发送sql语句.
//调用get方法马上发送sql语句查询数据库
Customer customer = session.get(Customer.class, 1);
System.out.println(customer.getCid());

(2)延迟查询

​ 根据id查询,还有load方法, 不会马上发送语句查询数据库, 只有得到对象里面的值的时候才会去发送语句查询数据库.

//根据cid=1客户
/*
    1.调用load方法之后, 不会马上发送sql语句
        (1). 返回对象里面只有id值
    2.得到对象里面不是id的其他值的时候才会发送sql语句.
*/
Customer load = session.load(Customer.class, 1);
System.out.println(load.getCid());
System.out.println(load.getCustName());

2.延迟查询中有分为两类

(1).类级别延迟

​ 根据id查询返回实体类对象, 调用load方法不会马上发送sql语句

//根据cid=1客户
/*
        1.调用load方法之后, 不会马上发送sql语句
                (1). 返回对象里面只有id值
        2.得到对象里面不是id的其他值的时候才会发送sql语句.
 */
Customer load = session.load(Customer.class, 1);
System.out.println(load.getCid());
System.out.println(load.getCustName());

(2).关联级别的延迟

​ 查询某个客户, 在查询这个客户所有联系人, 查询客户的所有联系人的过程是否需要延迟, 这个过程称为关联级别延迟.

3.关联基本延迟操作:

1.在映射文件中进行配置实现

​ (1).根据客户得到所有联系人, 在客户映射文件中配置

2.在set标签上使用两个属性:

(1)fetch 值 select(默认)(2)lazy : 值 - true : 延迟(默认) - false : 不延迟 1.调用get方法后, 直接执行两条查询语句. - extra : 及其延迟/及其懒惰 1.要什么值给什么值, 不要不给

批量抓取:

​ 1.查询所有的客户, 返回list集合, 遍历这个list集合, 得到每个客户, 得到每个客户的所有联系人.

//查询所有的客户
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
//得到所有客户里面所有的联系人
for (Customer customer : list) {
    System.out.println(customer.getCid() + "  ,  " + customer.getCustName());
    Set<LinkMan> setLinkMan = customer.getSetLinkMan();
    for (LinkMan linkMan : setLinkMan) {
        System.out.println(linkMan.getLkm_id() + "  ,  " + linkMan.getLkm_name());
    }
}
//上面代码发送多条sql语句, 效率极地

批量抓取代码:

1.在客户的set表里里面 batch-size

<set name="setLinkMan" cascade="save-update,delete" inverse="true" batch-size="10">

里面的值, 越大执行越快, 减少语句发送

//查询所有的客户
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
//得到所有客户里面所有的联系人
for (Customer customer : list) {
    System.out.println(customer.getCid() + "  ,  " + customer.getCustName());
    Set<LinkMan> setLinkMan = customer.getSetLinkMan();
    for (LinkMan linkMan : setLinkMan) {
        System.out.println(linkMan.getLkm_id() + "  ,  " + linkMan.getLkm_name());
    }
}

Hibernate框架的搭建:

1.导包

​ 1.1 : Hibernate核心包(hibernate-release-5.0.7.Final.zip ==> lib ==> required(必须的意思) ==> 里面所有的包) 1.2 : Hibernate驱动包(是Mysql就用mysql的包 , 是oracle就用oracle的包)

2.创建数据库,准备表

​ cst_customer(表名)

3.书写ORM元数据(对象与表的映射配置文件; "元数据"理解为ORM的"映射文件")

​ 3.1 : 导入约束.(Liberaries ==> Web App Liberaries ==> hibernate-core-5.0.7.Final.jar ==> org.hilbernate ==> hilbernate-configuration-3.0(4.0).xsd ) Window ==> preferences ==> XML ==> XML Catalog ==> Add ==> File System ==> (将dtd文件选中, 自己的 hibernate-configuration-3.0.dtd 文件) ==> Key type选择URL ==> Key的路径是hilbernate-configuration-3.0(4.0).xsd 这个文件注释中的路径 http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd 3.2 : (进入)实体类编写 3.3 : 书写ORM元数据 (看Customer.hbm.xml的配置信息) hibernate-release-5.0.7.Final.zip ==> project ==> etc(下面放的配置文件) ==> hiberbate.properties 里面全部都是要用到的信息(在里面找到Mysql 或 Oracle 的配置)

4. 书写主配置文件

​ 连接数据库的相关配置信息(文件名必须(框架名.config.xml)hibernate.cfg.xml)

5. 书写代码测试

例:

类名.hbm.xml
<!-- 这个头不建议手写, 建议coby -->
<?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">
<!-- 头到这结束 -->
    <!-- 配置与实体对象的关系 (配置文件的根元素); package 指包名, 填写包名 ; 必须先配置package属性,在元素内部凡是需要书写完整的类名的属性, 可以直接写简单的类名-->
    <hibernate-mapping package="com.yao.www.bean">
        <!-- class中要带有两个行内属性, name 和table -->
        <!--
             calss元素: 配置 实体与表的对应关系的
             name : 完整类名
             table : 数据库表名
        -->
        <class name="完整的实体类的名字路径" table="数据库中表的名字">
            <!-- id中要带有两个行内属性, name 和 column(是对应数据库中的某个列) -->
            <!-- id:用来配置主键映射的属性 ; name属性填写主键对应属性名 ; column填写表中主键的列名-->
            <id name="实体类中的属性名id" column="与实体类中的属性名对应的数据库中的列名id">
                <!-- generator : 主键生成策略(后面详述) -->
                <generator class="notive"></generator>
            </id>
            <!-- property中 ,要添加column属性-->
            <!-- property的数量与数据库中列的数量一致 -->
            <!-- 
                property : 用来配置除了id之外的属性的映射 ; 
                name属性填写对应属性名 ; 
                column(可选)填写表中列名  默认值是列名会使用属性名;
                type(可选,hibernate会自动检测实体的类型, 要写可以三种类型 :
                                                        java类型 : 例: java.long.String
                                                        hibernate类型 : 例: string
                                                        sql类型 : 例 : <property name="" colum="id">
                                                                        <colum name="id" sql-type="varchar"></colum>
                                                                    </property>
                not_null :(可选) 配置该属性的列是否不能为空;(默认是false)
                length :(可选) 配置数据库列的长度, 默认值是(当前数据库类型的最大长度255)
                是填写列(属性)的类型 (上面id里面也可以写这些属性)
            -->
            <property name="name" column="name" type=""></property>
            <property name="age" column="age"></property>
        </class>
    </hibernate-mapping>

配置文件详解:

分为三部分:

1.ORM元数据
2.hibernate主配置
必选属性(5个)

1.驱动 ==> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 2.数据库连接驱动(/// 代表localhost(本机) , 后面写数据库名称) ==> <property name="hibernate.connection.url">jdbc:mysql:///数据库名称</property> 3.数据库账号 ==> <property name="hibernate.connection.username">root</property> 4.数据库密码 ==> <property name="hibernate.connection.password">root</property>

可选属性(3个)

​ sql语句打印到控制台: <property name="hibernate.show_sql">true</property> sql语句的格式格式化(缩进): <property name="hibernate.format_sql">true</property> 创建新表的时的操作: <property name="hibernate.hbm2ddl.auto">update</property>

元数据的引入配置

​ <!-- 引入orm的元数据 ; 路径书写规范 : 填写Src下的路径 --> <mapping resource="com/yao/www/bean.hbm.xml"/>

hibernate.cfg.xml
<?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框架 -->    
    <<hibernate-configuration>
        <session-factory>
        <!-- 
            #hibernate.dialect org.hibernate.dialect.MySQLDialect
            #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
            #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
            #hibernate.connection.driver_class org.gjt.mm.mysql.Driver
            #hibernate.connection.driver_class com.mysql.jdbc.Driver
            #hibernate.connection.url jdbc:mysql:///test
            #hibernate.connection.username gavin
            #hibernate.connection.password
         -->
            <!-- 必选配置 -->
            <!-- 数据库驱动 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <!-- 数据库url  ; /// 代表localhost(本机) , 后面写数据库名称-->
            <property name="hibernate.connection.url">jdbc:mysql:///数据库名称</property>
            <!-- 数据库账号 -->
            <property name="hibernate.connection.username">root</property>
            <!-- 数据库密码 -->
            <property name="hibernate.connection.password">root</property>
            <!-- 数据库方言 例: Mysql的分页limit 就是Mysql的方言;
                            不同的数据库中sql语句略有区别, 指定方言可以让Hibernate框架在生成sql语句时, 针对数据库的方言生成.
                            sql99标准: DDL(数据定义语言) 库表的增删改查
                                      DCL(数据控制语言) 事物权限
                                      DML(数据操纵语言)增删改查
                                      TCL(事务控制语言)(X)
                            注意事项:   MySql在选择方言时, 请选择最短的方言.    
            -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

            <!-- 可选配置 -->
            <!-- 
                #hibernate.show_sql true
                #hibernate.format_sql true
             -->
             <!-- hilbernate 会把生成的sql语句打印到控制台 -->
            <property name="hibernate.show_sql">true</property>
            <!-- 把sql语句打印到控制台进行格式化 (缩进), 不格式化就是sql语句就是一条-->
            <property name="hibernate.format_sql">true</property>
             <!-- 
               ## auto schema export   ==> 自动导出表结构, 自动建表
               #hibernate.hbm2ddl.auto create   自动建表,每次框架运行外以后都会创建新的表, 以前的表将会被覆盖.表数据会丢失,一般在开发环境中的测试中使用. 
               #hibernate.hbm2ddl.auto create-drop 自动建表, 并且每次框架运行结束都会将表删除(开发环境测试中).
               #hibernate.hbm2ddl.auto update(推荐使用) 自动建表, 如果已经存在就不会在创建了, 如果表有变动, 自动更新表.(在正式的项目更新时使用, 自动更新表, 不会删除任何数据)
               #hibernate.hbm2ddl.auto validate 效验, 不自动生成表, 每次启动效验数据库中表是否正确, 效验失败会抛出异常
              -->
            <property name="hibernate.hbm2ddl.auto">update</property>
            <!-- 引入orm的元数据 ; 路径书写规范 : 填写Src下的路径 -->
            <mapping resource="com/yao/www/bean.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>

HibernateAPI详解:

Configuration(Dome)

Dome.java:

package com.yao.b_API;
​
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
​
import com.yao.www.bean;
​
/**
 * 
 * @ClassName: Demo
 * @Description: 学习Configuration    
 * @author: Administrator
 * @date: 2018年7月3日 下午6:46:06
 * 备注:Configuration 功能: 配置加载类, 用户加载主配置, orm元数据的加载
 */
public class Demo {
    //保存用户
    public void fun1(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration();

        //2. 读取指定的主配置文件 , 空參加载方法是  加载src下的hibernate.cfg.xml 文件
        conf.configure();

        //3. 读取指定orm元数据(上古时期的方法) , 如果主配置中引入了映射配置就不需要手动加载
        //conf.addResource(resourceName);
        //conf.addClass(persistentClass)

        //4.根据配置信息, 创建SessionFactory
        SessionFactory buildSessionFactory = conf.buildSessionFactory();

    }

}
SessionFactory(Dome2)

如何加载主配置 如何加载orm元数据(上古配置) 获取Session //第一种方法: sf.openSession();//打开一个新的Session对象. //第二种方法: sf.getCurrentSession(); //获得与线程绑定的Session对象

Dome02.java

package com.yao.b_API;
​
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
​
import com.yao.www.bean;
​
/**
 * 
 * @ClassName: Demo
 * @Description: 学习SessionFactory 对象    
 * @author: Administrator
 * @date: 2018年7月3日 下午6:46:06
 * 备注:SessionFactory 功能: 用于创建操作数据库库的核心对象Session对象的工厂
 *                      简单的说功能就一个  ==> 创建Session对象
 *      注意: 
 *          1.SessionFactory负责保存和使用配置信息, 消耗内存资源非常大.
 *          2.SessionFactory属于线程安全的对象设计.
 *      结论:
 *          保证Web项目中, 只创建一个SessionFactory. 因为SessionFactory是一个线程安全的对象, 但是十分消耗资源.
 */
public class Demo2 {
    //保存用户
    public void fun1(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration();

        //2. 读取指定的主配置文件 , 空參加载方法是  加载src下的hibernate.cfg.xml 文件
        conf.configure();

        //3. 读取指定orm元数据(上古时期的方法) , 如果主配置中引入了映射配置就不需要手动加载
        //conf.addResource(resourceName);
        //conf.addClass(persistentClass)

        //4.根据配置信息, 创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

        //============================================>
        //5.获取Session
        //第一种方法:
        sf.openSession();//打开一个新的Session对象.
        //第二种方法:
        sf.getCurrentSession(); //获得与线程绑定的Session对象 
    }

}
Session(Dome3)

Dome3.java

package com.yao.b_API;
​
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
​
import com.yao.www.bean;
​
/**
 * 
 * @ClassName: Demo
 * @Description: 学习Session 对象   
 * @author: Administrator
 * @date: 2018年7月3日 下午6:46:06
 * 备注:Session 功能: 表达Hibernate框架与数据库之间的连接(会话).Session类似于JDBC年代connection对象.还可以完成对数据库中的增删改查
 *                  Sessions是hibernate操作的核心对象       
 *      
 */
public class Demo3 {
    @Test
    //事务操作
    public void fun1(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration().configure();
​
        //2.根据配置信息, 创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

        //============================================>
        //3.获取Session
        //第一种方法:
        Session session = sf.openSession();//打开一个新的Session对象.
        //第二种方法:
        //sf.getCurrentSession(); //获得与线程绑定的Session对象

        //4.session获得操作事物的Transaction对象
        //第一种
        //获得操作事物的tx对象
        //Transaction tx = session.getTransaction();
        //第二种:
        //开启事物并获得操作事物的tx对象(推荐使用)
        Transaction tx2 = session.beginTransaction();
        //==========================================

        //==========================================
        tx2.commit();// 提交事物
        tx2.rollback();//回滚事物
        session.close();//释放资源
        sf.close();//释放资源

    }

    @Test
    //session的新增功能
    public void fun2(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration().configure();
​
        //2.根据配置信息, 创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

        //============================================>
        //3.获取Session
        //第一种方法:
        Session session = sf.openSession();//打开一个新的Session对象.
        //第二种方法:
        //sf.getCurrentSession(); //获得与线程绑定的Session对象

        //4.session获得操作事物的Transaction对象
        //第一种
        //获得操作事物的tx对象
        //Transaction tx = session.getTransaction();
        //第二种:
        //开启事物并获得操作事物的tx对象(推荐使用)
        Transaction tx2 = session.beginTransaction();
        //==========================================
        bean bean = new bean();//创建实体类的对象
        bean.setName("小花"); //使用实体类对象中的set方法 给其属性赋值

        session.save(bean); //将bean放入到Session对象中
        //==========================================
        tx2.commit();// 提交事物
        //tx2.rollback();//回滚事物
        session.close();//释放资源
        sf.close();//释放资源

    }


    @Test
    //session的查询功能
    //以id 来查询
    public void fun3(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration().configure();
​
        //2.根据配置信息, 创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

        //============================================>
        //3.获取Session
        //第一种方法:
        Session session = sf.openSession();//打开一个新的Session对象.
        //第二种方法:
        //sf.getCurrentSession(); //获得与线程绑定的Session对象

        //4.session获得操作事物的Transaction对象
        //第一种
        //获得操作事物的tx对象
        //Transaction tx = session.getTransaction();
        //第二种:
        //开启事物并获得操作事物的tx对象(推荐使用)
        Transaction tx2 = session.beginTransaction();
        //==========================================

        //第一个参数是写找哪一个类型 ,第二个参数写要查询的那个值.(id后面要加一个L, 因为id的类型为long型)
        bean bean = session.get(bean.class, 1L);
        System.out.println("bean = " + bean);

        //==========================================
        tx2.commit();// 提交事物
        //tx2.rollback();//回滚事物
        session.close();//释放资源
        sf.close();//释放资源

    }


    @Test
    //session的修改功能
    //修改以id为准的属性
    public void fun4(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration().configure();
​
        //2.根据配置信息, 创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

        //============================================>
        //3.获取Session
        //第一种方法:
        Session session = sf.openSession();//打开一个新的Session对象.
        //第二种方法:
        //sf.getCurrentSession(); //获得与线程绑定的Session对象

        //4.session获得操作事物的Transaction对象
        //第一种
        //获得操作事物的tx对象
        //Transaction tx = session.getTransaction();
        //第二种:
        //开启事物并获得操作事物的tx对象(推荐使用)
        Transaction tx2 = session.beginTransaction();
        //==========================================

        //第一步 : 要获得要修改的对象
        bean b = session.get(bean.class, 1L);
        //第二步 : 修改
        b.setName("咸鱼干");
        //第三步 : 执行update
        session.update(b);

        //==========================================
        tx2.commit();// 提交事物
        //tx2.rollback();//回滚事物
        session.close();//释放资源
        sf.close();//释放资源

    }

    @Test
    //session的删除功能
    //删除以id为准的属性
    public void fun5(){
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration().configure();
​
        //2.根据配置信息, 创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

        //============================================>
        //3.获取Session
        //第一种方法:
        Session session = sf.openSession();//打开一个新的Session对象.
        //第二种方法:
        //sf.getCurrentSession(); //获得与线程绑定的Session对象

        //4.session获得操作事物的Transaction对象
        //第一种
        //获得操作事物的tx对象
        //Transaction tx = session.getTransaction();
        //第二种:
        //开启事物并获得操作事物的tx对象(推荐使用)
        Transaction tx2 = session.beginTransaction();
        //==========================================

        //第一步: 查询
        bean b = session.get(bean.class, 1L);
        //第二步: 调用delete方法删除
        session.delete(b);

        //==========================================
        tx2.commit();// 提交事物
        //tx2.rollback();//回滚事物
        session.close();//释放资源
        sf.close();//释放资源

    }
}
Transaction

控制事务

hibernateUtils(工具类的封装)
package com.yao.dbutils;
​
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.loader.custom.Return;
​
import com.yao.www.bean;
​
/**
 * 
 * @ClassName: HibernateUtils
 * @Description: 工具类
 * @author: Administrator
 * @date: 2018年7月3日 下午10:03:04
 */
public class HibernateUtils {

    private static SessionFactory sf;

    static{
        //1.创建. 调用一个空參的方法
        Configuration conf = new Configuration().configure();

        //2.根据配置信息, 创建SessionFactory
        sf = conf.buildSessionFactory();

    }

    //获得Session的方法: ==> 获得一个全新的Session
    public static Session openSession(){

        //3.获取Session
        Session session = sf.openSession();//打开一个新的Session对象.

        return session;
    }

    //获得Session的方法: ==> 获得一个于线程绑定的Session
    public static Session getCurrentSession(){

        //3.获取Session
        Session session = sf.getCurrentSession();

        return session;
    }
}
测试类
package com.yao.test;
​
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
​
import com.yao.www.bean;
​
/**
 * 
​
 * @ClassName: Demo
​
 * @Description: 测试
​
 * @author: Administrator
​
 * @date: 2018年7月3日 下午6:10:59
 */
public class Demo {

    public void fun1(){
        //保存用户

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

        SessionFactory sessionFactory = conf.buildSessionFactory();

        Session session = sessionFactory.openSession();

        Transaction tx = session.beginTransaction();
        //========================================
        bean b = new bean();
        b.setName("aa");
        session.save(b);
        //========================================
        tx.commit();
        session.close();
        sessionFactory.close();
    }

}
例:
com.yao.domain.Customer.java
package com.yao.domain;
​
public class Customer {
        /**
         * CREATE TABLE `cst_customer` (
          `cust_id` bigint(20) NOT NULL AUTO_INCREMENT,
          `cust_name` varchar(255) DEFAULT NULL,
          `cust_source` varchar(255) DEFAULT NULL,
          `cust_industry` varchar(255) DEFAULT NULL,
          `cust_level` varchar(255) DEFAULT NULL,
          `cust_linkman` varchar(255) DEFAULT NULL,
          `cust_phone` varchar(255) DEFAULT NULL,
          `cust_moblie` varchar(255) DEFAULT NULL,
          `cust_mobile` varchar(255) DEFAULT NULL,
          PRIMARY KEY (`cust_id`)
        ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=gbk;
         */
        private Long cust_id; 

        private String cust_name;
        private String cust_source;
        private String cust_industry;
        private String cust_level;
        private String cust_linkman;
        private String cust_phone;
        private String cust_moblie;
        public Long getCust_id() {
            return cust_id;
        }
        public void setCust_id(Long cust_id) {
            this.cust_id = cust_id;
        }
        public String getCust_name() {
            return cust_name;
        }
        public void setCust_name(String cust_name) {
            this.cust_name = cust_name;
        }
        public String getCust_source() {
            return cust_source;
        }
        public void setCust_source(String cust_source) {
            this.cust_source = cust_source;
        }
        public String getCust_industry() {
            return cust_industry;
        }
        public void setCust_industry(String cust_industry) {
            this.cust_industry = cust_industry;
        }
        public String getCust_level() {
            return cust_level;
        }
        public void setCust_level(String cust_level) {
            this.cust_level = cust_level;
        }
        public String getCust_linkman() {
            return cust_linkman;
        }
        public void setCust_linkman(String cust_linkman) {
            this.cust_linkman = cust_linkman;
        }
        public String getCust_phone() {
            return cust_phone;
        }
        public void setCust_phone(String cust_phone) {
            this.cust_phone = cust_phone;
        }
        public String getCust_moblie() {
            return cust_moblie;
        }
        public void setCust_moblie(String cust_moblie) {
            this.cust_moblie = cust_moblie;
        }
        @Override
        public String toString() {
            return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + "]";
        }
    }
com.yao.domain.Cutomer.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">
    <!--  配置表与实体对象的关系-->
    <!--package属性:填写一个包名 ,在元素内部凡是需要书写完整的类名的属性,可以直接写简单的类名 -->
    <hibernate-mapping package="com.yao.domain">
    
    <!-- 
        class元素:配置实体与表的对应关系的
        name:完整类名
        table:数据库表名
     -->
        <class name="Customer" table="cst_customer">
        <!-- id元素:配置主键映射的属性
             name:填写主键对应属性名
             column(可选):填写表中的主键列名 默认值:列名会使用属性名
             type(可选):填写列(属性)的类型,hibernate会自动检测实体的属性类型。
                          每个类型有三种填法:java类型|hibernate类型|数据库类型
                          
                 not-null(可选):配置该属性(列)是否不能为空.默认值:false  
                 length(可选):配置  数据库列的长度.默认值:使用数据库类型的最大长度      
         -->
            <id name="cust_id" >
            <!--generator:主键生成策略,就是每天记录录入时,主键的生成规则.(7个)
                identity:主键自增。  由数据库来维护主键值,在录入时不需要指定主键.
                sequence:oracle中的主键生成策略.
                increment(了解) 主键自增,由hibernatel.来维护,每次插入前会先查询表中id最大值.+1作为新主键值 
                hilo():高低位算法.主键自增,由hibernatel。开发时不使用.
                native:hilo+sequence+identity 自动三选一策略.
                uuid:产生随机字符串作为主键。主键类型必须为String类型.
                assigned:自然主键生成策略.hibernate不会管理主键值,由开发人员自己录入。
              -->
                <generator class="increment"></generator>
            </id>
            <!-- propert元素除id之外的普通属性映射 
                 name:填写属性名
                 column(可选):填写列名
                 type(可选):填写列(属性)的类型,hibernate会自动检测实体的属性类型。
                          每个类型有三种填法:java类型|hibernate类型|数据库类型
                          
                 not-null(可选):配置该属性(列)是否不能为空.默认值:false  
                 length(可选):配置  数据库列的长度.默认值:使用数据库类型的最大长度          
            -->
            <property name="cust_name" column="cust_name"  >
                <!--  <column name="cust_name" sql-type="varchar"></column>-->
            </property>
            <property name="cust_source" column="cust_source"></property>
            <property name="cust_industry" column="cust_industry"></property>
            <property name="cust_level" column="cust_level"></property>
            <property name="cust_linkman" column="cust_linkman"></property>
            <property name="cust_phone" column="cust_phone"></property>
            <property name="cust_moblie" column="cust_moblie"></property>
        </class>
    </hibernate-mapping>
src.hibernate.cfg.xml
<?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>
        <!-- 
        #hibernate.dialect org.hibernate.dialect.MySQLDialect
        #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
        #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
        #hibernate.connection.driver_class com.mysql.jdbc.Driver
        #hibernate.connection.url jdbc:mysql:///test
        #hibernate.connection.username gavin
        #hibernate.connection.password


         -->
         <!-- 数据驱动 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
             <!-- 数据库URL -->
            <property name="hibernate.connection.url">jdbc:mysql:///1806</property>
             <!-- 数据库连接用户名-->
            <property name="hibernate.connection.username">root</property>
             <!-- 数据库连接密码-->
            <property name="hibernate.connection.password">root</property>
            <!-- 数据方言 
                 不同的数据中,sql语句略you8区别,指定方言可以让hiberante框架在生成sql语句时,针对数据库的方言生成.
                 sql99标准:DDL:定义语言  库表的增删该查  
                          DCL:控制语言 事务 权限
                          DML:操作语言  增删该查  
                注意事项:mysql在选择方言是,请选择最短的方言.hibernate.dialect org.hibernate.dialect.MySQLDialect
            -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

            <!-- 
            #hibernate.show_sql true
            #hibernate.format_sql true
             -->
             <!-- 将hibernate生成的sql语句打印到控制台 -->
             <property name="hibernate.show_sql">true</property>
             <!-- 将hibernate生成的sql语句打印到控制台(格式化) -->
             <property name="hibernate.format_sql">true</property>

             <!-- 
             ## auto schema export 自动导出表结构.自动建表
            #hibernate.hbm2ddl.auto create 自动建表,每次框架运行都会创建新的表。以前的表将会被覆盖。表数据会丢失.(开发环境中测试使用)
            #hibernate.hbm2ddl.auto create-drop 自动建表,每次框架运行结束都会将所有表删除.(开发环境中测试使用)
            #hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会在生成。如果表有变动,自动更新表.(自动更新表不会删除任何数据)
            #hibernate.hbm2ddl.auto validate 校验。不自动生成表.每次启动校验数据库中表是否正确。校验失败.
            生成环境(Sit4)
             -->


            <property name="hibernate.hbm2ddl.auto">update</property>

            <!-- 引入orm元数据 
                 路径书写:填写src下的路径
            -->
            <mapping resource="com/yao/domain/Customer.hbm.xml"/>
        </session-factory>

    </hibernate-configuration>
com.yao.utils.HibernateUtils.java
package com.yao.utils;
​
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
 * 
 * @author 注意: 此处如出现错误, 极有可能是eclipse 与 jdk的版本不对应, 建议下载同版本的;
 *
 */
public class HibernateUtils {
    private static SessionFactory sf;

    static{

        //1、创建,调用空参方法
        Configuration conf = new Configuration().configure();
        //2、根据配置信息,创建SessionFactory对象
         sf = conf.buildSessionFactory();
    }

    //获得session => 获得全新session
    public static Session openSession(){

                //3、获得session
                Session session = sf.openSession();

                return session;
    }

    //获得session => 获得与线程绑定的session
    public static Session getCurrentSession(){
                //3、获得session
                Session session = sf.getCurrentSession();
                return session;
    }
    public static void main(String[] args) {
        System.out.println(HibernateUtils.openSession());
    }
}

hibernate中的实体规则

实体类创建的注意事项:

​ 1.持久化类提供无參的无參的构造方法 2.成员变量私有化, 并提供GetSet方法进行访问.需要提供属性(在bean的实体类中没有私有化的属性,而是私有化的成员变量.能被称为属性的是配GetSet方法后的成员变量, 那里才能被称为属性) 3.持久化类中的属性, 应尽量使用包装类型.(持久化是对数据库的增删查改)(包装类型是八大基本类型 int 对应 Integer, Long 对应 long… ==> 开头大写就是包装类型) 从jsk1.5就有自动装箱/拆箱,所以这里给包装类. 4.在持久化类中需要提供oid与数据库中的主键列对象.(数据库中叫id,在hibernate里面叫在oid); 没有主键的字段是不被hibernate使用的表. 5.不要用final修饰class 动态代理: 面向接口的代理"cglib" hibernate使用cglib代理生成对象, 代理对象是继承被代理对象, 如果被final修饰, 将无法生成代理对象

主键类型:

​ 1.自然主键(少见) 表的业务列中, 有业务列符合必须有, 并且不重复的特征时, 该类可以叫做自然主键. 2.代理主键(常见) 表的业务中, 没有某业务符合,必须有,并且不重复的特征时,创建一个没有业务意义的列作为代理主键.

<!-- 
    id元素:配置主键映射的属性
             name:填写主键对应属性名
             column(可选):填写表中的主键列名 默认值:列名会使用属性名
             type(可选):填写列(属性)的类型,hibernate会自动检测实体的属性类型。
                          每个类型有三种填法:java类型|hibernate类型|数据库类型
                          
                 not-null(可选):配置该属性(列)是否不能为空.默认值:false  
                 length(可选):配置  数据库列的长度.默认值:使用数据库类型的最大长度      
  -->
            <id name="cust_id" >
            <!--
                generator:主键生成策略,就是每条记录录入时,主键的生成规则.(7个)
                    identity:主键自增。  由数据库来维护主键值,在录入时不需要指定主键.
                    sequence(Oracle独有的):oracle中的主键生成策略.
                    increment(了解,不建议使用,有线程安全问题.) 主键自增,由hibernate来维护,每次插入前会先查询表中id最大值.+1作为新主键值 
                    hilo(数据库中就是使用的高低位算法):高低位算法.主键自增,由hibernate。开发时不使用.==> 与数据库的功能重复了.
                    native(三合一):hilo+sequence+identity 自动三选一策略.
                    uuid:产生随机字符串作为主键。主键类型必须为String类型.
                    assigned:自然主键生成策略.hibernate不会管理主键值,由开发人员自己录入。
              -->
                <generator class="native"></generator>
            </id>
package com.yao.test.a_generator;
​
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
​
import com.yao.domain.Customer;
import com.yao.utils.HibernateUtils;
​
​
public class Dome {

    @Test
    public void fun1(){
        //1.获取Session
        Session session = HibernateUtils.openSession();

        //2.控制事物
        Transaction tx = session.beginTransaction();

        //3.执行操作
        Customer c = new Customer();
        c.setCust_name("小明");

        session.save(c);

        //4.提交事物,关闭事物
        tx.commit();
        session.close();

        /*
    使用"identity": 
            控制台打印:
                Hibernate: 
                        insert 
                        into
                            cst_customer
                            (cust_name, cust_source, cust_industry, cust_level, cust_linkman, cust_phone, cust_moblie) 
                        values
                            (?, ?, ?, ?, ?, ?, ?)
         */
        /*
    使用"increment":
         控制台打印
            Hibernate: 
                select
                    max(cust_id) 
                from
                    cst_customer
            Hibernate: 
                insert 
                into
                    cst_customer
                    (cust_name, cust_source, cust_industry, cust_level, cust_linkman, cust_phone, cust_moblie, cust_id) 
                values
                    (?, ?, ?, ?, ?, ?, ?, ?)

         */

    }
}

hibernate中的对象状态:

​ 对象分为三种状态: 1.瞬时状态 没有id, 没有与session关联, 2.持久化状态 有id, 与session有关联 3.游离状态(托管状态) 有id, 没有与session关联

package com.yao.test.b_state;
​
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
​
import com.yao.domain.Customer;
import com.yao.utils.HibernateUtils;
​
/**
 * 
 * @author 测试对象的三种状态
 *      1.学习对象三种状态结论:
 *          将我们希望同步到数据库的数据,对应的对象转化为持久化状态.
 *              
 *
 */
public class Demo {
​
    @Test
    /**
     * 查看三种状态
     */
    public void fun1(){

        //1.获取session对应
        Session session = HibernateUtils.openSession();

        //2.控制事物
        Transaction tx = session.beginTransaction();

        //3.执行操作
        Customer c = new Customer(); //创建出来没有id, 在没有与session关联的时候,属于瞬时状态


        c.setCust_name("花花"); //没有id, 没有与session关联, 瞬时状态;


        session.save(c); //有id, 与session关联, 持久化状态;

        //4.提交事物,关闭事物
        tx.commit();
        session.close();// 有id, 与session的关联被关闭, 游离状态/托管状态


    }

    @Test
    /**
     * 三种状态的特点(与主键类型有关联)
     *      save方法: 其实不能理解成保存, 应理解为将瞬时状态转化为持久化状态;
     *          主键自增, 执行save方法, 为了将对象转换为持久化状态, 必须生成id值, 所以需要执行insert语句.
     *          主键生成策略increment方法: 执行了save方法, 为了生成id, 会执行查询id最大值的sql语句
     */
    public void fun2(){
        //获取session 对象
        Session session = HibernateUtils.openSession();

        //控制事物
        Transaction tx = session.beginTransaction();

        //获取实体类 ,并操作实体类
        Customer c2 = new Customer();
        c2.setCust_name("小米");

        //将实体类存放到session对象中
        session.save(c2);// save 可以看作对象的瞬时状态转化为持久化状态.

        //提交事物
        tx.commit();
        //关闭事物
        session.close();

    }

    @Test
    /**
     * 三种状态的特点:
     *      持久化状态的特点:
     *          持久化状态对象的任何变化都会同步到数据库中.
     */
    public void fun3(){
        //获取session对象
        Session session = HibernateUtils.openSession();

        //获取事物
        Transaction tx = session.beginTransaction();

        //执行事物
        Customer c3 = session.get(Customer.class, 1L); //有id ,与session相关联, 持久化状态对象;

        c3.setCust_name("hello");

        //提交事物
        tx.commit();

        //关闭事物
        session.close();
        /*
        控制台打印:
                Hibernate: 
                    select
                        customer0_.cust_id as cust_id1_0_0_,
                        customer0_.cust_name as cust_nam2_0_0_,
                        customer0_.cust_source as cust_sou3_0_0_,
                        customer0_.cust_industry as cust_ind4_0_0_,
                        customer0_.cust_level as cust_lev5_0_0_,
                        customer0_.cust_linkman as cust_lin6_0_0_,
                        customer0_.cust_phone as cust_pho7_0_0_,
                        customer0_.cust_moblie as cust_mob8_0_0_ 
                    from
                        cst_customer customer0_ 
                    where
                        customer0_.cust_id=?
                Hibernate: 
                    update
                        cst_customer 
                    set
                        cust_name=?,
                        cust_source=?,
                        cust_industry=?,
                        cust_level=?,
                        cust_linkman=?,
                        cust_phone=?,
                        cust_moblie=? 
                    where
                        cust_id=?
         */
    }
}


公交车司机终于在众人的指责中将座位让给了老太太