Zain Elabidine
Zain Elabidine

Reputation: 359

JPA throws lazy loading exception even it is eager fetch

User entity

@Entity
@Table(name = "T_USER")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String email;
    //A user can be employee in many organizations so he look at the same time as many emplyee
    @JsonManagedReference(value = "user-association")
    @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
    private Set<Association> associations;

.... Association entity

@Entity
@Table(name = "T_ASSOCIATION")
public class Association implements Serializable {
    @EmbeddedId
    private AssociationId associationId;
    private String permission;
    @ManyToOne(fetch = FetchType.LAZY)
    @JsonBackReference(value = "user-association")
    @JoinColumn(name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
    private User user;
    @ManyToOne(fetch = FetchType.LAZY)
    @JsonBackReference(value = "organization-association")
    @JoinColumn(name = "organization_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Organization organization;

POST endpoint

 @PostMapping(path = "/{id}/users", consumes = MediaType.APPLICATION_JSON_VALUE)
    public List<User> associateUserToOrganization(@RequestBody AssociationDTO userToOrgDTO, @PathVariable String id) {
        Association association = new Association(new AssociationId(userToOrgDTO.getUserId(), userToOrgDTO.getOrganizationId()));
        association.setPermission("GUEST_SET");
        User userToAffect = userRepository.findById(userToOrgDTO.getUserId()).get();
        Organization orgToAffect = organizationRepository.findById(userToOrgDTO.getOrganizationId()).get();
        userToAffect.addAssociation(association);
        orgToAffect.addAssociation(association);
        organizationRepository.save(orgToAffect);
        return userRepository.findAll().stream().filter(user -> !user.getAssociations().isEmpty()).collect(Collectors.toList());
    }

When I add a user to the organization using POSTMAN with correct input, the famous error of serialization of lazy loading appears even I am not using fetch type Lazy

this is the error

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->jpa.workspace.manytomanyadditional.domain.User$HibernateProxy$pL9wPAuw["hibernateLazyInitializer"])

So i made the solution as it is mentioned in this exception and i put in application.properties,

spring.jackson.serialization.fail-on-empty-beans=false

and @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) to remove it from the json

The issue is fixed sure, but why I am supposed to consider the User->associations relationship as Lazy fetching and not eager as I chose it...Is it related to @JsonManagedReference maybe?

am using spring 2.4.1 and hibernate (core 5.4.25 & annotations 5.1.2 Final)

Upvotes: 1

Views: 476

Answers (1)

dm_tr
dm_tr

Reputation: 4763

Remove @JsonManagedReferenced, @JsonBackReference and add these following in your config class

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(jackson2HttpMessageConverter());
}

@Bean
public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(jacksonBuilder().build());

    return converter;
}

public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();

    Hibernate5Module hibernateModule = new Hibernate5Module();
    hibernateModule.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, false);

    builder.modules(hibernateModule);
    builder.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    builder.featuresToDisable(MapperFeature.DEFAULT_VIEW_INCLUSION);

    return builder;
}

Upvotes: 1

Related Questions