2011-07-09 148 views
6

休眠默认创建该秤非常不好IMHO其用于产生用于所有的表,(在对PostgreSQL的情况下)ID的globel序列。虽然我可以为每个实体类型指定使用哪个序列,但我不喜欢这样做。我不喜欢明确命名序列并强制使用序列作为生成器策略,因为我希望hibernate为可能不支持序列的数据库生成DDL。单个全局序列也使得不可能使用32位int作为主键,这意味着我必须将所有int id转换为long类型。我可以配置Hibernate默认为每个表创建单独的序列吗?

回答

4

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

此前的Hibernate 3.2.3得到了由休眠没有妥善的解决办法,但在3.2.3版休眠家伙使我们能够提供这种便携式ID生成的任何数据库上运行良好。这两者是以下,

  • org.hibernate.id.enhanced.SequenceStyleGenerator

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

  • org.hibernate.id.enhanced.TableGenerator

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

例实体,用法,Hibernate的所有数据库中的序列。

@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; 
} 

} 
} 
+2

在这篇文章的开头描述是剪切和粘贴从原来的代码作家史蒂夫·埃伯索尔,谁在http://in.relation.to/2082.lace博客上讲述这个功能看,那有更多的细节。 –

+0

是的,描述来自hibernate的官方文档。 –

2

如果未明确指定每个实体的序列的唯一原因是你想要使用DDL上不支持序列数据库,这可能是你的解决方案:

@Id 
@SequenceGenerator(name = "your_table_id_seq", sequenceName = "your_table_id_seq") 
@GeneratedValue(strategy = GenerationType.AUTO, generator = "your_table_id_seq") 
@Column(name = "your_table_id") 
public Long getId() { 
    return id; 
} 

这是去工作的数据库W/O序列(策略AUTO)。

相关问题