【问题标题】:Update entity via JpaRepository通过 JpaRepository 更新实体
【发布时间】:2017-09-11 05:11:08
【问题描述】:

我正在尝试更新与我的数据库中的 tvShowApiId 属性匹配的实体。我有这样的实体:

@Data
@Setter(AccessLevel.NONE)
@Builder
@Entity
@Table(name = "tv_shows")
public class TvShowLocal implements TvShowEntity<SeasonLocal, EpisodeLocal> {

    @Id
    @GeneratedValue
    @Column(name = "tv_show_id")
    private Integer id;

    private String tvShowApiId;

    @Lob
    @Column(length = 100000)
    private String summary;

    private Integer updated;

    @OneToMany(cascade = CascadeType.ALL)
    @ElementCollection(targetClass = SeasonLocal.class)
    @JoinColumn(name = "tv_show_id")
    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    private List<SeasonLocal> seasons;

    @OneToMany(cascade = CascadeType.ALL)
    @ElementCollection(targetClass = EpisodeLocal.class)
    @JoinColumn(name = "tv_show_id")
    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    private List<EpisodeLocal> episodes;

}

我在我的 JpaRepository 中写了@Query:

public interface TvShowRepository extends JpaRepository<TvShowLocal, Integer> {

    @Modifying
    @Transactional
    @Query("UPDATE TvShowLocal tv SET tv = :tvShow WHERE tv.tvShowApiId = :id")
    void update(@Param("tvShow")TvShowLocal tvShowLocal, @Param("id") String tvShowApiId);

}

但是当我尝试在数据库提供程序类中调用更新方法时,我遇到了异常:

org.hibernate.TransientObjectException: 对象引用了一个未保存的对象 瞬态实例 - 在刷新之前保存瞬态实例: pl.hypeapp.core.entity.database.TvShowLocal;嵌套异常是 java.lang.IllegalStateException: org.hibernate.TransientObjectException:对象引用了一个未保存的 瞬态实例 - 在刷新之前保存瞬态实例: pl.hypeapp.core.entity.database.TvShowLocal

有什么问题?我怎样才能以正确的方式进行这样的操作?

【问题讨论】:

  • 这个查询没有多大意义。更新用于更新实体的一个或多个属性。不要用另一个实体代替一个实体。我认为您正在寻找repository.save(tvShowLocal)。你想达到什么目的?
  • @JBNizet 出于某种原因 repository.save(tvShowLocal) 添加新记录而不是更新。我正在尝试更新我的数据库中的整个记录​​。
  • 这很可能是因为您保存的 TvShowLocal 没有任何 ID。所以它被认为是新的,因此被插入。

标签: java spring hibernate jpa spring-data-jpa


【解决方案1】:

首先你必须从数据库中读取它(用于填充 ID 变量),然后你可以更新对象。 如果 pojo 中存在 id,save 函数会更新它,如果 id 没有值,函数会保存它。

用于更新现有对象

TvShowLocal tvShowLocal = TvShowRepository.getOne(id); 

TvShowRepository.save(tvShowLocal); // tvShowLocal will be update

用于保存新对象

TvShowLocal tvShowLocal2=new  TvShowLocal(); //New Object
TvShowRepository.save(tvShowLocal2);   //tvShowLocal2 will be save as new object

【讨论】:

    【解决方案2】:

    错误表明您尝试保存的对象尚未插入数据库。 您可以按顺序执行以下操作: 1. 插入 TvShowLocal。 2. 执行更新。

    【讨论】:

    • Alex,对象在更新前被插入到数据库中。
    • SeasonLocal 和 EpisodeLocal 怎么样,它们可能与 TvShowLocal 无关。发生瞬态异常时,其中任何一个对象都不会保存。
    猜你喜欢
    • 2019-11-15
    • 2011-03-06
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多