如何使用 JPA 和 Hibernate 将 MySQL JSON 列映射到 Java 实体属性

新手上路,请多包涵

我有一个声明为 JSON 类型的 MySQL 列,但我无法将其映射到 JPA/Hibernate。我在后端使用 Spring Boot。

这是我的代码的一小部分:

 @Entity
@Table(name = "some_table_name")
public class MyCustomEntity implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "json_value")
private JSONArray jsonValue;

该程序返回一个错误并告诉我无法映射该列。

在 mysql 表中,该列定义为:

 json_value JSON NOT NULL;

原文由 Heril Muratovic 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

我更喜欢这样做:

  • 创建从 Map 到 String 的转换器(属性转换器),反之亦然。
  • 使用Map映射域(实体)类中的mysql JSON列类型

代码如下。

JsonToMapConverted.java

 @Converter
public class JsonToMapConverter
                    implements AttributeConverter<String, Map<String, Object>>
{
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonToMapConverter.class);

    @Override
    @SuppressWarnings("unchecked")
    public Map<String, Object> 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<String, Object> dbData)
    {
        try
        {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(dbData);
        }
        catch (JsonProcessingException e)
        {
            LOGGER.error("Could not convert map to json string.");
            return null;
        }
    }
}

域(实体映射)类的一部分

...

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

...

这个解决方案非常适合我。

原文由 Heril Muratovic 发布,翻译遵循 CC BY-SA 4.0 许可协议

您不必手动创建所有这些类型,您可以使用以下依赖项通过 Maven Central 简单地获取它们:

>  <dependency>
>     <groupId>com.vladmihalcea</groupId>
>     <artifactId>hibernate-types-52</artifactId>
>     <version>${hibernate-types.version}</version>
> </dependency>
>
> ```
>
> 有关详细信息,请查看 [Hibernate Types 开源项目](https://vladmihalcea.com/the-hibernate-types-open-source-project-is-born/)。

现在,解释它是如何工作的。

假设您有以下实体:

@Entity(name = “Book”) @Table(name = “book”) @TypeDef( name = “json”, typeClass = JsonType.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

}


请注意上面代码片段中的两件事:

- `@TypeDef` 用于定义新的自定义Hibernate类型, `json` 由 [`JsonType`](https://vladmihalcea.com/how-to-store-schema-less-eav-entity-attribute-value-data-using-json-and-hibernate/) 处理
- `properties` 属性有一个 `json` 列类型,它被映射为 `String`

而已!

现在,如果你保存一个实体:

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 将生成以下 SQL 语句:

INSERT INTO book ( isbn, properties, id ) VALUES ( ‘978-9730228236’, ‘{“title”:“High-Performance Java Persistence”,“author”:“Vlad Mihalcea”,“publisher”:“Amazon”,“price”:44.99}’, 1 )


你也可以加载它并修改它:

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/“” + “}” );


Hibernate 为您处理 `UPDATE` 声明:

SELECT b.id AS id10 FROM book b WHERE b.isbn = ‘978-9730228236’

SELECT b.id AS id1_00 , b.isbn AS isbn2_00 , b.properties AS properti3_00 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

”`

GitHub 上 提供的所有代码。

原文由 Vlad Mihalcea 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题