Persisting a JSON Object using Hibernate and JPA

后端 未结 4 868
庸人自扰
庸人自扰 2020-12-13 07:19

I am trying to store a JSON object in MySQL database in spring boot. I know I am doing something wrong but I a can\'t figure out what it is because I am fairly new to Spring

4条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-13 08:00

    This is a very common requirement, so I decided to write a very detailed article, about the best way to map JSON column types when using JPA and Hibernate.

    Maven dependency

    The first thing you need to do is to set up the following Hibernate Types Maven dependency in your project pom.xml configuration file:

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

    Domain model

    Let's assume you have the following entity:

    @Entity(name = "Book")
    @Table(name = "book")
    @TypeDef(
        typeClass = JsonBinaryType.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
    }
    

    Notice the @TypeDef is used to instruct Hibernate to map the JsonNode object using the JsonBinaryType offered by the Hibernate Types project.

    Testing time

    Now, if you save an entity:

    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 );
    

    Hibernate is going to generate the following SQL statement:

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

    And you can also load it back and modify it:

    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/\"" +
            "}"
        )
    );
    

    Hibernate taking caare of the UPDATE statement for you:

    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
    

提交回复
热议问题