我正在使用 Hibernate/JPA 开发我的第一个 Spring boot 应用程序。我创建了两个带有 @ManyToMany
映射的 @Entities
:Team
和 Game
。
目前,数据库有一个保存团队
的表,我想插入一个引用两个团队
的游戏
。
问题是我收到错误:
`org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataLoader': Invocation of init method failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.data.entities.FootballTeam.homeGames, could not initialize proxy - no Session
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:838) ~[spring-context-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:347) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:295) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
at com.example.FootballPoolSpringSpringBoot.main(FootballPoolSpringSpringBoot.java:11) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.3.0.RELEASE.jar:1.3.0.RELEASE]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.data.entities.FootballTeam.homeGames, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:555) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.write(AbstractPersistentCollection.java:400) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:314) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at com.example.service.DataLoader.loadData(DataLoader.java:106) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:354) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:305) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
... 23 common frames omitted`.
我做错了什么?
@Entity
public class FootballTeam {
private FootballTeam(){/**/}
public FootballTeam(String teamName) {
this.teamName = teamName;
}
@Id
@GeneratedValue
private Long teamId;
@Column(name = "team_name", unique = true)
private String teamName;
@Column(name = "short_name", unique = true)
private String teamShortName;
private String teamLeague;
private String teamDivision;
@Embedded
private Location teamLocation;
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "favoriteTeams")
private List<Users> fans = new ArrayList<>();
@OneToMany(mappedBy = "homeTeam")
List<FootballGame> homeGames = new ArrayList<>();
@OneToMany(mappedBy = "visitingTeam")
List<FootballGame> awayGames = new ArrayList<>();
/* getters and setters omitted for brevity */
}
游戏.java
@Entity
@Table(name = "football_game",
uniqueConstraints= @UniqueConstraint(
columnNames={"played_on", "home_team", "visiting_team"}))
public class FootballGame {
private FootballGame(){/**/}
public FootballGame(Date playedOn, FootballTeam homeTeam, FootballTeam visitingTeam) {
this.homeTeam = homeTeam;
this.playedOn = playedOn;
this.visitingTeam = visitingTeam;
}
@Id
@GeneratedValue
private Long gameId;
@Column(name = "played_on", nullable = false)
private Date playedOn;
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "home_team", nullable = false)
private FootballTeam homeTeam;
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "visiting_team", nullable = false)
private FootballTeam visitingTeam;
private int homeTeamScore;
private int visitingTeamScore;
@OneToOne(mappedBy = "footballGame")
private FootballPool footballPool;
/* getters and setters omitted for brevity */
}
DataLoader.class
@Service
public class DataLoader {
private FootballTeamRepository teamRepository;
private FootballGameRepository gameRepository;
@Autowired
public DataLoader(FootballGameRepository gameRepository,
FootballTeamRepository teamRepository) {
this.gameRepository = gameRepository;
this.teamRepository = teamRepository;
}
@PostConstruct
private void loadData(){
FootballTeam f4 = new FootballTeam("lil Shin-Kickers");
f4.setTeamLocation(new Location("California"));
teamRepository.save(f4);
FootballTeam f1 = new FootballTeam("Tumble Tots");
f1.setTeamLocation(new Location("Colorado"));
teamRepository.save(f1);
FootballTeam homeTeam = teamRepository.findTeamByTeamNameIgnoreCase("lil Shin-Kickers");
System.out.println(homeTeam.getTeamName());
FootballTeam visitingTeam = teamRepository.findTeamByTeamNameIgnoreCase("Tumble Tots");
FootballGame footballGame = new FootballGame(new Date(), homeTeam, visitingTeam);
footballGame.setHomeTeamScore(7);
footballGame.setVisitingTeamScore(21);
gameRepository.save(footballGame);
}
最佳答案
这指向您的错误:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.data.entities.FootballTeam.homeGames, could not initialize proxy - no Session
@OneToMany
和 @ManyToMany
(对于 Hibernate,我相信 @ManyToOne
和 @OneToOne
)是懒惰的实例化。这意味着它不会在需要时将对象或对象列表从数据库加载到内存中。在您的情况下,您会收到异常,因为当您引用 FootballTeam
类时, session 已关闭或不在范围内。
如果映射不会太大,您可以在映射上指定获取策略:
@OneToMany(mappedBy = "homeTeam", fetch = FetchType.EAGER)
这将立即将实例加载到内存中。请注意,您可能需要在所有映射中执行此操作。
UDPATE:以下选项不适用于 @PostContruct
方法。请参阅下面 David Lizárraga 的评论。适用于更一般的情况,例如从 Controller
调用 Service
类并使用 @Transactional 注释
Service
方法
如果无法立即将所有内容加载到内存中,则在引用映射对象时,您必须确保您的 Session
仍在范围内。对于您当前的情况,可以通过使用 @Transactional 注释来注释您的方法来完成此操作。一般来说,您需要确保访问延迟加载对象的方法是在 @Transaction
方法中完成的。
关于java - Spring Boot 数据插入一行,其中包含已保存到数据库的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34424000/