问:事务代码为何如此有效?
Q: Transactional Code why does this work so well?
你好,我的专业人士,我有一个简单的问题,我想请求解决这个问题..
这是会员实体
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
/*@ToString(of = {"id", "username", "age"})*/
public class Member {
@Id
/*@GeneratedValue(strategy = GenerationType.IDENTITY)*/
@Column(name = "member_id")
private Long id;
private String username;
private int age;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "member")
private List<Team> teams;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "member")
private List<Coach> coachs;
}
这是 Coach 的一个实体
@Entity
@AllArgsConstructor
@Getter
@Builder
@Setter
@NoArgsConstructor
@ToString(of = {"id","name","career"})
public class Coach {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name= "coach_id")
private Long id;
@Column
private String name;
@Column
private String career;
@ManyToOne(fetch = FetchType.LAZY,cascade = ALL)
@JoinColumn(name = "member_id")
private Member member;
@OneToOne(fetch = FetchType.LAZY,cascade = ALL)
@JoinColumn(name = "team_id")
private Team team;
}
这是控制器代码
@GetMapping("/member")
public void createUser(){
Member m = memberService.createMember();
Coach c = m.getCoachs().get(0);
log.info(c.getName());
}
这是服务代码
private final MemberRepository memberRepository;
@Transactional
public Member createMember(){
return memberRepository.findMemberById(3L);
}
最后一个是 RepositoryCode
Member findMemberById(Long id);
所以我的问题是,当我在控制台的控制器上打印出 Coach 的名字时
打印的真好。
但据我所知,事务已从服务结束,因此持久性容器已关闭,这意味着无法导入教练名称,因为它处于延迟加载状态,持久性容器已关闭,但打印效果很好
我想知道为什么...
这是控制台结果谢谢!!
[2022-01-10 23:27:46.835] [http-nio-9000-exec-2] [] INFO o.a.c.c.C.[.[.[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
[2022-01-10 23:27:46.835] [http-nio-9000-exec-2] [] INFO o.s.w.s.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
[2022-01-10 23:27:46.855] [http-nio-9000-exec-2] [] INFO o.s.w.s.DispatcherServlet - Completed initialization in 19 ms
Hibernate:
/* select
generatedAlias0
from
Member as generatedAlias0
where
generatedAlias0.id=:param0 */ select
member0_.member_id as member_i1_1_,
member0_.age as age2_1_,
member0_.username as username3_1_
from
member member0_
where
member0_.member_id=?
[2022-01-10 23:27:47.007] [http-nio-9000-exec-2] [4c0222d3] INFO p6spy - #1641824867007 | took 15ms | statement | connection 1| url jdbc:mariadb://patrick-lab.cjeq2ffynlc2.ap-northeast-2.rds.amazonaws.com:3306/patricklab?characterEncoding=UTF-8&serverTimezone=UTC
/* select generatedAlias0 from Member as generatedAlias0 where generatedAlias0.id=:param0 */ select member0_.member_id as member_i1_1_, member0_.age as age2_1_, member0_.username as username3_1_ from member member0_ where member0_.member_id=?
/* select generatedAlias0 from Member as generatedAlias0 where generatedAlias0.id=:param0 */ select member0_.member_id as member_i1_1_, member0_.age as age2_1_, member0_.username as username3_1_ from member member0_ where member0_.member_id=3;
[2022-01-10 23:27:47.170] [http-nio-9000-exec-2] [4c0222d3] INFO p6spy - #1641824867170 | took 12ms | commit | connection 1| url jdbc:mariadb://patrick-lab.cjeq2ffynlc2.ap-northeast-2.rds.amazonaws.com:3306/patricklab?characterEncoding=UTF-8&serverTimezone=UTC
;
Hibernate:
select
coachs0_.member_id as member_i4_0_0_,
coachs0_.coach_id as coach_id1_0_0_,
coachs0_.coach_id as coach_id1_0_1_,
coachs0_.career as career2_0_1_,
coachs0_.member_id as member_i4_0_1_,
coachs0_.name as name3_0_1_,
coachs0_.team_id as team_id5_0_1_
from
coach coachs0_
where
coachs0_.member_id=?
[2022-01-10 23:27:47.200] [http-nio-9000-exec-2] [4c0222d3] INFO p6spy - #1641824867200 | took 12ms | statement | connection 1| url jdbc:mariadb://patrick-lab.cjeq2ffynlc2.ap-northeast-2.rds.amazonaws.com:3306/patricklab?characterEncoding=UTF-8&serverTimezone=UTC
select coachs0_.member_id as member_i4_0_0_, coachs0_.coach_id as coach_id1_0_0_, coachs0_.coach_id as coach_id1_0_1_, coachs0_.career as career2_0_1_, coachs0_.member_id as member_i4_0_1_, coachs0_.name as name3_0_1_, coachs0_.team_id as team_id5_0_1_ from coach coachs0_ where coachs0_.member_id=?
select coachs0_.member_id as member_i4_0_0_, coachs0_.coach_id as coach_id1_0_0_, coachs0_.coach_id as coach_id1_0_1_, coachs0_.career as career2_0_1_, coachs0_.member_id as member_i4_0_1_, coachs0_.name as name3_0_1_, coachs0_.team_id as team_id5_0_1_ from coach coachs0_ where coachs0_.member_id=3;
[2022-01-10 23:27:47.213] [http-nio-9000-exec-2] [4c0222d3] INFO m.p.l.m.c.MemberController - Coach1
我相信这是因为您正在使用 spring-boot 默认设置,其中 spring.jpa.open-in-view
设置为 true。
此 属性 启用 模式,您可以简单地认为在处理任何 HTTP 请求时(例如在 Servlet 过滤器等中),事务将在一开始就自动为您打开.因此,在您的服务方法执行之前事务实际上已经打开,并且在您的服务方法完成后它仍然处于活动状态。因此,即使您在服务方法之外访问未初始化的属性,您也不会遇到任何 LazyInitializationException
,因为事务仍然处于活动状态。
关于 spring-boot 是否应该在过去默认启用它存在激烈的争论。如果您有兴趣,可以参考 this 了解更多详情。我个人建议将其关闭。
你好,我的专业人士,我有一个简单的问题,我想请求解决这个问题..
这是会员实体
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
/*@ToString(of = {"id", "username", "age"})*/
public class Member {
@Id
/*@GeneratedValue(strategy = GenerationType.IDENTITY)*/
@Column(name = "member_id")
private Long id;
private String username;
private int age;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "member")
private List<Team> teams;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "member")
private List<Coach> coachs;
}
这是 Coach 的一个实体
@Entity
@AllArgsConstructor
@Getter
@Builder
@Setter
@NoArgsConstructor
@ToString(of = {"id","name","career"})
public class Coach {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name= "coach_id")
private Long id;
@Column
private String name;
@Column
private String career;
@ManyToOne(fetch = FetchType.LAZY,cascade = ALL)
@JoinColumn(name = "member_id")
private Member member;
@OneToOne(fetch = FetchType.LAZY,cascade = ALL)
@JoinColumn(name = "team_id")
private Team team;
}
这是控制器代码
@GetMapping("/member")
public void createUser(){
Member m = memberService.createMember();
Coach c = m.getCoachs().get(0);
log.info(c.getName());
}
这是服务代码
private final MemberRepository memberRepository;
@Transactional
public Member createMember(){
return memberRepository.findMemberById(3L);
}
最后一个是 RepositoryCode
Member findMemberById(Long id);
所以我的问题是,当我在控制台的控制器上打印出 Coach 的名字时
打印的真好。
但据我所知,事务已从服务结束,因此持久性容器已关闭,这意味着无法导入教练名称,因为它处于延迟加载状态,持久性容器已关闭,但打印效果很好
我想知道为什么...
这是控制台结果谢谢!!
[2022-01-10 23:27:46.835] [http-nio-9000-exec-2] [] INFO o.a.c.c.C.[.[.[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
[2022-01-10 23:27:46.835] [http-nio-9000-exec-2] [] INFO o.s.w.s.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
[2022-01-10 23:27:46.855] [http-nio-9000-exec-2] [] INFO o.s.w.s.DispatcherServlet - Completed initialization in 19 ms
Hibernate:
/* select
generatedAlias0
from
Member as generatedAlias0
where
generatedAlias0.id=:param0 */ select
member0_.member_id as member_i1_1_,
member0_.age as age2_1_,
member0_.username as username3_1_
from
member member0_
where
member0_.member_id=?
[2022-01-10 23:27:47.007] [http-nio-9000-exec-2] [4c0222d3] INFO p6spy - #1641824867007 | took 15ms | statement | connection 1| url jdbc:mariadb://patrick-lab.cjeq2ffynlc2.ap-northeast-2.rds.amazonaws.com:3306/patricklab?characterEncoding=UTF-8&serverTimezone=UTC
/* select generatedAlias0 from Member as generatedAlias0 where generatedAlias0.id=:param0 */ select member0_.member_id as member_i1_1_, member0_.age as age2_1_, member0_.username as username3_1_ from member member0_ where member0_.member_id=?
/* select generatedAlias0 from Member as generatedAlias0 where generatedAlias0.id=:param0 */ select member0_.member_id as member_i1_1_, member0_.age as age2_1_, member0_.username as username3_1_ from member member0_ where member0_.member_id=3;
[2022-01-10 23:27:47.170] [http-nio-9000-exec-2] [4c0222d3] INFO p6spy - #1641824867170 | took 12ms | commit | connection 1| url jdbc:mariadb://patrick-lab.cjeq2ffynlc2.ap-northeast-2.rds.amazonaws.com:3306/patricklab?characterEncoding=UTF-8&serverTimezone=UTC
;
Hibernate:
select
coachs0_.member_id as member_i4_0_0_,
coachs0_.coach_id as coach_id1_0_0_,
coachs0_.coach_id as coach_id1_0_1_,
coachs0_.career as career2_0_1_,
coachs0_.member_id as member_i4_0_1_,
coachs0_.name as name3_0_1_,
coachs0_.team_id as team_id5_0_1_
from
coach coachs0_
where
coachs0_.member_id=?
[2022-01-10 23:27:47.200] [http-nio-9000-exec-2] [4c0222d3] INFO p6spy - #1641824867200 | took 12ms | statement | connection 1| url jdbc:mariadb://patrick-lab.cjeq2ffynlc2.ap-northeast-2.rds.amazonaws.com:3306/patricklab?characterEncoding=UTF-8&serverTimezone=UTC
select coachs0_.member_id as member_i4_0_0_, coachs0_.coach_id as coach_id1_0_0_, coachs0_.coach_id as coach_id1_0_1_, coachs0_.career as career2_0_1_, coachs0_.member_id as member_i4_0_1_, coachs0_.name as name3_0_1_, coachs0_.team_id as team_id5_0_1_ from coach coachs0_ where coachs0_.member_id=?
select coachs0_.member_id as member_i4_0_0_, coachs0_.coach_id as coach_id1_0_0_, coachs0_.coach_id as coach_id1_0_1_, coachs0_.career as career2_0_1_, coachs0_.member_id as member_i4_0_1_, coachs0_.name as name3_0_1_, coachs0_.team_id as team_id5_0_1_ from coach coachs0_ where coachs0_.member_id=3;
[2022-01-10 23:27:47.213] [http-nio-9000-exec-2] [4c0222d3] INFO m.p.l.m.c.MemberController - Coach1
我相信这是因为您正在使用 spring-boot 默认设置,其中 spring.jpa.open-in-view
设置为 true。
此 属性 启用 LazyInitializationException
,因为事务仍然处于活动状态。
关于 spring-boot 是否应该在过去默认启用它存在激烈的争论。如果您有兴趣,可以参考 this 了解更多详情。我个人建议将其关闭。