JavaWeb - Hibernate框架使用(二)

hibernate中的实体(Entity)类规则

  • 实体类创建的注意事项

    1. 持久化类提供无参数构造
    2. 成员变量私有,提供共有get/set方法访问.需提供属性
    3. 持久化类中的属性,应尽量使用包装类型
    4. 持久化类需要提供oid.与数据库中的主键列对应
    5. 不要用final修饰class
      hibernate使用cglib代理生成代理对象.代理对象是继承被代理对象.如果被final修饰.将无法生成代理.
  • 主键类型

    1. 自然主键(少见)
      表的业务列中,有某业务列符合,必须有,并且不重复的特征时,该列可以作为主键使用.
    2. 代理主键(常见)
      表的业务列中,没有某业务列符合,必须有,并且不重复的特征时,创建一个没有业务意义的列作为主键
  • 主键生成策略(7种)

    1. 代理主键
      • identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
      • sequence: Oracle中的主键生成策略.
      • increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
      • hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
      • native:hilo+sequence+identity 自动三选一策略.
      • uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
    2. 自然主键
      • assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.

hibernate中的对象状态

  • 对象分为三种状态

    1. 瞬时状态:没有id,没有在session缓存中
    2. 持久化状态:有id,在session缓存中
    3. 游离|托管状态:有id,没有在session缓存中
  • 三种状态的转换图

hibernate中的对象状态

hibernate进阶 - 一级缓存

  • 缓存

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

  • 提高查询效率

提高效率手段1
  • 减少不必要的修改语句发送

提高效率手段2
  • 代码测试
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import domain.Customer;
import utils.HibernateUtils;
//测试一级缓存
public class Demo {
    @Test
    //证明一级缓存存在
    public void fun1(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        Customer c1 = session.get(Customer.class, 1l);
        Customer c2 = session.get(Customer.class, 1l);
        Customer c3 = session.get(Customer.class, 1l);
        Customer c4 = session.get(Customer.class, 1l);
        Customer c5 = session.get(Customer.class, 1l);
        System.out.println(c3==c5);//true
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //
    public void fun2(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        Customer c1 = session.get(Customer.class, 1l);
        c1.setCust_name("哈哈");
        c1.setCust_name("嘿嘿");
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //持久化状态对象其实就是放入session缓存中的对象
    public void fun3(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        Customer c1 = new Customer();
        c1.setCust_id(1l);//托管|游离
        session.update(c1);//c1被放入session缓存了
        Customer c2 = session.get(Customer.class, 1l);
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
}

hibernate中的事务

  • 事务

    1. 事务特性(ACID)
      a 原子性(Atomicity)
      c 一致性(Consistency)
      i 隔离性(Isolation)
      d 持久性(Durability)

    2. 事务并发问题

      1. 脏读
      2. 不可重复度
      3. 幻|虚读

      更新丢失(lost update):当系统允许两个事务同时更新同一数据是,发生更新丢失。
      脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。
      不可重复读取(nonrepeatableread):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删,每次返回不同的结果集,此时发生不可重复读取。
      幻像(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。

    3. 事务的隔离级别
      读未提交- 123
      读已提交 - 23
      可重复读(mysql默认级别)-3
      串行化 - 没有问题

  • 如何在hibernate中指定数据库的隔离级别

在Hibernate主配置文件hibernate.cfg.xml中:

<hibernate-configuration>
    <session-factory>
        ...
         <!-- 指定hibernate操作数据库时的隔离级别 
            #hibernate.connection.isolation 1|2|4|8     
            0001    1   读未提交
            0010    2   读已提交
            0100    4   可重复读
            1000    8   串行化
         -->
         <property name="hibernate.connection.isolation">4</property>
         <!-- 指定session与当前线程绑定 -->
         <property name="hibernate.current_session_context_class">thread</property>
        ...
    </session-factory>
</hibernate-configuration>
  • 在项目中如何管理事务

    1. 业务(Service层)开始之前打开事务,业务执行之后提交事务. 执行过程中出现异常.回滚事务.
    2. 在dao层操作数据库需要用到session对象.在service控制事务也是使用session对象完成. 我们要确保dao层和service层使用的使用同一个session对象
    3. 在hibernate中,确保使用同一个session的问题,hibernate已经帮我们解决了. 我们开发人员只需要调用sessionFactory.getCurrentSession()方法即可获得与当前线程绑定的session对象
    4. 注意1: 调用getCurrentSession方法必须配合主配置中的一段配置
      <property name="hibernate.current_session_context_class">thread</property>
    5. 注意2: 通过getCurrentSession方法获得的session对象.当事务提交时,session会自动关闭.不要手动调用close关闭.

hibernate中的批量查询(概述)

  • HQL查询-Hibernate Query Language

多表查询,但不复杂时使用,Hibernate独家查询语言,属于面向对象的查询语言

  1. 基本查询
  2. 条件查询
    ?号占位符
    命名占位符
  3. 分页查询

测试代码

import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import domain.Customer;
import utils.HibernateUtils;
//测试HQL语句
public class Demo {
    @Test
    //基本查询
    public void fun1(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
//      String hql = " from 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);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //条件查询
    //HQL语句中,不可能出现任何数据库相关的信息的
    public void fun2(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
        String hql = " from Customer where cust_id = 1 "; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //3> 根据查询对象获得查询结果
        Customer c = (Customer) query.uniqueResult();
        System.out.println(c);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //条件查询
    //问号占位符
    public void fun3(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
        String hql = " from Customer where cust_id = ? "; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置参数
        //query.setLong(0, 1l);
        query.setParameter(0, 1l);
        //3> 根据查询对象获得查询结果
        Customer c = (Customer) query.uniqueResult();
        System.out.println(c);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //条件查询
    //命名占位符
    public void fun4(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
        String hql = " from Customer where cust_id = :cust_id "; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置参数
        query.setParameter("cust_id", 1l);
        //3> 根据查询对象获得查询结果
        Customer c = (Customer) query.uniqueResult();
        System.out.println(c);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //分页查询
    public void fun5(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1> 书写HQL语句
        String hql = " from Customer  "; // 查询所有Customer对象
        //2> 根据HQL语句创建查询对象
        Query query = session.createQuery(hql);
        //设置分页信息 limit ?,?
        query.setFirstResult(1);
        query.setMaxResults(1);
        //3> 根据查询对象获得查询结果
        List<Customer> list =  query.list();
        System.out.println(list);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
}
  • Criteria查询

单表条件查询时使用方便,Hibernate自创的无语句面向对象查询
测试代码:

import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
import domain.Customer;
import utils.HibernateUtils;
//测试Criteria查询
public class Demo {
    @Test
    //基本查询
    public void fun1(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //查询所有的Customer对象
        Criteria criteria = session.createCriteria(Customer.class);
        List<Customer> list = criteria.list();
        System.out.println(list);
//      Customer c = (Customer) criteria.uniqueResult();
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //条件查询
    //HQL语句中,不可能出现任何数据库相关的信息的
    // >                gt
    // >=               ge
    // <                lt
    // <=               le
    // ==               eq
    // !=               ne
    // in               in
    // between and      between
    // like             like
    // is not null      isNotNull
    // is null          isNull
    // or               or
    // and              and
    public void fun2(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //创建criteria查询对象
        Criteria criteria = session.createCriteria(Customer.class);
        //添加查询参数 => 查询cust_id为1的Customer对象
        criteria.add(Restrictions.eq("cust_id", 1l));
        //执行查询获得结果
        Customer c = (Customer) criteria.uniqueResult();
        System.out.println(c);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //分页查询
    public void fun3(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //创建criteria查询对象
        Criteria criteria = session.createCriteria(Customer.class);
        //设置分页信息 limit ?,?
        criteria.setFirstResult(1);
        criteria.setMaxResults(2);
        //执行查询
        List<Customer> list = criteria.list();
        System.out.println(list);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //查询总记录数
    public void fun4(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //创建criteria查询对象
        Criteria criteria = session.createCriteria(Customer.class);
        //设置查询的聚合函数 => 总行数
        criteria.setProjection(Projections.rowCount());
        //执行查询
        Long count = (Long) criteria.uniqueResult();
        System.out.println(count);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
}
  • 原生SQL查询

复杂的业务查询使用
测试代码:

import java.util.Arrays;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
import domain.Customer;
import utils.HibernateUtils;
//测试原生SQL查询
public class Demo {
    @Test
    //基本查询
    public void fun1(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1 书写sql语句
        String sql = "select * from cst_customer";
        //2 创建sql查询对象
        SQLQuery query = session.createSQLQuery(sql);
        //3 调用方法查询结果
        List<Object[]> list = query.list();
        //query.uniqueResult();
        for(Object[] objs : list){
            System.out.println(Arrays.toString(objs));
        }
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //基本查询
    public void fun2(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1 书写sql语句
        String sql = "select * from cst_customer";
        //2 创建sql查询对象
        SQLQuery query = session.createSQLQuery(sql);
        //指定将结果集封装到哪个对象中
        query.addEntity(Customer.class);
        //3 调用方法查询结果
        List<Customer> list = query.list();
        System.out.println(list);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //条件查询
    public void fun3(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1 书写sql语句
        String sql = "select * from cst_customer where cust_id = ? ";
        //2 创建sql查询对象
        SQLQuery query = session.createSQLQuery(sql);
        query.setParameter(0, 1l);
        //指定将结果集封装到哪个对象中
        query.addEntity(Customer.class);
        //3 调用方法查询结果
        List<Customer> list = query.list();
        System.out.println(list);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
    @Test
    //分页查询
    public void fun4(){
        //1 获得session
        Session session = HibernateUtils.openSession();
        //2 控制事务
        Transaction tx = session.beginTransaction();
        //3执行操作
        //-------------------------------------------
        //1 书写sql语句
        String sql = "select * from cst_customer  limit ?,? ";
        //2 创建sql查询对象
        SQLQuery query = session.createSQLQuery(sql);
        query.setParameter(0, 0);
        query.setParameter(1, 1);
        //指定将结果集封装到哪个对象中
        query.addEntity(Customer.class);
        //3 调用方法查询结果
        List<Customer> list = query.list();
        System.out.println(list);
        //-------------------------------------------
        //4提交事务.关闭资源
        tx.commit();
        session.close();// 游离|托管 状态, 有id , 没有关联
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容