Home > Blockchain >  JpaRepository returning child for the first item in the list and then only the id for the rest
JpaRepository returning child for the first item in the list and then only the id for the rest

Time:12-02

I have the following Post class:

@Entity
@Table(name = "posts")
@Getter
@Setter
@JsonIdentityInfo(      generator = ObjectIdGenerators.PropertyGenerator.class, 
                        property  = "id", 
                        scope     = Long.class)
public class Post {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String title;
    
    private String subtitle;
    
    private String content;
    
    private String img_url;
    
    @CreationTimestamp
    private Timestamp created_on;
    
    @UpdateTimestamp
    private Timestamp last_updated_on;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "owner_id", nullable=false)
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
    private User creator;
    
}

And the following repository that extends JpaRepository

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

    Optional<Post> findById(Long id);
    
    List<Post> findAll();
    
}

When returning the result of findAll() inside the following controller, only the first creator item is sent completely and the rest just contain the id:

@GetMapping("/news")
    public List<Post> getNews() {
        return postRepository.findAll();
    }

This is the JSON I get as result:

[
{"id":15,"title":"Title example #1","subtitle":"Subtitle example #1","content":"Lorem #1 ipsum dolor sit amet","img_url":null,"created_on":"2021-12-01T00:00:00.000 00:00","last_updated_on":"2021-12-01T00:00:00.000 00:00","creator":{"id":1,"username":"user-example","email":"[email protected]","roles":[{"id":1,"name":"ROLE_USER"}]}}

,{"id":25,"title":"Title example #2","subtitle":"Subtitle example #2","content":"Lorem #2 ipsum dolor sit amet","img_url":null,"created_on":"2021-12-01T00:00:00.000 00:00","last_updated_on":"2021-12-01T00:00:00.000 00:00","creator":1}
]

Why is this happening? Is there a way I can get the whole child object for every element in the JSON array?

Thanks

EDIT: added the User class

@Entity
@Table( name = "users", 
        uniqueConstraints = { 
            @UniqueConstraint(columnNames = "username"),
            @UniqueConstraint(columnNames = "email") 
        })
@DiscriminatorValue(value="USER")
public class User extends OwnerEntity {

    @NotBlank
    @NotNull
    @Size(max = 20)
    private String username;

    @NotBlank
    @NotNull
    @Size(max = 50)
    @Email
    private String email;

    @NotBlank
    @Size(max = 120)
    @JsonIgnore
    private String password;
    
    @CreationTimestamp
    private Timestamp created_on;
    
    @UpdateTimestamp
    private Timestamp last_updated_on;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable( name = "user_roles", 
                joinColumns = @JoinColumn(name = "user_id"), 
                inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();

    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Institution> institutions;
    
    @OneToMany(mappedBy="creator", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    protected Set<Post> posts;
    
    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Institution> following;
}

EDIT 2: Added the OwnerEntity class

@Entity
@Table(name = "entities")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
@Getter
@Setter
@JsonIdentityInfo(      generator = ObjectIdGenerators.PropertyGenerator.class, 
                        property  = "id", 
                        scope     = Long.class)
public class OwnerEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;
    
}

CodePudding user response:

Your OwnerEntity also has @JsonIdentityInfo. In its reference documentation we can read the following:

Annotation used for indicating that values of annotated type or property should be serializing so that instances either contain additional object identifier (in addition actual object properties), or as a reference that consists of an object id that refers to a full serialization. In practice this is done by serializing the first instance as full object and object identity, and other references to the object as reference values.

This perfectly explains why you are getting the JSON like that. If you don't want this, just remove @JsonIdentityInfo but it might be there to fix an infinite recursion while serializing bidirectional relationships (you can read more about this in the following online resource https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion).

  • Related