2017-02-10 42 views
3

我有這樣的JPA庫:爲什麼JpaRepository沒有更新我的實體?

public interface BalanceRepository extends JpaRepository<Balance, Long> { 

} 

據我所知(這answer這確認)實體管理器插入新記錄(當實體是新的)和更新實體記錄是不是新的時候。

我的實體類層次結構:

@Entity 
@Table(name = "balances") 
public class Balance extends BaseEntity { 
// omitted 
} 

BaseEntity

@MappedSuperclass 
    @EntityListeners(AuditingEntityListener.class) 
    @JsonIgnoreProperties({"handler", "hibernateLazyInitializer"}) 
    public abstract class BaseEntity { 

     private static Logger LOGGER = LogManager.getLogger(BaseEntity.class); 

     @Id 
     @GeneratedValue(strategy = GenerationType.IDENTITY) 
     @Column(name = "id", updatable = false, nullable = false) 
     @JsonProperty("id") 
     private Long id; 

     public Long getId() { 
      return id; 
     } 

     public void setId(Long id) { 
       this.id = id; 
      } 

    public boolean isNew() { 
      return id == null; 
     } 

} 

當我保存新Balance實體,插入新記錄,但不更新完成後,爲什麼呢?

Balance bal = new Balance(); 
     bal.setFinalBalance(BigDecimal.TEN); 
     bal.setUser(user); 
     bal.setRecordDate(date); 
     bal.setMinusBalance(BigDecimal.TEN); 
     bal.setPlusBalance(BigDecimal.TEN); 
     bal.setTotalBalance(BigDecimal.TEN); 

     // entity is inserted 
     balanceRepository.save(bal); 

     // no update... 
     bal.setFinalBalance(bal.getFinalBalance().add(BigDecimal.TEN)); 
     balanceRepository.save(bal); 

更新1 - 當我findOne(Long id)更新的記錄,價值似乎被更新,但在數據庫中的值不會改變。

+0

是否真的在數據庫中沒有更新?合併操作不會更新您傳遞的實體,但會返回一個新的實體 – Deltharis

+0

真的,數據庫表中沒有更新...(我用'spring.jpa.show-sql = true'寫出查詢) – Artegon

+0

您是否嘗試過做一個實體Mananger。更新後刷新()? JPA緩存數據庫請求並稍後刷新它們(在事務結束後)......只要您在單個節點/應用程序上使用jpa,那麼這是沒有問題的...... – Anton

回答

0

嘗試設置「bal = balanceRepository.save(bal);」 ...這將返回保存的對象,並將包括生成的ID ...當您運行下一次保存時,它會知道它是一個現有對象,然後將執行更新而不是保存。

如果這不起作用,請創建一個newBalance對象,並在第一次保存時將其設置爲第二次保存和setFinalBalance調用。

+1

EntityManager.persist(會在第一次保存時調用)會更新傳遞給它的對象 - 所以'bal'確實有生成的id。 – Deltharis

+0

@昆頓 - 它擊敗所有優點.... – Artegon

+0

是啊......我沒有想到這一點。我的錯。 8- { 我通常使用Spring Boot的CrudRepository ...所以我的JPA Repository有點生疏......忽略我的答案。 8-} –

0

嘗試重寫代碼這樣的方式:

@Service 
public class BalanceService { 
    // ... 
    @Transactional 
    public void save(Balance balance){ 
    balanceRepository.save(balance); 
    } 

    public void check(){ 
    Balance bal = new Balance(); 
    bal.setFinalBalance(BigDecimal.TEN); 
    bal.setUser(user); 
    bal.setRecordDate(date); 
    bal.setMinusBalance(BigDecimal.TEN); 
    bal.setPlusBalance(BigDecimal.TEN); 
    bal.setTotalBalance(BigDecimal.TEN); 
    // entity is inserted 
    save(bal); 

    bal.setFinalBalance(bal.getFinalBalance().add(BigDecimal.TEN)); 
    save(bal); 

    } 

} 

並告訴我,它幫助與否。

+1

從@ javax或Spring的'@ Transactional'? – Artegon

+0

Spring,off course – rvit34

+0

這不會有什麼區別... Spring使用代理和內部方法調用不通過代理。因此'@ Transactional'在這裏基本上被忽略了。 –

0

這部分看起來怪我:

public boolean isNew() { 
    return id == null; 
} 

因爲這個功能由Persistable接口覆蓋,是默認的實現。請閱讀此處:https://docs.spring.io/spring-data/jpa/docs/1.4.1.RELEASE/reference/html/jpa.repositories.html#jpa.entity-persistence.saving-entites

您可以通過在Entity中實現Persistable接口來覆蓋此功能。我需要這樣做,因爲我使用了一個沒有生氣的表格ID作爲PK。

您是否嘗試在@DataJpaTest期間保存數據?因爲這會導致打開的事務並不會保存到數據庫。

是否從balanceRepository.save(bal);返回的值與bal相同?如果不是,您可以添加@Version註釋。我讀到這有時可能會有所幫助。 您也可以特里結構來實現Persistable接口,並添加@Version註釋和使用它像這樣:

@Version 
private Long version; 

@Override 
public Long getId() { 
    return id; 
} 

@Override 
public boolean isNew() { 
    return version == null; 
} 
相關問題