0

I need to convert to json an Entity with JsonManagedReference and JsonBackReference implementations:

@Entity
@Table(name = "myparenttable", schema = "myschema", catalog = "mydb")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Parent implements Serializable {
    private Integer id_parent;
    private String name;

    @JsonManagedReference
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private List<Child> children;
    
    //getters and setters
    
    
}


@Entity
@Table(name = "mychildtable", schema = "myschema", catalog = "mydb")
public class Child implements Serializable {
    private Integer id_child;
    private String description;
   

    @JsonBackReference
    private Parent parent;
    
    //getters and setters
    
}

With this setup, the persist function is straightforward, I just perform a

em.persist(parent);

and both entities are inserted into the database; but also I need to convert those entities into json for audit purposes. I get a infinite recursion error when doing this:

ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper
                    .writerWithDefaultPrettyPrinter()
                    .writeValueAsString(parent);

Is there a way to do both?

Naty Bizz
  • 2,262
  • 6
  • 33
  • 52
  • 1
    https://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue – ollitietavainen Oct 05 '20 at 15:46
  • It could be preferable to use DTOs (data transfer objects) instead of entities to avoid disclosure of entity implementation details and cluttering the entity with Json annotations as well as provide simpler view. – Nowhere Man Oct 05 '20 at 16:06
  • RestRepositories might be a candidate for your next tech-review. – Grim Oct 05 '20 at 16:22
  • This is weird. You shouldn't be getting an error, `@JsonBackReference`s are not supposed to be serialized. Is `children` the only association in `Parent`? – crizzis Oct 06 '20 at 20:51

2 Answers2

0

You may want to annotate your parent object into Child class with

@JsonIgnore
private Parent parent;

in this way the reference of the parent object isn't put into the serialized json object.

Check if you realy need to implement Serializable interface

Roberto Petrilli
  • 711
  • 1
  • 8
  • 22
0

This is a perfect use case for using DTOs with Blaze-Persistence Entity Views.

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:

@EntityView(Parent.class)
public interface ParentDto {
    @IdMapping
    Integer getId();
    String getName();
    List<ChildDto> getChildren();

    @EntityView(Child.class)
    interface ChildDto {
        @IdMapping
        Integer getId();
        String getDescription();
    }
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

ParentDto a = entityViewManager.find(entityManager, ParentDto.class, id);

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

On top solving your serialization issue, using Blaze-Persistence Entity-Views will also improve performance because it only select the columns that are actually needed.

Christian Beikov
  • 15,141
  • 2
  • 32
  • 58