使用休眠和 JPA 持久化 JSON 对象

2022-09-03 04:34:51

我正在尝试在春季启动中将JSON对象存储在MySQL数据库中。我知道我做错了什么,但我不知道这是什么,因为我对春天相当陌生。

我有一个休息端点,我在其中获取以下JSON对象(通过HTTP PUT),我需要将其存储在数据库中,以便用户以后可以(通过HTTP GET)获取它。

{
  "A": {
    "Name": "Cat",
    "Age": "1"
  },
  "B": {
    "Name": "Dog",
    "Age": "2"
  },
  "C": {
    "Name": "Horse",
    "Age": "1"
  }
}

请注意,在上面的情况下,对象中的可能会有所不同,由于该要求,我正在使用a来捕获控制器中的对象。HashMap

@RequestMapping(method = RequestMethod.POST)
    public String addPostCollection(@RequestBody HashMap<String, Animal> hp) {

        hp.forEach((x, y) -> {
            postRepository.save(hp.get(x));
        });

        return "OK";

    }

正如您在方法中看到的那样,我可以迭代并保留db中的每个对象。但我正在寻找一种方法将整个记录保留在单个记录中。我做了一些阅读,他们建议我使用映射。HashMapAnimalHashMap@ManyToMany

任何人都可以为我指出一个方向,以不同的方式坚持下去吗?(或者使用唯一和正确的方法来做到这一点?HashMap@ManyToMany


答案 1

对专家的依赖性

您需要做的第一件事是在项目配置文件中设置以下休眠类型 Maven 依赖项:pom.xml

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

域模型

假设您有以下实体:

@Entity(name = "Book")
@Table(name = "book")
@TypeDef(
    typeClass = JsonType.class, 
    defaultForType = JsonNode.class
)
public class Book {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String isbn;

    @Column(columnDefinition = "jsonb")
    private JsonNode properties;

    //Getters and setters omitted for brevity
}

请注意,用于指示 Hibernate 使用 Hibernate Types 项目提供的 JsonType 映射对象。@TypeDefJsonNode

测试时间

现在,如果保存实体:

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

休眠将生成以下 SQL 语句:

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

您还可以将其加载并修改:

Session session = entityManager.unwrap( Session.class );
 
Book book = session
    .bySimpleNaturalId( Book.class )
    .load( "978-9730228236" );
 
LOGGER.info( "Book details: {}", book.getProperties() );
 
book.setProperties(
    JacksonUtil.toJsonNode(
        "{" +
        "   \"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/\"" +
        "}"
    )
);

冬眠为你采取声明的caare:UPDATE

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
 
-- Book details: {"price":44.99,"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon"}
 
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

答案 2

您可以使用 FasterXML(或类似方法)将 Json 解析为实际对象(您需要定义类)并用于检索 Json 字符串。它还简化了对象的使用,因为您的数据类也可能具有功能。Json.toJson(yourObj).toString()