SSH框架---Hibernate的主键生成策略与一级缓存(五)

一、持久化类的编写规范

1、持久化类

持久化类: 与表建立了映射关系的实体类,就可以称之为持久化类。
                = java类+配置文件(ex:类.java+类.hbm.xml)

2、Hibernate对持久化类的要求规范:

  • 1 需要提供一个无参的构造方法   hibernate是通过无参构造器来实例化对象的
  • 2 所有属性都要私有化  
  • 3 需要对外提供set/get方法
  • 4 基本类型(int)和包装类型(integer),建议全部包装类型。默认值不同的,包装类默认值null,基本数据类型默认0
  • 5 持久化类不能被final修饰,否则hibernate的优化手段就失效,即延迟加载就会失效变成立即加载
           原因:load查询返回的是代理对象,而这个代理对象是持久化类的子类生产的,final修饰后不能再产生子类
  • 6 持久化类必须要有标识属性(OID属性)  :Hibernate用来判断对象是否是同一个
           标识属性(OID属性):就是与表中主键建立映射关系的属性。
           作用: 让hibernate来区分对象是否是同一个。如果多个对象的标识属性值相同,hibernate会认为是同一个对象,存储数据会                 报错。

ps: 如果一个类与一张表做了映射 我们可以把这个类称为持久化类。
      如果一个类中的属性和一张表中的主键字段做了映射,我们可以把这个属性称为标识属性或则OID属性。
      只有增删改和主键查询(OID查询),Hibernate会主动生成SQL,其他查询需要自己手写SQL。

标识属性(OID属性)的作用在哪里?  常用于面试题
    标识属性: Object Identifie  简称OID属性
    作用: hibernate根据IOD属性来区分多个对象是否是同一个对象
        
     ps:每个技术对于多个对象是否为同一个对象的判断凭据不同
     虚拟机jvm: 是根据内存地址
          如果内存地址相同 多个对象它会认为是同一个
    
     数据库: 是根据主键
          如果主键相同 多个对象它会认为是同一个

     Hibernate:是根据oid
          如果oid相同 多个对象它会认为是同一个

    结论是: Hibernate必须得有一个oid属性,而且这个oid属性还不能相同。一般通过主键生成策略来生成oid属性。

问题: 怎么保证每个对象oid属性的不同?
         使用Hibernate提供的一门技术: 主键生成策略

二、主键生成策略 

1、区分自然主键和代理主键

  • 1、自然主键:创建表的时候,使用的是实体类中的自身属性作为表的主键。
          例如: 创建一张人员表,可以用自身的身份证号(唯一不可重复的)作为主键
  • 2、代理主键:创建表的时候,使用的不是实体类中的自身属性作为主键,而是创建一个不相关的字段作为主键。
          例如: 创建一张人员表,不使用自身的身份证号(唯一不可重复的)作为主键,用另外创建一个id作为主键

     ***** 尽量使用代理主键。使用自然主键,如果主键需要参与到业务逻辑中,有可能需要改变很多的设计和代码。

2、Hibernate的主键生成策略

主键不应该由用户自己维护,应该统一管理,那么Hibernate就提供了主键统一管理的方式:主键生成策略。

  • 1、increment:由Hibernate维护。自动增长,适用于short、int、long类型的主键,使用的是Hibernate中提供一种自动增长方式,不是数据库中的自动增长。
    原理:首先使用select max(CUST_ID) from T_CUSTOMER;将这个最大值+1作为下一条记录的主键。
    缺点:对于并发访问数据库不适用 
  • 2、identity:由Hibernate维护。自动增长,适用于short、int、long类型的主键,使用的是数据库自动增长机制,数据库自动解决多线程问题。如:MySql、db2。不是所有数据库都支持自动增长,比如Oracle没有自动增长。 
  • 3、sequence:由Hibernate维护。序列,适用于short、int、long类型的主键,使用序列方式完成主键的生成。必须是支持序列方式的数据库。如:Oracle、db2
  • 4、native:由Hibernate维护。本地策略,根据底层的数据库不同,自动选择使用identity还是sequence。
  • 5、uuid:由Hibernate维护。随机字符串,适用于字符串类型的主键。
  • 6、assigned:Hibernate不维护主键。开发人员需要手动设置主键。

总结: 如果主键是数值型,选择用native;如果主键是varchar类型,选择用uuid

这里多说一点:increment增长并发访问时会抛出异常:Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: 违反唯一约束条件。
这是因为:因为increment是通过“select max(CUST_ID) from T_CUSTOMER  的值+1” 来获取主键的,这个max(CUST_ID)值有可能同时被多个线程获得,但只能有一个提交,其他的就会报错。由于这个原因,increment这种方式也没人用就是了。

三、持久化类的三种状态及三种状态之间的相互转化(多用于面试)

1、三种状态

  • 1、瞬时态:                 当前持久化类没有oid属性,没有被session操作管理
  • 2、持久态:                 当前持久化类有oid属性,有被session操作管理
  • 3、托管态(离线态):    当前持久化类有oid属性,没有被session操作管理

2、三种状态的相互转化

    1)、瞬时态
        ①获得 
            Customer customer = new Customer(); 
        ②状态转换
            瞬时-->持久:session.save()、session.saveOrUpdate()
            瞬时-->托管:customer.setCust_id(1l);
    2)、持久态: 只要查询操作得到的对象都是持久态对象
        ①获得
            例:Customer customer = session.get(Customer.class,1l);
            只要是涉及到查询方法直接获得持久态对象。
        ②状态转换
            持久-->脱管:session.close()
            持久-->瞬时:session.delete()
    3)、脱管态
        ①获得
            Customer customer = new Customer();
            customer.setCust_id(1l);
        ②状态转换
        脱管-->持久:session.save()、session.saveOrUpdate()
        脱管-->瞬时:customer.setCust_id(null);

3持久态可以自动更新数据库
       持久态: 只要是通过查询返回的对象都是持久化类的持久态对象
           特点: 持久态对象修改完属性,不需要执行更新操作,就会自动更新数据库数据

自动更新的原因: 一级缓存的存在。
一级缓存存在于session中,本质上是一堆Java集合。生命周期随session销毁被清空。可分为存储区和快照区。
具体原因或原理:我们初次执行查询操作的时候,将从数据库中的数据放到缓存的存储区中一份,快照区中一份。执行更新操作的时候,会修改缓存的存储区,快照区则不修改。执行事务提交的时候,会自动对比两个区的数据,若一致,则不处理,若不一致,Hibernate自动发送update语句来提交。
如何看到存储区和快照区的数据?可debug查看
session-->persistenceContext--->存储区entitiesByKey  + 快照区entityEntryContext  的数据变化。

存储区变化图:
-----》
快照区一直不变:

四、Hinbernate的一级缓存

1、概述

Hibernate框架本身的性能不是很好,但是Hibernate提供了很多的性能优化的手段,比如,延迟加载和缓存。
Hibernate框架共提供了两个级别的缓存:
一级缓存:称为Session级别的缓存。因为一级缓存的生命周期与session一致的。自带的,不可卸载的。(由Session中一系列的Java集合构成的)。一级缓存实质上就是一堆Java集合。只要session不被销毁,数据就一直存在。session是事务的。
二级缓存:称为SessionFactory级别的缓存。需要进行配置的缓存的插件。默认不开启的。 比如:ehche。现在缓存多用redis技术。


大白话:除了删除,增改查数据库后,都会往一级缓存中留一份
              查询先去一级缓存查,查不到;去数据库查,查询以后还会放到一级缓存中一份
              但是session只要关闭,一级缓存的数据全部清空

2、证明一级缓存的存在


3、关闭缓存的方法

  • 1、session.close()        session关闭 一级缓存也销毁
  • 2、session.clear()         clear可以清空一级缓存的所有数据
  • 3、session.evict(对象)  可以清空一级缓存的某一个对象的数据

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值