1

My case is super weird, and quite frankly I am not entirely sure if its a Jackson serialization problem or something to do with Spring Data JPA on how it fetches Lazy objects

Spring 2.0.2

  • spring-boot-starter-data-jpa
  • spring-boot-starter-web
  • spring-boot-devtools
  • mysql-connector-java

When you search most people's problem with Jackson is it serialization a lazy fetch outside a session causing below exception. However, I am not getting this exception at all....

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

Problem

  1. It actually fetches the data and return json object in my controller (hibernate query below). Its a problem to Fetch Eagerly because its getting unnecessary large data that is not used.

Structure (Omit getter and setter to make the thread shorter)

       User
        | <---[ OneToMany ]        
     Employee { hierarchies entity }
        |
  +-----+-----+
  |           |
PartTime   FullTime

User

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;

@OneToMany(mappedBy="user")
@JsonIgnoreProperties("user")
private List<Employee> employee = new ArrayList<>();

Empolyee

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Employee {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JsonIgnoreProperties("employee")
private User user;

FullTime / PartTime ( field salary change to hourelywage when in PartTime )

@Entity
public class FullTime extends Employee  {

private BigDecimal salary;

UserRepository extends CrudRepository

UserService

public User getUserById(Long id) {

    Optional<User> optionalUser = userRepo.findById(id);
    User user = optionalUser.get();

    logger.info("\n User -> {}", user);
    return user;
}

Controller

@RestController
@RequestMapping(value="/api/user")
public class UserController {

  @GetMapping(value="/{userId}" )
  public User getUser(@PathVariable("userId") Long id) {
    return userService.getUserById(id);
  }   

}

On my Application extends CommandLineRunner which allows me to run commands at start of application

@Override
public void run(String... args) throws Exception {
  logger.info("users 1 -> {}" , userService.getUserById(1L));
}


Hibernate: 
select
    user0_.id as id1_3_0_,
    user0_.name as name2_3_0_ 
from
    user user0_ 
where
    user0_.id=?

INFO 14434 --- [  restartedMain] ication$$EnhancerBySpringCGLIB$$6cf0457c :     
users 1 -> 
User [id=1, name=Jack]

But when I go through my controller http://localhost:8080/api/user/1 I get 2 separate hibernate calls both seems to be within my service layer. Keep in mind, my service layer I do not have Transactional, so its really weird....

Hibernate:  << 1st
select
    user0_.id as id1_3_0_,
    user0_.name as name2_3_0_ 
from
    user user0_ 
where
    user0_.id=?

com.example.app.service.UserService      : << -- In service 
User -> 
User [id=1, name=Jack]

Hibernate: 
select
    employee0_.user_id as user_id2_0_0_,
    employee0_.id as id1_0_0_,
    employee0_.id as id1_0_1_,
    employee0_.user_id as user_id2_0_1_,
    employee0_1_.salary as salary1_1_1_,
    employee0_2_.hourly_wage as hourly_w1_2_1_,
    case 
        when employee0_1_.id is not null then 1 
        when employee0_2_.id is not null then 2 
        when employee0_.id is not null then 0 
    end as clazz_1_ 
from
    employee employee0_ 
left outer join
    full_time employee0_1_ 
        on employee0_.id=employee0_1_.id 
left outer join
    part_time employee0_2_ 
        on employee0_.id=employee0_2_.id 
where
    employee0_.user_id=?

Now if its a Jackson Serialization problem I have visited Avoid Jackson serialization on non fetched lazy objects , Configure Jackson to omit lazy-loading attributes in Spring Boot , and many more, but all done by exdending WebMvcConfigurerAdapter which in spring5 i believe is deprecated ?

If its something to do with Spring Data JPA... then please shed some light because I always thought you need @Transaction annotation for lazy Fetch to associate relationship with hibernate session...

Sorry for the long thread...

Eric Huang
  • 1,114
  • 3
  • 22
  • 43
  • You should use DTO. Please check https://stackoverflow.com/questions/1612334/difference-between-dto-vo-pojo-javabeans and http://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application You are returning hibernate object and during serialization, there are not session, because it is already closed. – Lemmy May 29 '18 at 07:41
  • 3
    Thanks for looking. but I am actually not getting LazyInitializationException.... I don't prefer DTO because its adds extra layer to the app.... – Eric Huang May 31 '18 at 02:51

1 Answers1

2

I think you have the property spring.jpa.open-in-view enabled (default is true). Check to see if you see the following message in your log:

spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning

You should see the required exception if you disable it.