我必须参加具有一对多关系的课程。当我尝试访问延迟加载的集合时,出现·。我在网上搜索了一段时间,现在我知道我得到了异常,因为用于加载保存集合的类的会话已关闭。但是我没有找到解决方案(或者至少我不理解它们)。基本上我有那些课:
User
@Entity @Table(name = "user") public class User { @Id @GeneratedValue @Column(name = "id") private long id; @OneToMany(mappedBy = "creator") private Set<Job> createdJobs = new HashSet<>(); public long getId() { return id; } public void setId(final long id) { this.id = id; } public Set<Job> getCreatedJobs() { return createdJobs; } public void setCreatedJobs(final Set<Job> createdJobs) { this.createdJobs = createdJobs; } }
UserRepository
public interface UserRepository extends JpaRepository<User, Long> {}
UserService
@Service @Transactional public class UserService { @Autowired private UserRepository repository; boolean usersAvailable = false; public void addSomeUsers() { for (int i = 1; i < 101; i++) { final User user = new User(); repository.save(user); } usersAvailable = true; } public User getRandomUser() { final Random rand = new Random(); if (!usersAvailable) { addSomeUsers(); } return repository.findOne(rand.nextInt(100) + 1L); } public List<User> getAllUsers() { return repository.findAll(); } }
Job
@Entity @Table(name = "job") @Inheritance @DiscriminatorColumn(name = "job_type", discriminatorType = DiscriminatorType.STRING) public abstract class Job { @Id @GeneratedValue @Column(name = "id") private long id; @ManyToOne @JoinColumn(name = "user_id", nullable = false) private User creator; public long getId() { return id; } public void setId(final long id) { this.id = id; } public User getCreator() { return creator; } public void setCreator(final User creator) { this.creator = creator; } }
JobRepository
public interface JobRepository extends JpaRepository<Job, Long> {}
JobService
@Service @Transactional public class JobService { @Autowired private JobRepository repository; public void addJob(final Job job) { repository.save(job); } public List<Job> getJobs() { return repository.findAll(); } public void addJobsForUsers(final List<User> users) { final Random rand = new Random(); for (final User user : users) { for (int i = 0; i < 20; i++) { switch (rand.nextInt(2)) { case 0: addJob(new HelloWorldJob(user)); break; default: addJob(new GoodbyeWorldJob(user)); break; } } } } }
App
@Configuration @EnableAutoConfiguration @ComponentScan public class App { public static void main(final String[] args) { final ConfigurableApplicationContext context = SpringApplication.run(App.class); final UserService userService = context.getBean(UserService.class); final JobService jobService = context.getBean(JobService.class); userService.addSomeUsers(); // Generates some users and stores them in the db jobService.addJobsForUsers(userService.getAllUsers()); // Generates some jobs for the users final User random = userService.getRandomUser(); // Picks a random user System.out.println(random.getCreatedJobs()); } }
我经常读到会话必须绑定到当前线程,但是我不知道如何使用Spring的基于注释的配置来做到这一点。有人可以指出我该怎么做吗?
PS我想使用延迟加载,因此急于加载是没有选择的。
基本上,你需要在事务内部时获取惰性数据。如果你的服务类别为@Transactional,那么你在其中时一切都应该没问题。退出服务类后,如果尝试get延迟集合,你将获得该异常,该异常位于main()方法line中System.out.println(random.getCreatedJobs());。
@Transactional
main()
System.out.println(random.getCreatedJobs())
现在,归结为你需要返回的服务方法。如果userService.getRandomUser()期望返回一个初始化了作业的用户,以便你可以对其进行操作,则该方法的责任是取回它。使用Hibernate最简单的方法是调用Hibernate.initialize(user.getCreatedJobs())。
userService.getRandomUser()
Hibernate.initialize(user.getCreatedJobs()