Overview
En esta guía, puedes aprender cómo crear entidades de Hibernate ORM que representen colecciones de MongoDB. Las entidades son clases de Java que definen la estructura de tus datos. Cuando se utiliza la extensión Hibernate ORM, se puede asociar cada entidad a una colección de MongoDB y usar estas entidades para interactuar con los documentos de la colección.
Tip
Tutorial de entidades
Para ver un tutorial que muestra cómo modelar relaciones uno-a-muchos utilizando entidades y la extensión Hibernate ORM, consulta la Modelado de relaciones con Hibernate ORM y MongoDB entrada de blog de Foojay.
Campos BSON de MongoDB
MongoDB organiza y almacena documentos en una representación binaria llamada BSON que permite un procesamiento de datos flexible. Esta sección describe el soporte de la extensión Hibernate ORM para campos BSON, que puede incluir en sus entidades.
Tip
Para obtener más información sobre cómo MongoDB almacena los datos BSON, consulta BSON Types en el manual de MongoDB Server.
La siguiente tabla describe los tipos de campos BSON admitidos y sus equivalentes de la extensión Hibernate ORM que se pueden usar en las entidades de Hibernate ORM:
Tipo de campo BSON | Tipo de campo de extensión | Descripción de BSON |
|---|---|---|
|
| Representa un valor nulo o la ausencia de datos. |
|
| Almacena datos binarios con subtipo 0. |
|
| Almacena valores de cadena codificados en UTF-8. Los tipos |
|
| Almacena enteros de 32bits con signo. |
|
| Almacena enteros de 64bits con signo. |
|
| Almacena valores de punto flotante. |
|
| Almacena valores de |
|
| Almacena valores decimales de 28 bits. Los valores de |
|
| Almacena identificadores únicos de 12bytes que MongoDB utiliza como claves primarias. |
|
| Almacena fechas y horas en milisegundos desde la época Unix. |
|
| Almacena documentos incrustados con valores de campo asignados según sus tipos respectivos. |
|
| Almacena valores de arreglo con elementos mapeados según sus tipos respectivos. Los arreglos de caracteres requieren la configuración de la propiedad de configuración |
Nota
La anotación @JdbcTypeCode no es compatible.
La extensión Hibernate ORM no admite la anotación @org.hibernate.annotations.JdbcTypeCode y genera una excepción si se utiliza esta anotación para anular la asignación de tipos de un campo.
Tipos de campos no soportados
Hibernate ORM serializa cualquier tipo Java que implemente java.io.Serializable a datos binarios cuando no tiene otra asignación para ese tipo. Para evitar que sus datos se almacenen en este formato, la extensión Hibernate ORM rechaza los siguientes tipos y lanza una excepción al iniciar la aplicación. Esta comprobación se aplica a claves primarias, campos ordinarios, atributos incrustables y elementos de colección.
La siguiente tabla describe los tipos de campos no compatibles y sus alternativas compatibles:
Categoría | Tipos no compatibles | Alternativa respaldada |
|---|---|---|
Fecha y Hora |
| Utilice |
BSON Values |
| Utilice |
Documentos BSON |
| Utilice un elemento incrustable agregado |
Define una entidad
Para crear una entidad que represente una colección de MongoDB, crea un nuevo archivo Java en el directorio base del paquete de tu proyecto y agrega la clase de tu entidad a dicho archivo. En la clase de tu entidad, especifica los campos que deseas almacenar y el nombre de la colección.
El elemento name de la anotación @jakarta.persistence.Table representa el nombre de tu colección de MongoDB. También puedes configurar el elemento opcional schema para que aparezca como prefijo del nombre de la colección, como se describe en la sección Calificadores de esquema de esta guía. Utiliza la siguiente sintaxis para definir una entidad:
public class <EntityName> { // Specify your primary key field here private <field type> <field name>; // Include additional fields here private <field type> <field name>; // Parameterized constructor public <EntityName>(<parameters>) { // Initialize fields here } // Default constructor public <EntityName>() { } // Getter and setter methods public <field type> get<FieldName>() { return <field name>; } public void set<FieldName>(<field type> <field name>) { this.<field name> = <field name>; } }
Para utilizar tus entidades, puedes consultarlas en tus archivos de aplicación. Para obtener más información sobre las operaciones CRUD en la extensión Hibernate ORM, consulta la guía Realizar operaciones CRUD.
Importante
El nombre del campo de clave primaria debe ser _id
MongoDB requiere que el campo de clave primaria se asigne al campo _id. Puede establecer explícitamente el nombre de la columna del campo @Id mediante la anotación @Column o la anulación orm.xml. Si establece este nombre con un valor distinto de _id, la extensión Hibernate ORM generará un error FeatureNotSupportedException durante el arranque. Para solucionar este error, elimine la anotación @Column o establezca su nombre en _id.
Esta validación no se aplica a las asignaciones XML de Hibernate Mapping (HBM) heredadas. Si asigna su entidad mediante HBM XML, la extensión Hibernate ORM cambia silenciosamente el nombre de la columna de identificador a _id en lugar de generar una excepción.
Calificadores de esquema
La anotación @Table acepta un elemento opcional schema que se antepone al nombre de la colección. Al configurar ambos elementos, la extensión Hibernate ORM asigna la entidad a una colección llamada <schema name>.<collection name>.
Un calificador de esquema solo cambia el nombre de la colección. Un esquema no es una base de datos MongoDB independiente. Cada colección con un calificador de esquema reside en la base de datos a la que se conecta su instancia SessionFactory. Dado que estas colecciones comparten una base de datos, una transacción puede abarcar varios esquemas.
Utilice la siguiente sintaxis para aplicar un calificador de esquema:
public class <EntityName> { // Define your fields, constructors, and methods here }
Nota
Limitaciones del calificador de esquema
La extensión Hibernate ORM rechaza el elemento catalog de la anotación @Table y la propiedad de configuración hibernate.default_catalog durante el arranque. Si su aplicación necesita acceder a varias bases de datos MongoDB, cree una instancia SessionFactory independiente para cada base de datos.
La extensión Hibernate ORM rechaza el uso de un punto (.) en el nombre de una tabla o un esquema durante el arranque. Esta restricción se aplica a los nombres de tablas primarias, secundarias, de unión y de colección, así como a los nombres de esquema establecidos mediante el atributo schema o la propiedad de configuración hibernate.default_schema.
Ejemplo
Esta clase de entidad de muestra Movie.java define una entidad Movie que incluye la siguiente información:
@Entityanotación que marca la clase como una entidad ORM de Hibernate@Tableanotación que asigna la entidad a la colecciónmoviesde los Conjuntos de datos de muestra de Atlas@Idy@ObjectIdGeneratoranotaciones que designan el campoidcomo la llave primaria y configuran la generación automática deObjectIdTip
Valores de llave primaria
Este ejemplo especifica el campo
ObjectIdcomo clave principal de la entidad, pero también puede establecer los camposStringointcomo clave principal mediante la anotación@Id. Para obtener más información, consulte Tipos de campos no compatibles.Campos privados que representan datos de películas
Constructores por defecto y parametrizados para la instanciación de entidades
Métodos getter y setter que proporcionan acceso a los campos de la entidad
package org.example; import com.mongodb.hibernate.annotations.ObjectIdGenerator; import org.bson.types.ObjectId; import java.util.List; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; public Movie(String title, String plot, int year, List<String> cast, List<String> directors) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; this.directors = directors; } public Movie() { } public ObjectId getId() { return id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPlot() { return plot; } public void setPlot(String plot) { this.plot = plot; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public List<String> getCast() { return cast; } public void setCast(List<String> cast) { this.cast = cast; } public List<String> getDirectors() { return directors; } public void setDirectors(List<String> directors) { this.directors = directors; } }
Tip
Para aprender más sobre los campos utilizados en la definición de la clase de entidad, consulta la sección Campos BSON de MongoDB de esta guía.
Identificadores generados por secuencia
La extensión Hibernate ORM puede asignar automáticamente identificadores numéricos consecutivos a sus entidades. Es posible que falten algunos números si se revierte una transacción o si una aplicación no utiliza todos los identificadores que reservó.
La extensión Hibernate ORM admite identificadores generados por secuencia para los tipos short, int y long, y para los tipos encapsulados Short, Integer y Long.
Agregue identificadores generados por secuencia a su entidad.
Puedes usar las anotaciones @GeneratedValue y @SequenceGenerator para agregar identificadores generados por secuencia a tu entidad. El siguiente ejemplo reserva identificadores en bloques de 50 del contador movies_SEQ:
private Long id;
Las anotaciones controlan cómo la extensión Hibernate ORM crea el ID:
@GeneratedValueLe indica a la extensión Hibernate ORM que cree el valor del campoid. Sus atributosstrategyygeneratordefinen cómo la extensión crea el ID:strategy:AUTOoSEQUENCE. ConAUTO, la extensión Hibernate ORM utiliza una secuencia y no es necesario declarar un@SequenceGenerator. ConSEQUENCE, la extensión Hibernate ORM utiliza el generador de secuencias denominado por el atributogenerator.generator: El nombre de@SequenceGeneratorque se utilizará. Si omite este atributo, la extensión Hibernate ORM nombra la secuencia según la tabla de la entidad, comomovies_SEQpara la tablamovies.
@SequenceGeneratordefine el generador de secuencias:name: El nombre al que hace referencia el atributo@GeneratedValuegenerator.sequenceName: El nombre del documento de contador. Si lo omite, la extensión Hibernate ORM utiliza elnamedel generador.initialValue: El valor a partir del cual se genera el primer ID. Por defecto es1.allocationSize: El número de identificadores reservados en cada bloque.
Dónde se almacenan los identificadores
La extensión Hibernate ORM almacena los documentos de contador en una colección fija llamada hibernate_sequences. Cada secuencia utiliza un documento de contador que tiene los siguientes campos:
_ides el nombre de la secuencia.next_valuees el valor del contador que la extensión Hibernate ORM incrementa para producir los siguientes ID. Debe coincidir con elinitialValuedel generador de secuencias, que por defecto es1.incrementes el número de ID reservados a la vez. Debe coincidir con el valorallocationSizedel generador de secuencias. Si no coincide,SessionFactoryno se inicia.
La extensión Hibernate ORM obtiene los ID en bloques. Esto reduce la cantidad de veces que debe contactar con la base de datos. Las solicitudes realizadas simultáneamente reciben cada una un ID diferente.
Importante
Requisitos del documento de contraparte
Tanto next_value como increment deben ser enteros de 64 bits (BSON Int64). Un documento de contador que no contenga alguno de estos campos, o que almacene un valor como un entero de 32 bits, no podrá asignar identificadores. Si la gestión de esquemas está deshabilitada, deberá crear un documento de contador para cada secuencia antes de que su aplicación pueda asignar identificadores.
Habilitar la gestión de esquemas
La gestión de esquemas es la forma en que Hibernate ORM crea los objetos de base de datos que necesitan tus entidades. La extensión de Hibernate ORM la utiliza para crear los documentos de contador para los ID generados por secuencia.
Para habilitar la administración de esquemas, configure la propiedad jakarta.persistence.schema-generation.database.action en su archivo hibernate.properties o persistence.xml. Utilice uno de los siguientes valores:
create: Crea los documentos de contador y los conserva cuando se cierraSessionFactory.create-drop: Crea los documentos de contador cuando se abreSessionFactoryy los elimina cuando se cierra.
El siguiente ejemplo utiliza create:
jakarta.persistence.schema-generation.database.action=create
Deshabilitar la administración de esquemas y la configuración manual de contadores.
Si prefiere desactivar la gestión de esquemas, puede crear manualmente documentos de contador para los ID generados por secuencia. Configure la siguiente propiedad:
jakarta.persistence.schema-generation.database.action=none
Luego, cree un documento de contador en la colección hibernate_sequences para cada secuencia. El _id del documento de contador debe coincidir con el sequenceName del generador de secuencias.
El siguiente ejemplo utiliza el controlador Java de MongoDB para insertar el documento de contador movies_SEQ en la colección hibernate_sequences de la base de datos que usted indique:
// Replace the placeholders with your connection string and database name. MongoClient client = MongoClients.create("<connection string>"); MongoDatabase database = client.getDatabase("<database name>"); database.getCollection("hibernate_sequences").insertOne( new Document("_id", "movies_SEQ") .append("next_value", new BsonInt64(1)) .append("increment", new BsonInt64(50)));
La inserción crea el documento de contador que se muestra. Establezca next_value al initialValue del generador y increment a su allocationSize.
Guarda una entidad y lee su ID generado.
El siguiente ejemplo guarda una nueva entidad Movie e imprime su ID generada. El ID depende del punto de inicio de la secuencia. Para un nuevo contador que comienza en 1, la salida es:
var movie = new Movie(); movie.setTitle("The Matrix"); session.persist(movie); System.out.println("Movie created with ID: " + movie.getId());
Configuraciones no admitidas
La extensión Hibernate ORM no admite las siguientes estrategias, tipos y configuraciones relacionadas con secuencias:
IDENTITYy estrategias de generación deTABLEBigIntegery tipos de identificadores generadosBigDecimalNombres de secuencia o esquemas que contienen un carácter
.Nombres de secuencia calificados por un catálogo, como un nombre de tres partes o el atributo
catalog.Secuencia
options@GenericGeneratory generadores@TableGenerator, generadores personalizados que utilizan una anotación@IdGeneratorTypey generadores heredados con nombre comoidentity,tableoincrement.Mapeo de una entidad en la colección
hibernate_sequencesinsert ... selectdeclaraciones que requieren asignación en línea de identificadores generados
Claves primarias compuestas
Para vincular una entidad a más de un campo, defina una clave primaria compuesta. Cree una clase o registro @Embeddable simple que contenga los componentes de la clave. A continuación, anote el campo identificador de su entidad con la anotación @jakarta.persistence.EmbeddedId.
El siguiente elemento incrustable BookId define una clave que consta de un componente publisherId y un componente bookNo:
public record BookId(long publisherId, long bookNo) {}
La siguiente entidad Book utiliza BookId como su clave primaria:
public class Book { private BookId id; private String title; public Book() { } public Book(BookId id, String title) { this.id = id; this.title = title; } // Getter and setter methods }
Debes asignar valores de clave compuesta en tu aplicación antes de persistir una entidad. La extensión Hibernate ORM no genera valores de clave compuesta.
Almacenamiento de claves compuestas
La extensión Hibernate ORM almacena una clave compuesta como un subdocumento _id. La entidad Book precedente produce documentos en el siguiente formato:
{ "_id": { "bookNo": 2, "publisherId": 10 }, "title": "My Book" }
La extensión Hibernate ORM ordena los componentes del subdocumento _id alfabéticamente por nombre, en lugar de seguir el orden en que se declaran. Este orden es el mismo tanto si se declara el elemento incrustable como una clase como un registro.
Importante
El orden de los componentes afecta la coincidencia de documentos.
MongoDB compara los subdocumentos según el orden de los campos, por lo que dos valores _id que contienen los mismos componentes en un orden diferente no coinciden. Dado que la extensión Hibernate ORM siempre escribe los componentes en el mismo orden, este comportamiento solo le afecta si también lee o escribe estos documentos fuera de la extensión Hibernate ORM, por ejemplo, a través del controlador Java de MongoDB.
Limitaciones de la clave compuesta
La extensión Hibernate ORM lanza una excepción FeatureNotSupportedException cuando se inicia la aplicación si se declara una clave compuesta de alguna de las siguientes maneras:
Un identificador no agregado, declarado con la anotación
@jakarta.persistence.IdClasso con múltiples atributos@Id. En su lugar, declare la clave con@EmbeddedId.Un identificador
@Structagregado incrustable. En su lugar, utilice un@Embeddablesimple.Un componente que no es un valor básico, como un
@Embeddableanidado o una colección. Cada componente de una clave compuesta debe ser un valor básico.Una asociación dentro del identificador, incluida la identidad derivada que utiliza la anotación
@jakarta.persistence.MapsId.
Tampoco se puede comparar un identificador compuesto completo utilizando un operador de ordenación como > o <. En su lugar, compare los componentes individualmente.
Datos incrustados
La extensión Hibernate ORM es compatible con documentos incrustados a través de anotaciones ORM Hibernate @Embeddable. Con los documentos incrustados, puedes crear relaciones Uno a Muchos, Muchos a Uno y Uno a Uno dentro de los documentos de MongoDB. Este formato es ideal para representar datos a los que se accede con frecuencia de forma conjunta.
Para representar documentos incrustados, utiliza las anotaciones @Struct y @Embeddable en una clase para crear un objeto agregable @Struct. Luego, incluye el tipo embebible en tu entidad principal como un campo. La extensión ORM de Hibernate admite la incorporación de objetos únicos, arreglos y colecciones de elementos embebibles.
Tip
Para obtener más información sobre embebibles agregados @Struct, consulta @Struct mapeo agregable embebido en la documentación de Hibernate ORM.
Relaciones uno a uno
Una relación uno a uno se da cuando un registro en una base de datos está asociado exactamente con un registro en otra base de datos. En MongoDB, puede crear una colección con un campo de documento incrustado para modelar una relación Uno a Uno. La extensión Hibernate ORM permite crear campos de documentos incrustados mediante el uso de agregados @Struct embebibles.
El ejemplo define un campo con un tipo embebible agregado @Struct en una entidad similar al ejemplo Definir una Entidad en esta guía. La clase de entidad de muestra Movie.java incluye la siguiente información:
@Entityy@Tableanotaciones que definen la entidad y la asignan a la colecciónmovies@Idy las anotaciones@ObjectIdGeneratorque designan el campoidcomo la llave primariaCampo de string que representa el título de la película
@Structcampos agregados integrables que representan premios de películas e información de los estudios
El siguiente ejemplo representa una relación uno a uno porque cada entidad Movie se asocia con un Awards incrustable y un Studio incrustable:
public class Movie { private ObjectId id; private String title; private Awards awards; private Studio studio; public Movie(String title, Awards awards, Studio studio) { this.title = title; this.awards = awards; this.studio = studio; } public Movie() { } // Getter and setter methods }
El siguiente código de muestra crea un embebible agregado Awards @Struct:
public class Awards { private int wins; private int nominations; private String text; public Awards(int wins, int nominations, String text) { this.wins = wins; this.nominations = nominations; this.text = text; } public Awards() { } // Getter and setter methods }
El siguiente código de muestra crea una Studio @Struct agregada incrustable:
public class Studio { private String name; private String location; private int foundedYear; public Studio(String name, String location, int foundedYear) { this.name = name; this.location = location; this.foundedYear = foundedYear; } public Studio() { } // Getter and setter methods }
Relaciones de uno a muchos
Una relación uno a muchos es cuando un registro en una base de datos está asociado con muchos registros en otra base de datos. En MongoDB, puedes definir un campo de colección que almacene una lista de documentos incrustados para modelar una relación uno a muchos. La extensión Hibernate ORM te permite crear campos de documentos incrustados utilizando una lista de @Struct embebibles agregados.
El ejemplo define un campo que almacena una lista de @Struct agregados embebidos en una entidad similar a la del Ejemplo de definición de entidad de esta guía. La clase de entidad de muestra Movie.java incluye la siguiente información:
@Entityy@Tableanotaciones que definen la entidad y la asignan a la colecciónmovies@Idy las anotaciones@ObjectIdGeneratorque designan el campoidcomo la llave primariaCampo de string que representa el título de la película
Campo de lista que almacena varios
Writer@Structembebidos agregados, lo cual representa información de autor
El siguiente ejemplo representa una relación de uno-a-muchos porque cada entidad Movie está asociada con múltiples componibles Writer:
public class Movie { private ObjectId id; private String title; private List<Writer> writers; public Movie(String title, List<Writer> writers) { this.title = title; this.writers = writers; } public Movie() { } // Getter and setter methods }
El siguiente código de muestra crea una Writer @Struct agregada incrustable:
public class Writer { private String name; public Writer() { } public Writer(String name) { this.name = name; } // Getter and setter methods }
Elementos incrustables anidados
Puedes anidar un elemento incrustable aplanado dentro de un elemento incrustable agregado @Struct. Un elemento incrustable aplanado es una clase que incluye una anotación @Embeddable pero no una anotación @Struct. La extensión Hibernate ORM almacena los campos de un elemento incrustable aplanado como campos del documento incrustado principal, en lugar de como un documento anidado independiente.
El siguiente código de ejemplo crea un elemento incrustable agregado Studio @Struct que incluye un elemento incrustable aplanado Address como campo:
public class Studio { private String name; private Address address; public Studio() { } public Studio(String name, Address address) { this.name = name; this.address = address; } // Getter and setter methods }
El siguiente código de ejemplo crea el elemento incrustable aplanado Address. La clase omite la anotación @Struct:
public class Address { private String city; private String country; public Address() { } public Address(String city, String country) { this.city = city; this.country = country; } // Getter and setter methods }
Cuando se persiste una entidad que incluye un campo Studio, los campos Address se convierten en campos del documento incrustado del campo Studio. El siguiente documento de ejemplo tiene un campo Studio llamado studio que almacena los campos de su elemento incrustable aplanado Address:
{ "_id": { "$oid": "..." }, "title": "Breathless", "studio": { "name": "Les Films Impéria", "city": "Paris", "country": "France" } }
Información Adicional
Para aprender a asignar una jerarquía de clases a una colección de MongoDB, consulte la guía "Asignar una jerarquía de herencia de entidades".
Para aprender a usar tus entidades para ejecutar operaciones de base de datos, consulta las siguientes guías en la sección Interactuar con Datos:
Para obtener más información sobre los campos Hibernate ORM, consulte la sección Tipos de mapeo en la documentación de Hibernate ORM.
Para aprender más sobre las entidades de Hibernate ORM, consulta Modelos POJO en la documentación de Hibernate ORM.