2011-07-09 16 views
6

Hibernate crea de forma predeterminada una secuencia globel que se utiliza para generar identificadores para todas las tablas, (en el caso de PostgreSQL) que escalas muy mal en mi humilde opinión. Aunque puedo especificar para cada entidad, qué secuencia usar, no me gusta hacerlo. No me gusta nombrar explícitamente la secuencia y forzar el uso de la secuencia como la estrategia del generador, porque quiero que Hibernate genere DDL para las bases de datos que pueden no ser compatibles con la secuencia en absoluto. La secuencia global única también imposibilita el uso de int de 32 bits como la clave primaria, lo que significa que debo convertir todas las identificaciones int a tipo largo.¿Puedo configurar Hibernate para crear una secuencia separada para cada tabla de forma predeterminada?

Respuesta

4

Hibernate significa que es una solución ORM independiente de la base de datos, pero al migrar a otro proveedor de bases de datos, llegan algunos problemas clave. Uno de ellos es la generación automática de ID de la base de datos subyacente. MySQL, Oracle & MS SQL Server utiliza diferentes técnicas para generar identificación automática para claves primarias. Entonces, cuando comenzamos a migrar enfrentamos muchos problemas, trabajo adicional que no debería ser el caso.

Prior Hibernate 3.2.3 no había una solución adecuada para el Hibernate, pero en la versión 3.2.3 los chicos de Hibernate hicieron posible ofrecer dicho generador de ID portátil que funciona bien en cualquier base de datos. Los dos son seguidores,

  • org.hibernate.id.enhanced.SequenceStyleGenerator

“el enfoque que lleva a la portabilidad es que realmente usted no le importa si usted está físicamente usando una secuencia en el base de datos; realmente solo quieres una generación de valores similar a una secuencia. En las bases de datos que admiten SECUENCIAS, SequenceStyleGenerator de hecho usará un SEQUNCE como generador de valor; para aquellas bases de datos que no admiten SECUENCIAS, en su lugar usarán una tabla de una sola fila como generador de valores, pero con las mismas características exactas que un generador de valores de SECUENCIA (es decir, trata la tabla de secuencias en una transacción separada en todo momento) ".

  • org.hibernate.id.enhanced.TableGenerator

aunque no apuntan específicamente a la portabilidad, TableGenerator sin duda se puede utilizar en todas las bases de datos. Utiliza una tabla de varias filas donde las filas están codificadas por una columna (configurable) sequence_name; Un enfoque sería hacer que cada entidad defina un valor de nombre de secuencia único en la tabla para segmentar sus valores de identificador. Surgió del antiguo org.hibernate.id.MultipleHiLoPerTableGenerator y básicamente utiliza la misma estructura de tabla. Sin embargo, mientras MultipleHiLoPerTableGenerator aplica de forma inherente un algoritmo hi-lo a la generación de valor, este nuevo TableGenerator se agregó para poder aprovechar los optimizadores conectables.

Entidad de ejemplo Qué uso, Secuencias de Hibernate en todas las bases de datos.

@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

La primera descripción en esta publicación es un corte y pegado del escritor de código original, Steve Ebersole, quien escribió un blog sobre esta función en http://in.relation.to/2082.lace. Busque allí para obtener más detalles. –

+0

Sí, la descripción es del documento oficial de Hibernate. –

2

Si la única razón para no especificar explícitamente la secuencia para cada entidad se le quieran utilizar el DDL en las bases de datos que no soportan secuencias, esto podría ser la solución para usted:

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

Este es yendo a trabajar para bases de datos sin secuencias (la estrategia AUTO).

Cuestiones relacionadas