Saltar al contenido

Cómo mapear una columna MySQL JSON a una propiedad de entidad Java usando JPA e Hibernate

Te recomendamos que revises esta solución en un ambiente controlado antes de pasarlo a producción, saludos.

Solución:

Yo prefiero hacerlo de esta manera:

  • Creando convertidor (attribute convertidor) de Mapa a Cadena y viceversa.
  • Uso de Map para mapear el tipo de columna mysql JSON en la clase de dominio (entidad)

El código está abajo.

JsonToMapConverted.java

@Converter
public class JsonToMapConverter 
                    implements AttributeConverter> 

    private static final Logger LOGGER = LoggerFactory.getLogger(JsonToMapConverter.class);

    @Override
    @SuppressWarnings("unchecked")
    public Map convertToDatabaseColumn(String attribute)
    
        if (attribute == null) 
           return new HashMap<>();
        
        try
        
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(attribute, HashMap.class);
        
        catch (IOException e) 
            LOGGER.error("Convert error while trying to convert string(JSON) to map data structure.");
        
        return new HashMap<>();
    

    @Override
    public String convertToEntityAttribute(Map dbData)
    
        try
        
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(dbData);
        
        catch (JsonProcessingException e)
        
            LOGGER.error("Could not convert map to json string.");
            return null;
        
    

Parte de la clase de dominio (mapeo de entidades)

...

@Column(name = "meta_data", columnDefinition = "json")
@Convert(attributeName = "data", converter = JsonToMapConverter.class)
private Map metaData = new HashMap<>();

...

Esta solución funciona perfectamente para mí.

No tiene que crear todos estos tipos manualmente, simplemente puede obtenerlos a través de Maven Central usando la siguiente dependencia:


    com.vladmihalcea
    hibernate-types-52
    $hibernate-types.version 
 

Para obtener más información, consulte el proyecto de código abierto Hibernate Types.

Ahora, para explicar cómo funciona todo.

Suponiendo que tiene la siguiente entidad:

@Entity(name = "Book")
@Table(name = "book")
@TypeDef(
    name = "json", 
    typeClass = JsonStringType.class
)
public class Book 
 
    @Id
    @GeneratedValue
    private Long id;
 
    @NaturalId
    private String isbn;
 
    @Type(type = "json")
    @Column(columnDefinition = "json")
    private String properties;
 
    //Getters and setters omitted for brevity

Observe dos cosas en el fragmento de código anterior:

  • los @TypeDef se utiliza para definir un nuevo tipo de hibernación personalizado, json que es manejado por el JsonStringType
  • los properties attribute tiene un json tipo de columna y se asigna como un String

¡Eso es todo!

Ahora, si guarda una entidad:

Book book = new Book();
book.setIsbn("978-9730228236");
book.setProperties(
    "" +
    "   "title": "High-Performance Java Persistence"," +
    "   "author": "Vlad Mihalcea"," +
    "   "publisher": "Amazon"," +
    "   "price": 44.99" +
    ""
);
 
entityManager.persist(book);

Hibernate va a generar la siguiente declaración SQL:

INSERT INTO
    book 
(
    isbn, 
    properties, 
    id
) 
VALUES
(
    '978-9730228236', 
    '"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99',  
    1
)

Y también puedes volver a cargarlo y modificarlo:

Book book = entityManager
    .unwrap(Session.class)
    .bySimpleNaturalId(Book.class)
    .load("978-9730228236");
     
book.setProperties(
    "" +
    "   "title": "High-Performance Java Persistence"," +
    "   "author": "Vlad Mihalcea"," +
    "   "publisher": "Amazon"," +
    "   "price": 44.99," +
    "   "url": "https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea/dp/973022823X/"" +
    ""
);

Hibernar tomando cuidado del UPDATE declaración para usted:

SELECT  b.id AS id1_0_
FROM    book b
WHERE   b.isbn = '978-9730228236'
 
SELECT  b.id AS id1_0_0_ ,
        b.isbn AS isbn2_0_0_ ,
        b.properties AS properti3_0_0_
FROM    book b
WHERE   b.id = 1    
 
UPDATE
    book 
SET
    properties = '"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99,"url":"https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea/dp/973022823X/"'
WHERE
    id = 1

Todo el código disponible en GitHub.

Si los valores dentro de tu json array son cadenas simples, puedes hacer esto:

@Type( type = "json" )
@Column( columnDefinition = "json" )
private String[] jsonValue;

Aquí puedes ver las comentarios y valoraciones de los lectores

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *