>>分享孙卫琴的Java技术专稿和著作 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 15303 个阅读者 刷新本主题
 * 贴子主题:  【持久化专题】映射对象标识符的基本原理 回复文章 点赞(0)  收藏  
作者:sunweiqin    发表时间:2021-05-05 11:00:44     消息  查看  搜索  好友  邮件  复制  引用

本文参考《精通JPA与Hibernate:Java对象持久化技术详解》,作者:孙卫琴,清华大学出版社出版
                      
Java语言按内存地址来识别或区分同一个类的不同对象,而关系数据库按主键值来识别或区分同一个表的不同记录。Hibernate使用OID来统一两者之间的矛盾,OID是关系数据库中的主键(通常为代理主键)在Java对象模型中的等价物。

在运行时,Hibernate根据OID来维持Java对象和数据库表中记录的对应关系。例如:      
Transaction tx  = session . beginTransaction ( ) ;  
Customer c1 =session . get (Customer . class , Long . valueOf ( 1 ) ) ;  
Customer c2 =session . get (Customer . class , Long . valueOf ( 1 ) ) ;  
Customer c3 =session . get (Customer . class , Long . valueOf ( 3 ) ) ;  
System .out . println (c1 ==c2 ) ;  
System .out . println (c1 ==c3 ) ;  

tx . commit ( ) ;

   在以上程序中,三次调用了Session的get()方法,分别加载OID为1或3的Customer对象。以下是Hibernate三次加载Customer对象的流程:
  • (1)第一次加载OID为1的Customer对象时,先从数据库的CUSTOMERS表中查询ID为1的记录,再创建相应的Customer实例,把它保存在Session缓存中,最后把这个对象的引用赋值给变量c1。
  • (2)第二次加载OID为1的Customer对象时,直接把Session缓存中OID为1的Customer对象的引用赋值给c2,因此c1和c2引用同一个Customer对象。
  • (3)当加载OID为3的Customer对象时,由于在Session缓存中还不存在这样的对象,所以必须再次到数据库中查询ID为3的记录,再创建相应的Customer实例,把它保存在Session缓存中,最后把这个对象的引用赋值给变量c3。
因此,表达式c1== c2的结果为true,表达式c1==c3的结果为false。

     与表的代理主键对应,OID也是整数类型,Hibernate允许在持久化类中把与代理主键对应的OID定义为以下类型:
  • short(或包装类Short):2个字节,取值范围是:-2^15 ~ 2^15-1
  • int(或包装类Integer):4个字节,取值范围是:-2^31 ~ 2^31-1
  • long(或包装类Long):8个字节,取值范围是:-2^63 ~ 2^63-1
  • java.math.BigInteger类:大整数类型。
  • java.math.BigDecimal类:大浮点数类型。尽管它是浮点数,实际上Hibernate的内置标识符生成器仍然按照整数递增的方式为OID赋值。
为了保证持久化对象的OID的唯一性和不可变性,通常由Hibernate或底层数据库来给OID赋值。因此,可以把持久化类的OID的setId()方法设为private类型,以禁止Java应用程序随便修改OID。而把getId()方法设为public 类型,这使得Java应用程序可以读取持久化对象的OID:      

  private Long id ;
private  void  setId (Long id ) {
   this .id =id ;
}
public Long  getId ( ) {
   return id ;
}

   在持久化类中,用来自JPA API的@Id注解和@GeneratedValue注解来映射对象标识符,例如:      

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ID")
private Long id;

   以上@Id注解表明id属性是OID,@GeneratedValue注解设定如何为OID赋值,它的strategy属性指定标识符生成策略。JPA API通过GenerationType枚举类型定义了四种标识符生成策略:
  • GenerationType.AUTO:根据标识符的数据类型以及数据库对自动生成标识符的支持方式,来选择具体的标识符生成器,如identity、uuid或sequence等。
  • GenerationType.IDENTITY:由数据库自动生成标识符。
  • GenerationType.SEQUENCE:由数据库中的特定序列来生成标识符。
  • GenerationType.TABLE:由用户自定义的表来生成标识符。
对于以上标识符生成策略,Hibernate会通过相应的标识符生成器来实现这些标识符生成策略。例如以下代码通过@SequenceGenerator注解设置了具体的序列化标识符生成器:      

    @Id
   @GeneratedValue (
    strategy  = GenerationType .SEQUENCE ,
    generator  =  "sequence-generator"
   )
   @SequenceGenerator (   //具体的序列化标识符生成器
    name  =  "sequence-generator" ,
    sequenceName  =  "hibernate_sequence"
   )
   @Column (name = "ID" )
   private Long id ;

   点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小



程序猿的技术大观园:www.javathinker.net





[这个贴子最后由 admin 在 2021-10-09 10:42:41 重新编辑]
  Java面向对象编程-->异常处理
  JavaWeb开发-->自定义JSP标签(Ⅱ)
  JSP与Hibernate开发-->通过JPA API检索数据
  Java网络编程-->XML数据处理
  精通Spring-->CSS过渡和动画
  Vue3开发-->通过Axios访问服务器
  【Vue.js技术专题】Vue组件的数据监听
  【Vue.js技术专题】注册全局组件和局部组件
  【Vue.js技术专题】Vue组件的单向数据流
  【Spring Cloud Alibaba专题】Seata的架构
  【Spring Cloud Alibaba专题】Dubbo框架中提供者回调消费者
  【Spring Cloud Alibaba专题】Nacos集群的Raft算法
  【Java基础编程专题】使用和创建JavaDoc文档
  【Spring专题】@Query注解设定查询语句
  【Spring专题】@Query和@Modifying注解的增删改操作
  从《精通Spring》和《精通Vue.js》的写作分享学习新技术的经...
  【持久化专题】从JPA API中获得Hibernate API
  【Java编程基础专题】用Scanner类读取用户在控制台输入的数据
  【Java网络编程专题】用Java套接字编写基本的客户/服务器程序
  【JavaWeb专题】选择32位或64位JDK或者Apache HTTP服务器的安...
  【Java基础编程专题】Java集合的批量操作
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。