java - Spring Boot 数据插入一行,其中包含已保存到数据库的数据

标签 java hibernate jpa spring-boot

我正在使用 Hibernate/JPA 开发我的第一个 Spring boot 应用程序。我创建了两个带有 @ManyToMany 映射的 @Entities:TeamGame

目前,数据库有一个保存团队的表,我想插入一个引用两个团队游戏

问题是我收到错误:

`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/

相关文章:

java - 互斥与原子变量

java - GAE java 响应时间极慢

java - Hibernate 一对一映射表现为一对多

java - JPA Criteria API - 设置连接并从连接实体中获取数据

java - 如何实现可移植的 JPA isDirty() 方法?

java - 如何根据微调器选项创建 EditText 字段?

java - 当我将 LinkedHashMap 元素转换为 Set 时,会发生什么情况?

mysql - 使用 MySQL 5.5 在 Hibernate HQL 中从 Int 转换为 Long

java - hibernate : Downside of merge() over update()

hibernate - 可能具有不变的JPA实体?