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
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;
}
}
}
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).
- 1. Bloqueo optimista en Hibernate de forma predeterminada
- 2. Hibernate @OneToMany sin unirse a una tabla separada
- 3. Crear una secuencia en una tabla existente
- 4. Informe de SSRS con cada categoría una tabla/cuadrícula separada
- 5. Asignación de los componentes de hibernación a una tabla separada
- 6. ¿Cómo configurar la fuente predeterminada para una aplicación WPF?
- 7. ¿Cómo puedo crear una secuencia en SQLite?
- 8. ¿Debo crear una interfaz para cada modelo?
- 9. Declarar una restricción predeterminada al crear una tabla
- 10. Hibernate produce SQL diferente para cada consulta
- 11. Forma más concisa para inicializar una tabla hash C#
- 12. Hibernate @generatedvalue para HSQLDB
- 13. Cómo configurar Visual Studio para contraer todas las regiones de forma predeterminada?
- 14. ¿Debo configurar Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture de forma predeterminada en mi aplicación?
- 15. Cómo agregar una clave principal separada a una tabla de unión en Hibernate
- 16. cambios de registro para cada columna en una tabla
- 17. ¿Cómo puedo configurar el entorno de Rails para mi secuencia de comandos Ruby algo independiente?
- 18. ¿Cómo usar hibernate/hql para truncar una tabla?
- 19. Obteniendo cada enésimo elemento de una secuencia
- 20. Cómo obtener un archivo 'codebehind' para crear una vista ASP.NET-MVC en RC1 de forma predeterminada
- 21. Cómo configurar CMake para crear una aplicación para el iPhone
- 22. ¿Configurar VIM para abrir archivos en modo "solo lectura" de forma predeterminada?
- 23. ¿Cómo puedo configurar la ruta de inclusión de Perl para módulos para una secuencia de comandos CGI?
- 24. ¿Se puede configurar "gem install" para instalar ejecutables fuera de/usr/bin/de forma predeterminada?
- 25. ¿Cómo puedo mapear una fecha de Java a DATETIME en mysql (de forma predeterminada es TIMESTAMP) con anotaciones de Hibernate
- 26. ¿PUEDO UNIRME dos tablas con una sola coincidencia para cada fila de una tabla en MySQL?
- 27. ¿Debería uno crear una nueva tabla para cada usuario en una aplicación web?
- 28. Secuencia de comandos SQL para crear una secuencia de comandos de inserción
- 29. Crear consulta MySQL para crear una tabla a partir de una tabla existente
- 30. ¿Qué es mejor: secuencia global única vs. secuencia por tabla?
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. –
Sí, la descripción es del documento oficial de Hibernate. –