我可以配置Hibernate默认为每个表创建单独的序列吗?

编程入门 行业动态 更新时间:2024-10-14 12:23:44
本文介绍了我可以配置Hibernate默认为每个表创建单独的序列吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 默认情况下,Hibernate会创建一个全局序列,用于为所有表生成ids(对于PostgreSQL而言),这会缩放非常糟糕的IMHO。虽然我可以为每个实体类型指定使用哪个序列,但我不喜欢这样做。我不喜欢明确命名序列并强制使用序列作为生成器策略,因为我希望hibernate为可能不支持序列的数据库生成DDL。单个全局序列也使得不可能使用32位int作为主键,这意味着我必须将所有int id转换为long类型。

解决方案

Hibernate意味着与数据库无关的ORM解决方案,但在迁移到另一个数据库供应商时会遇到一些关键问题。其中之一是底层数据库的Auto ID生成。 MySQL,Oracle& MS SQL Server都使用不同的技术为主键生成自动ID。所以,当我们开始迁移时,我们面临很多问题,额外的工作应该不是这样。

之前的Hibernate 3.2.3没有Hibernate的正确解决方案,但在3.2.3版本中,Hibernate人员可以提供这样的便携式ID生成器,它可以在任何数据库上运行良好。以下两项是:

  • org.hibernate.id.enhanced.SequenceStyleGenerator

可移植性需要的方法是,您真的不在乎您是否在数据库中物理使用SEQUENCE;真的,你只是想要一个像序列一样的值生成。在支持SEQUENCES的数据库上,SequenceStyleGenerator实际上将使用SEQUNCE作为值生成器;对于不支持SEQUENCES的数据库,它将使用单行表作为值生成器,但与SEQUENCE值生成器具有相同的确切特征(即它始终在单独的事务中处理序列表) 。

  • org.hibernate.id.enhanced.TableGenerator
  • ul>

    虽然没有专门针对可移植性,但TableGenerator当然可以在所有数据库中使用。它使用一个多行表,其中行由(可配置的)sequence_name列键入;一种方法是让每个实体在表中定义唯一的sequence_name值来分割其标识符值。它由早期的org.hibernate.id.MultipleHiLoPerTableGenerator发展而来,基本上使用相同的表结构。然而,虽然MultipleHiLoPerTableGenerator固有地将Hi-Lo算法应用于值生成,但是新添加的TableGenerator可以充分利用可插入优化器的优势。

    示例实体对所有数据库使用Hibernate的序列。

    @Entity @Table(name = author) public class Author实现java.io.Serializable { // Fields private Integer id; 私人字符串名称; 私人日期birthDate; 私人日期deathDate; private String bio; 私人字符串wikiUrl; private String imagePath; 私有布尔isFeatured; private long totalContent; 私人套餐<内容> contents = new HashSet< Content>(0); //构造函数 $ b $ / **默认构造函数* / public作者(){} //属性访问器 @Id @GeneratedValue(generator =Author_SequenceStyleGenerator) @GenericGenerator(name =Author_SequenceStyleGenerator,strategy =org.hibernate.id.enhanced.SequenceStyleGenerator,参数= { @Parameter(name =sequence_name,value =Author_SEQ), @Parameter(name =optimizer,value =hilo), @参数(name =initial_value,value =1), @Parameter(name =increment_size,value =1)} ) @Column(name = id,unique = true,nullable = false,length = 11) public Integer getId(){ return this.id; } public void setId(Integer id){ this.id = id; @Column(name =name,length = 50) public String getName(){ return this.name; } public void setName(String name){ this.name = name; } @Temporal(TemporalType.DATE) @Column(name =birth_date,length = 10) public Date getBirthDate(){返回this.birthDate; } public void setBirthDate(Date birthDate){ this.birthDate = birthDate; } @Temporal(TemporalType.DATE) @Column(name =death_date,length = 10) public Date getDeathDate(){返回this.deathDate; } public void setDeathDate(Date deathDate){ this.deathDate = deathDate; @Column(name =bio,length = 65535) public String getBio(){ return this.bio; } public void setBio(String bio){ this.bio = bio; @Column(name =wiki_url,length = 128) public String getWikiUrl(){ return this.wikiUrl; } public void setWikiUrl(String wikiUrl){ this.wikiUrl = wikiUrl; @Column(name =image_path,length = 50) public String getImagePath(){ return this.imagePath; } public void setImagePath(String imagePath){ this.imagePath = imagePath; @Column(name =is_featured) public Boolean getIsFeatured(){ return this.isFeatured; } public void setIsFeatured(Boolean isFeatured){ this.isFeatured = isFeatured; } @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy =author) public Set< Content> getContents(){ return this.contents; } public void setContents(Set< Content> contents){ this.contents = contents; } @Transient public Long getTotalContent(){ return totalContent; } public void setTotalContent(Long totalContent){ this.totalContent = totalContent; } } }

    Hibernate by default creates a globel sequence which is used to generate ids for all tables, (in the case for PostgreSQL) which scales very bad IMHO. Though I can specify for each entity type which sequence to use, I don't like to do it. I don't like to explicit name the sequence and force to use sequence as the generator strategy, because I want hibernate generate DDL for databases which may not support sequence at all. The single global sequence also make it impossible to use 32-bit int as the primary key, which means I must convert all int id(s) to long type.

    解决方案

    Hibernate meant to be Database independent ORM solution, but while migrating to another database vendor some key issues arrives. One of them is Auto ID generation of underlying database. MySQL, Oracle & MS SQL Server all uses different techniques to generate auto ID for primary keys. So, when we start migrating we face lot of issues, extra work which should not be the case.

    Prior Hibernate 3.2.3 there was no proper solution by the Hibernate, but in version 3.2.3 Hibernate guys made it possible to offer such portable ID generator which works well on any database. The two are followings,

    • org.hibernate.id.enhanced.SequenceStyleGenerator

    "the approach it takes to portability is that really you dont care whether you are physically using a SEQUENCE in the database; really you just want a sequence-like generation of values. On databases which support SEQUENCES, SequenceStyleGenerator will in fact use a SEQUNCE as the value generator; for those database which do not support SEQUENCES, it will instead use a single-row table as the value generator, but with the same exact charecteristics as a SEQUENCE value generator (namely it deals with the sequence table in a separate transaction at all times)".

    • org.hibernate.id.enhanced.TableGenerator

    while not specifically targetting portability, TableGenerator can certainly be used across all databases. It uses a multi-row table where the rows are keyed by a (configurable) sequence_name column; one approach would be to have each entity define a unique sequence_name value in the table to segment its identifier values. It grew out of the older org.hibernate.id.MultipleHiLoPerTableGenerator and uses basically the same table structure. However, while MultipleHiLoPerTableGenerator inherently applies a hi-lo algorithm to the value generation, this new TableGenerator was added to be able to take advantage of the pluggable optimizers.

    Example Entity Which usage, Hibernate's Sequences across all databases.

    @Entity @Table(name = "author") public class Author implements java.io.Serializable { // Fields private Integer id; private String name; private Date birthDate; private Date deathDate; private String bio; private String wikiUrl; private String imagePath; private Boolean isFeatured; private Long totalContent; private Set<Content> contents = new HashSet<Content>(0); // Constructors /** default constructor */ public Author() { } // Property accessors @Id @GeneratedValue(generator = "Author_SequenceStyleGenerator") @GenericGenerator(name = "Author_SequenceStyleGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { @Parameter(name = "sequence_name", value = "Author_SEQ"), @Parameter(name = "optimizer", value = "hilo"), @Parameter(name = "initial_value", value = "1"), @Parameter(name = "increment_size", value = "1") } ) @Column(name = "id", unique = true, nullable = false, length = 11) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name = "name", length = 50) public String getName() { return this.name; } public void setName(String name) { this.name = name; } @Temporal(TemporalType.DATE) @Column(name = "birth_date", length = 10) public Date getBirthDate() { return this.birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } @Temporal(TemporalType.DATE) @Column(name = "death_date", length = 10) public Date getDeathDate() { return this.deathDate; } public void setDeathDate(Date deathDate) { this.deathDate = deathDate; } @Column(name = "bio", length = 65535) public String getBio() { return this.bio; } public void setBio(String bio) { this.bio = bio; } @Column(name = "wiki_url", length = 128) public String getWikiUrl() { return this.wikiUrl; } public void setWikiUrl(String wikiUrl) { this.wikiUrl = wikiUrl; } @Column(name = "image_path", length = 50) public String getImagePath() { return this.imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } @Column(name = "is_featured") public Boolean getIsFeatured() { return this.isFeatured; } public void setIsFeatured(Boolean isFeatured) { this.isFeatured = isFeatured; } @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "author") public Set<Content> getContents() { return this.contents; } public void setContents(Set<Content> contents) { this.contents = contents; } @Transient public Long getTotalContent() { return totalContent; } public void setTotalContent(Long totalContent) { this.totalContent = totalContent; } } }

更多推荐

我可以配置Hibernate默认为每个表创建单独的序列吗?

本文发布于:2023-10-23 05:23:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1519914.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:序列   默认为   Hibernate

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!