spring 懒加载和懒加载异常总结
-
实体类:
@Entity @Table(name = "book_info") public class Book { @Id @GeneratedValue private Integer id; @Column(name = "book_name") private String bookName; @Column(name = "user_id") private Integer userId; // 省略 构造函数 // 省略 get set 方法 // 省略 toString 方法 }@Entity @Table(name = "user_info") public class User { @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; @Column(nullable = false) private Integer age; @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY) @JoinColumn(name = "user_id") private List<Book> books = new ArrayList<>(); // 省略 构造函数 // 省略 get set 方法 // 省略 toString 方法 } -
JpaRepository 类
public interface BookRepository extends JpaRepository<Book, Long> {}public interface UserRepository extends JpaRepository<User, Long> { User findByName(String name); User findByNameAndAge(String name, Integer age); @Query(value ="from User u where u.name=:name") User findUser(@Param("name") String name); } -
调用
@Test public void test02() { User user = userRepository.findUser("robinyang"); System.out.println(user); } -
结果
发现会出现异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.robin.jpa.domain.User.books, could not initialize proxy - no Session根据异常提示,发现是获取 books的数据,session 没有。
-
分析
image我们断点来看看,发现user里部分值是取到的,但是在获取 books的时候,报懒加载异常。
原因: 是由于我们的这里采用的是懒加载,也就是说books数据只有在真正使用的时候才会去查询数据库,但此时session 已经关闭了,导致没有连接查询,所以查询失败。
-
解决办法 (有两种方式解决,推荐第二种,既可以节省性能,代码上简单)
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)将懒加载改成立即加载,为fetch=FetchType.EAGER-
增加事物,将需要使用数据的步骤,全部放在一个事物里面,就可以解决
@Service public class UserService { @Autowired private UserRepository userRepository; @Transactional public void show() { User user = userRepository.findByName("robinyang"); System.out.println(user); } }
