弹簧启动 2.Jackson json 序列化或 Spring Data JPA FetchType.Lazy.



我的情况非常奇怪,坦率地说,我不完全确定这是杰克逊序列化问题还是与Spring Data JPA有关,它如何获取懒惰对象

春季 2.0.2

  • 弹簧-引导-启动器-数据-JPA
  • 弹簧启动启动网
  • 弹簧引导开发工具
  • MySQL-connector-java

当您搜索大多数人对杰克逊的问题时,序列化是会话外的懒惰获取导致以下异常。但是,我根本没有得到这个例外....

org.hibernate.LazyInitializationException: 无法初始化代理 - 无会话

问题

  1. 它实际上在我的控制器中获取数据并返回 json 对象(下面的休眠查询(。 急切地获取是一个问题,因为它会获取未使用的不必要的大数据。

结构(省略吸气剂和设置器以使螺纹更短(

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

用户

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

恩波利

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JsonIgnoreProperties("employee")
private User user;

全职/兼职(兼职时现场工资更改为小时工资(

@Entity
public class FullTime extends Employee  {
private BigDecimal salary;

UserRepository 扩展了 CrudRepository

用户服务

public User getUserById(Long id) {
Optional<User> optionalUser = userRepo.findById(id);
User user = optionalUser.get();
logger.info("n User -> {}", user);
return user;
}

控制器

@RestController
@RequestMapping(value="/api/user")
public class UserController {
@GetMapping(value="/{userId}" )
public User getUser(@PathVariable("userId") Long id) {
return userService.getUserById(id);
}   
}

在我的应用程序上扩展了命令行运行程序,它允许我在应用程序启动时运行命令

@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]

但是当我通过我的控制器时http://localhost:8080/api/user/1我收到 2 个单独的休眠调用,这两个调用似乎都在我的服务层内。请记住,我的服务层我没有事务性,所以它真的很奇怪......

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=?

现在,如果这是我访问过的杰克逊序列化问题 避免对未获取的惰性对象进行杰克逊序列化 ,将 Jackson 配置为在 Spring 启动中省略延迟加载属性 ,以及更多,但所有这些都是通过扩展 WebMvcConfigurerAdapter 完成的,我相信在 spring5 中已被弃用?

如果它与Spring Data JPA有关...那么请阐明一些信息,因为我一直认为您需要@Transaction惰性 Fetch 的注释才能将关系与休眠会话相关联......

对不起,线程太长...

我认为您已启用属性spring.jpa.open-in-view(默认值为true(。检查您是否在日志中看到以下消息:

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

如果禁用它,您应该会看到所需的异常。

最新更新