Java学习——Hibernate框架-02(第二天)

二、第二天

1.  hibernate-01 复习

2.  hibernate 中的实体类的规则-详解

     (1)实体类创建的注意事项:

                 1. 持久化类需要提供无参数构造方法;   因为Hibernate 的底层需要使用反射生成类的实例;

                 2. 成员变量私有,提供公有get/set 方法(属性)访问;需提供属性;

                 3. 持久化类中的属性,应尽量使用包装类型;

                4.  持久化类需要提供oid.  与数据库中的主键列对应;

                5.  不要用 final 修饰 class;

                          hibernate 使用 cglib 代理生成代理对象。 代理对象是继承被代理对象。

                          如果被 final 修饰,将无法继承,则将无法生成代理。

       (2) 主键类型:(2种类型)    主键不能为空,且不能重复;

                自然主键(少见):把具有业务含义的字段列作为主键;

                代理主键(常见):把不具备业务含义的字段列作为主键;

3. hibernate 中的实体规则——主键生成策略详解

主键生成策略:就是 每条记录录入时,主键的生成规则(7个)。 eg:  <generator class="native"></generator>

(1) 代理主键策略: 

   1. identity: 主键自增; 由数据库来维护主键值,录入时不需要指定主键。

   2. increment(了解): 主键自增,由hibernate 来维护,每次插入前会先查询表中id最大值,然后+1 作为新主键;正式开发时不要使用,存在线程并发安全问题;

   3. sequence:Oracle中的主键生成策略;

   4. hilo(了解):采用高低位算法,主键自增,由hibernate来维护,开发时不使用;

   5. native: hilo + sequence + identity ,自动三选一策略;

   6. uuid:产生随机字符串作为主键,主键类型必须为string 类型;

(2)自然主键策略:

    7. assigned: 自然主键生成策略,hibernate不会管理主键值,由开发人员手动指定、自己录入;

4. hibernate 中的对象状态

    对象分为三种状态: 瞬时状态, 持久化状态, 游离(托管)状态

   1. 瞬时状态: 没有id,不在session缓存中;

   2. 持久化状态: 有id ,在session 缓存中;   持久化状态对象的任何变化都会自动同步到数据库中。

   3. 游离(托管)状态: 有id ,在session缓存中;

   三种状态的转换图

   对象状态的转换: 增(save)、删(delete)、改(update)、查(get)

结论: 将我们希望同步到数据库的数据对应的对象 转换为 持久化状态,于是,对象的任何变化都会自动同步到数据库中。

            可以使用 saveOrUpdate( )方法来完成

5. hibernate 进阶: 一级缓存( session 缓存)  和 快照

  缓存 cache:提高效率,hibernate中的一级缓存 也是为了提高操作数据库的效率。

  快照: 将数据库返回的内容,组装成两个对象: 一个放入缓存中,一个放入快照中;

  提高效率的手段: 1. 提高查询效率——缓存;  2. 减少不必要的修改语句发送——快照;

6. hibernate 中的事务: 隔离级别设置 & 项目中的事务管理

  事务的4大特性: ACID(原子性,一致性,隔离性,持久性) 

  事务并发问题: 1. 脏读(两次数据不一致); 2. 不可重复读;  3. 幻读(虚读)

  事务的隔离级别:  hibernate.connection.isolation  1 | 2 | 4 | 8

   0001 —— 1 —— 读未提交(可能出现的问题: 1(脏读)、2(不可重复读)、3(幻读));

   0010 —— 2 —— 读已提交(可能出现的问题:2、3); 

   0100 —— 4 —— 可重复读(可能出现的问题:3);             

   1000 —— 8 —— 串行化;

  知识点1: 如何在hibernate中指定数据库的隔离级别

  知识点2:在项目中如何管理事务

     在业务开始之前,打开事务;

     在业务执行之后,提交事务;

     在执行过程中出现异常,回滚事务;

在dao层操作数据库需要用到session对象。 在service层控制事务也是使用session对象完成,因此我们要确保dao层和service层使用的是同一个session对象。

 在hibernate中,确保使用同一个session的问题,hibernate已经帮我们解决了。我们开发人员只需要调用sf.getCurrentSession()方法即可获得与当前线程绑定的session对象。

注意1:调用getCurrentSession方法必须配合主配置中的一段配置

    指定session与当前线程绑定:<property name="hibernate.current_session_context_class"> thread </property>

    而 HibernateUtils.openSession( ) 方法是每次获得新的session;

 注意2:  通过getCurrentSession 方法获得的session对象, 当事务提交时,session会自动关闭。所以切记不要手动调用close关闭,否则抛出异常。

  改造crm代码

7.  hibernate 中的批量查询        三种方式: HQL查询, Criteria查询 , 原生SQL查询

     1.  HQL( Hibernate Query Language)查询:  Hibernate 独家查询语言,属于面向对象的查询语言;

             在多表查询且不复杂时使用

  (1)HQL基本查询的一般步骤:        

     1. 书写HQL语句
        //其他写法:String hql = " from cn.itheima.domain.Customer ";
        String hql = " from Customer "; // 查询所有Customer对象
     2. 根据HQL语句创建查询对象
        Query query = session.createQuery( hql );
     3. 根据查询对象获得查询结果
        List<Customer> list = query.list( );    // 返回list结果
        //其他写法:query.uniqueResult( );  //接收唯一的查询结果
   
        System.out.println(list);

     注意: 在HQL语句中,只能出现对象名和属性名,不可能出现任何数据库相关的信息的;

(2)HQL条件查询  String hql = " from Customer where cust_id = 1 "; 

  问号占位符: String hql = " from Customer where cust_id = ? ";  query.setLong(0,1l); //设置参数

  命名占位符: String hql = " from Customer where cust_id = :cust_id ";  query.setParameter("cust_id",1l); //设置参数

(3)HQL分页查询 String hql = " from Customer  "; query.setFirstResult( 0 );     query.setMaxResults( 1 );

  2. Criteria 查询: Hibernate 自创的无语句面向对象查询; 单表条件查询

 (1)基本查询:

    Criteria criteria = session.createCriteria( Customer.class ); //创建 criteria 查询对象

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

   System.out.println( list );

   (2)  条件查询:

    Criteria criteria = session.createCriteria( Customer.class ); //创建 criteria 查询对象

    criteria.add( Restrictions.eq("cust_id",1l ) );    // 添加查询参数——查询cust_id 为1 的Customer对象

    Customer c = ( Customer ) criteria.uniqueResult( );  //执行查询获得结果

    System.out.println(c);  

  SQL语句的条件查询: > , >= , < , <= , == , != , in , between and , like , is not null , is null , or , and

  HQL语句中对应的:    gt , ge , lt , le , eq , ne , in , between , like , isNotNull , isNull , or , and 

  (3) 分页查询

  Criteria criteria = session.createCriteria( Customer.class ); //创建criteria 查询对象

  criteria.setFirstResult( 0 );   criteria.setMaxResults(1 );   // 设置分页设置

  List< Customer > List = criteria.list( );  //执行查询

  System.out.println( list );

 (4) 查询总记录数 

 Criteria criteria = session.createCriteria( Customer.class ); //创建criteria 查询对象

  criteria.setProjection(Projections.rowCount( ) );   // 设置查询的聚合函数——总行数

  Long count = (Long) criteria.uniqueResult( );  //执行查询

  System.out.println( count );

3. 原生SQL查询(复杂的业务查询)

  (1)基本查询:

     String sql = " select  *  from  cst_customer " ; //书写sql语句

     SQLQuery query = session.createSQLQuery( sql ) ;// 创建sql 查询对象

     query.addEntity( Customer.class ); //指定将结果集封装到哪个对象中

     List< Customer > list = query.list( ); // 调用方法查询结果

     System.out.println( list );

     //List< Object[ ] >  list = query.list( ); //调用方法查询结果

     //for( Object[ ] objs : list ){

    //        System.out.println(Arrays.toString( objs ) );

    // }

   (2)条件查询

   (3)分页查询

        

8.  练习——客户列表

  运行流程:

 1. 请求 发送给  ListCustomerServlet , 包括:

(1)调用service查询客户列表;   CustomerService 中: List< Customer > getAll( )    事务处理,调用dao

                                                        CustomerDao 中:  List< Customer > getAll( ) , HQL 或 Criteria 

(2)将列表数据放入request域;

(3)转发到list页面显示列表;

    

猜你喜欢

转载自blog.csdn.net/weixin_35908504/article/details/82628469