javaEE 之 Hibernate 基础讲解

实体类规范

  1. 提供无参构造方法
  2. 成员变量私有化 提供get/set方法
  3. 基本数据类型尽量使用包装类型(可以多表示一个值null 例如考试分数 缺考和0分)
  4. 实体中必须要提供一个与表中的主键对应的属性id
    hibernate是通过主键来区别对象是否相同
  5. 不要使用final修饰实体类(代理对象是要继承该类的)

主键类型

  1. 自然主键
    业务逻辑中本身存在的不能重复的字段设为主键
  2. 代理主键(常用)
    自定义一个和业务本身没有关系的字段 设为主键

一般我们这样定义

< generator class=”native”> < /generator>
还可以使用以下几种主键生成策略
identity:主键自增 由数据库来维护主键 录入的时候不需要指定主键
increment:主键自增 由hibernate来维护主键 每次插入前会先查询表中 id最大值 +1 作为新主键 效率不高 每次都要查询 如何10个人同时要保存 可能会出现线程问题
sequence:Oracle中的主键生成策略 序列
hilo:高低位算法(数据库中的主键自增算法原理) 由hibernate来维护主键
native:hilo + sequence + identity 自动三选一 检测你是什么数据库

hibernate 的三种状态

1.瞬时态 没有id 没有和session关联
2. 持久态 有id 有关联
3. 游离态 有id 没有关联

这里写图片描述

代码示例:

@Test
    public void fun5() {
        // 获取session
        Session session = HibernateUtils.getSession();
        // 开启事物
        Transaction transaction = session.beginTransaction();
        // 包裹语句

        User user = new User(); // 瞬时态 无id session中的缓存无关联
        user.setId(1);  //游离态 有id 无联系
        // 从数据库返回结果集 是保存进 缓存和快照中
        // updata 时 是这个要更新的对象放入缓存中(跟快照没关系)
        session.update(user);   // 持久态 有id 有联系
        // get查询时 去缓存中查找 看有没有该id的对象
        User u = session.get(User.class, 1);

        // 提交事物
        // 当事物提交的时候 hibernate 会对比快照和缓存中的对象是否相同
        // 不相同 会把缓冲中的对象 同步到数据库
        transaction.commit();
        // 关闭session
        session.close();        // 游离态 有id 没关联
    }

一级缓存与快照

缓存原理图解:
这里写图片描述

缓存测试:

@Test
    public void fun3() {
        // 获取session
        Session session = HibernateUtils.getSession();
        // 开启事物
        Transaction transaction = session.beginTransaction();
        // 包裹语句
        User user = session.get(User.class, 1);
        User user2 = session.get(User.class, 1);
        User user3 = session.get(User.class, 1);
        User user4 = session.get(User.class, 1);
        User user5 = session.get(User.class, 1);

        System.out.println(user2 == user5);

        // 提交事物
        transaction.commit();
        // 关闭session
        session.close();        // 游离态 有id 没关联
    }
    // 这里输出 只输出一条查询语句 第二个输出为true 
    // 根据上图 原理 我们可以看出 第一次 hibernate 和 数据库之间会产生关联 
    // 并且在返回的结果集中 hibernate 将结果集封装为一个对象 存放在缓存中
    // 然后将缓存返回给程序 当第二个语句执行的时候 hibernate 会去缓存中根据id来查询
    // 发现匹配成功就直接返回缓存中的对象 hibernate之所以会这样写 是为了提高程序的运行效率 和减少资源浪费

快照原理图片:
这里写图片描述

代码示例:

@Test
    public void fun4() {
        // 获取session
        Session session = HibernateUtils.getSession();
        // 开启事物
        Transaction transaction = session.beginTransaction();
        // 包裹语句

        User user = session.get(User.class, 1);
        user.setUsername("james");
        user.setUsername("Miku");
        // 提交事物
        transaction.commit();
        // 关闭session
        session.close();        // 游离态 有id 没关联
    }
    // 这里会输出 一条查询语句 和一条修改语句
    // 首先我们修改的数据在什么时候进行更改的 ! 是在commit的时候才会进行修改
    // 那么commit的时候系统会做什么操作呢?
    // 首先系统会根据ID 判断缓存中的对象是否和快照一样 不一样会将缓存中的数据更新到数据库 一样就不做操作

事务的隔离级别

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

通过hibernate 来设置事物的隔离级别
1.脏读
2.可重复读
3.幻读
READ UNCOMMITTED 读未提交 123 1
READ COMMITTED 读已提交 23 2
REPEATABLE READ 可重复读 3 4
SERIALIZABLE 串行化(只能一个一个访问) 8
设置事物的隔离级别(etc文件中)
隔离级别是用 1个字节存储的 0001 0010 0100 1000
hibernate.connection.isolation 1|2|4|8

获取当前session

需要在hibernate.cfg.xml 中设置才能实现

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

hibernate 中的查询

HQL 查询

@Test
    public void fun1() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        String hql = "from User";
        Query query = session.createQuery(hql);
        // 单数据 使用uniqueResult()  多数据使用list
        // User user = (User) query.uniqueResult();
        List<User> list = query.list();
        System.out.println(list);
        transaction.commit();
        session.close();
    }

问号?占位符

@Test
    public void fun2() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        String hql = "from User where id = ?";
        Query<User> query = session.createQuery(hql);
        // 给语句中的?赋值 第一个参数 是从零开始
        query.setParameter(0, 2);
        List<User> list = query.list();
        System.out.println(list);

        transaction.commit();
        session.close();
    }

冒号:占位符

@Test
    public void fun3() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        // 冒号后面 相当于给这个冒号占位符 起了个别名
        // 注意:冒号后面不要加空格
        String hql = "from User where id =:w";
        Query<User> query = session.createQuery(hql);
        query.setParameter("w", 1);
        List<User> list = query.list();
        System.out.println(list);

        transaction.commit();
        session.close();
    }

分页查询

@Test
    public void fun4() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        String hql = "from User";
        Query<User> query = session.createQuery(hql);
        // 设置起始 和 最大显示
        query.setFirstResult(2);
        query.setMaxResults(2);
        List<User> list = query.list();
        System.out.println(list);

        transaction.commit();
        session.close();
    }

无语局查询

@Test
    public void fun6() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        Criteria criteria = session.createCriteria(User.class);
        // 添加一个查询条件 Restrictions.eq 等于
        Criteria add = criteria.add(Restrictions.eq("id", 2));
        List<User> list = add.list();
        System.out.println(list);

        transaction.commit();
        session.close();
    }

原生sql 查询 返回的结果 跟对象没有关系

@Test
    public void fun8() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        String sql = "select * from user where id = ?";
        Query query = session.createSQLQuery(sql);
        query.setParameter(0, 3);
        // 一条记录就是一个 Object[]
        Object[] object = (Object[]) query.uniqueResult();
        for (Object object2 : object) {
            System.out.println(object2);
        }

        transaction.commit();
        session.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值