这对我来说有点奇怪。我的理解是,如果你尝试访问Hibernate会话之外的实体,你应该得到一个LazyInitializationException - 没有会话,但我没有得到这个异常。事实上,似乎我仍然在我的服务层之外的会话中继续使用@Transactional注释。
问题
结构
User
|
Profile { hierarchies entity }
|
+-----+-----+
| |
Teacher Student
用户
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstname;
private String lastname;
@OneToMany(fetch = FetchType.LAZY , mappedBy = "user")
@JsonManagedReference
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Profile> profiles = new ArrayList<>();
服务
@Override
@Transactional
public User getUserById(Long id) {
Optional<User> optionalUser = userRepo.findById(id);
User user = optionalUser.get();
logger.info("\n User -> {}", user);
return user;
}
Controller :: 而不是thow Exception,或者应该返回空数组。 Hibernate执行左连接
@GetMapping(value="/{userId}", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public User getUser(@PathVariable("userId") Long userId) {
logger.info("User Controller is called");
User user = userService.getUserById(userId);
logger.info("User is returned -> {}", user);
logger.info("Profiles -> {}", user.getProfiles()); // <-- Expecting this to throw LazyInitializationException
return user;
}
控制台
018-05-31 15:17:35.462 INFO 15599 --- [nio-8080-exec-1] c.d.c.controller.UserController : User Controller is called
Hibernate:
select
user0_.id as id1_4_0_,
user0_.firstname as firstnam2_4_0_,
user0_.lastname as lastname3_4_0_
from
user user0_
where
user0_.id=?
2018-05-31 15:17:35.467 INFO 15599 --- [nio-8080-exec-1] c.d.c.services.UserServiceImpl :
User ->
User [id=1, firstname=Hendric, lastname=Rosenberg]
2018-05-31 15:17:35.467 INFO 15599 --- [nio-8080-exec-1] c.d.c.controller.UserController : User is returned ->
User [id=1, firstname=Hendric, lastname=Rosenberg]
Hibernate:
select
profiles0_.user_id as user_id2_3_0_,
profiles0_.id as id1_3_0_,
profiles0_.id as id1_3_1_,
profiles0_.user_id as user_id2_3_1_,
profiles0_1_.citizent_id as citizent1_2_1_,
profiles0_1_.profile_type as profile_2_2_1_,
profiles0_2_.license as license1_1_1_,
profiles0_2_.practitioner_type as practiti2_1_1_,
profiles0_2_.profile_type as profile_3_1_1_,
profiles0_2_.specialized as speciali4_1_1_,
case
when profiles0_1_.id is not null then 1
when profiles0_2_.id is not null then 2
when profiles0_.id is not null then 0
end as clazz_1_
from
profile profiles0_
left outer join
patient profiles0_1_
on profiles0_.id=profiles0_1_.id
left outer join
medical_profession profiles0_2_
on profiles0_.id=profiles0_2_.id
where
profiles0_.user_id=?
c.d.c.controller.UserController : User is returned -> [
Student [profileType=STUDENT, id=A1236578889],
Teacher [profileType=TEACHER, license=234SFLLWEKD32342]]
答案 0 :(得分:1)
spring.jpa.open-in-view = true
默认设置。所以你不会得到一个LazyInitializationException
此属性将注册OpenEntityManagerInViewInterceptor
Spring Web请求拦截器,它将JPA EntityManager绑定到线程以进行整个请求处理。用于“Open EntityManager in View”模式,即允许在Web视图中进行延迟加载,尽管原始事务已经完成。 此拦截器通过当前线程使JPA EntityManagers可用,该线程将由事务管理器自动检测。它适用于通过JpaTransactionManager或JtaTransactionManager进行的服务层事务以及非事务性只读执行。 与OpenEntityManagerInViewFilter相比,此拦截器在Spring应用程序上下文中设置,因此可以利用bean连接。