当前位置: 首页 > 知识库问答 >
问题:

Spring Boot数据插入包含已持久化到数据库的数据的行

秦炜
2023-03-14

我正在使用Hibernate/JPA完成我的第一个Spring Boot应用程序。我已经创建了两个@Entity,带有@ManyToMore映射: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 */
}

Game.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 */
}

数据oader.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);

}

共有3个答案

方嘉志
2023-03-14

因此,如果您得到“分离实体错误”,这意味着您的子对象没有任何要跟踪的标志。所以,只要你保存,它就会把孩子当作新的对象。所以只需将“版本”字段放在带有注释@version的实体上,并将版本字段放在相关表中。另外,在保存新的子对象时,请确保在子对象上设置父对象。

贺景铄
2023-03-14

在JPA多对多关系中,如果在CascadeType中设置了级联类型。Persist(或CascadeType.ALL,其中包括CascadeType。PERSIST),然后在保存父级并用子级的引用更新它的同时,它将再次尝试保存子级。

由于您正在使用Hibernate,请尝试:

@ManyToOne(cascade = CascadeType.MERGE)
裴宏壮
2023-03-14

这指向您的错误:

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(mappedBy = "homeTeam", fetch = FetchType.EAGER)

这将立即将实例加载到内存中。请注意,您可能需要在所有映射中使用此选项。

UDPATE:下面的选项不适用于@PostContruct方法。见下面的David Lizrraga评论。将适用于更一般的情况,例如从Controller调用Service类,并用@Transactional注释Service方法

如果不能立即将所有内容加载到内存中,则在引用映射对象时,必须确保您的会话仍在范围内。对于您当前的情况,这可以通过使用@Transactional注释对您的方法进行注释来实现。通常,您需要确保访问延迟加载对象的方法是在@Transaction方法中完成的。

 类似资料:
  • 我正在开发一个服务,在该服务中,我侦听队列,反序列化接收到的消息,并将它们持久化到数据库(Oracle)。大致情况: 在缺省消息侦听器bean中,我设置并发性和setSessionTransactived(true)。这足以使整个onMessage具有事务性吗?因此,在一个事务中接收并保存一条消息,并在其中任何一点出现故障时回滚?当试图保存特定消息时,我尝试对其抛出异常,消息确实被回滚到队列,侦听

  • 为了学习数据的持久化,写一个简单的地址薄合约.虽然这个例子因为各种原因作为生产环境的合约不太实用,但它是一个很好的合约用来学习EOSIO的数据持久化并且不会因为与eosio multi_index不相关的相关业务逻辑分心. Step 1:创建一个新的文件夹 进入之前的目录: cd /Users/zhong/coding/CLion/contracts 为我们的合约创建一个新的目录并进去: mkd

  • 目的 配置 NFS 共享为 OpenShift 节点提供存储,并且配置 OpenShift 持久卷以绑定至数据库 Pod。 环境 openshift v3.11.16/kubernetes v1.11.0 步骤 配置 NFS 共享持久卷1. 登录到 NFS 服务器 # ssh nfs.example.com2. 创建 config-nfs.sh 脚本,内容如下 #!/usr/bin/sh exp

  • 问题内容: 我想创建一个作业,但是我想在没有任何数据库持久性的情况下运行它。不幸的是,spring-batch要求以某种方式将作业周期写入数据库,从而迫使我至少提供某种带有transactionmanager和Entitymanager的数据库。 是否可以防止元数据并独立于txmanagers和数据库运行? 更新: 问题答案: 我回到我自己的问题上,因为该解决方案不再起作用。从spring-bat

  • 我想创建一个作业,但我想在没有任何数据库持久性的情况下运行它。不幸的是spring-batch要求以某种方式将作业循环写入数据库的,从而使我至少提供某种带有transactionmanager和EntityManager的db。 是否可以阻止元数据并独立于TXManager和数据库运行? 更新:

  • 我在我的项目中使用postgres docker映像。对于初始化,我使用以下命令来创建和初始化我的数据库(表、视图、数据…) 复制sql_dump.sql /docker-entrypoint-initdb.d 容器停止和删除后是否可以保留这些数据?例如,当我运行postgres的图像时,它将使用这些数据创建数据库,而每次容器启动时都没有加载脚本。只需加载第一次运行创建的数据。 我做了一些研究,发