首页 > 解决方案 > Spring Data @JoinColumn 和实体更新

问题描述

首先,我没有给这个问题合适的标题。随时更新它。

问题陈述

我有以下实体:

@Entity
public class Session {
    @Column(name = "last_screen_id")
    private Long lastScreenId;

    @JoinColumn(name = "last_screen_id", referencedColumnName = "id", insertable = false, updatable = false)
    @OneToOne
    private Screen lastScreen;

    // Getters and setters for lastScreenId
    // Getter for lastScreen (I don't have a setter for lastScreen object since lastScreen object is marked as insertable=false and updatable=false)
}

如果我更新lastScreenId我希望lastScreen更新对象。例如,我将lastScreenIdfrom设置12使用session.setLastScreenId(2)我希望lastScreen对象是具有 id 的对象2

所以这是我尝试过的:

  1. 只需更新lastScreenId. 我希望该lastScreen对象会被更新,因为该session对象仍然是一个MANAGED实体

    失败,因为lastScreen对象仍然是前一个对象

  2. 使用 a更新lastScreenId并保存对象,并将当前对象替换为保存在数据库中的新对象sessionSessionRepositorysessionsession

    session= sessionRepository.save(screen);

    lastScreen由于未从数据库中提取对象而失败

  3. 使用另一种方法保存session与不同的事务

     @Transactional(Transactional.TxType.REQUIRES_NEW)
     public Session saveSessionInANewTransaction(Session session) {
    
         return sessionRepository.save(session);
    
     }
    

    这个也失败了。

标签: javahibernatespring-data-jpa

解决方案


您需要在同一对象中复制映射“last_screen_id”列的任何原因?

如果不是,我建议您将其更改为仅将其映射到Screen更简单的实体:

@Entity
public class Session {

    @JoinColumn(name = "last_screen_id", referencedColumnName = "id")
    @OneToOne
    private Screen lastScreen;

}

要将 Screen 从 ID 1 更新到 ID 2 ,您必须首先获取 new Screen 并将其设置为SessionlastScreen.Throw 异常,如果没有新的 ID Screen

public void updateSessionLastScreen(Long sessionId, Long newScreenId){
    Session session  = sessionRepository.findbyId(sessionId).orElseThrow(()-> new RuntimeException("Session does not exist"));  
    Screen newScreen = screenRepository.findById(newScreenId).orElseThrow(()-> new RuntimeException("Screen does not exist")); 
    session.setLastScreen(newScreen);
}

推荐阅读