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 elJsonStringType
- los
properties
attribute tiene unjson
tipo de columna y se asigna como unString
¡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;