2017-02-10 6 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

が本当にデータベースには更新がありません: またPersistableインタフェースを実装し、@Version注釈を追加し、このようにそれを使用するようにトライすることができますか?マージ操作で渡したエンティティは更新されませんが、新しいものが返されます – Deltharis

+0

本当に、データベーステーブルの更新はありません。(私は 'spring.jpa.show-sql = true'でクエリを書きます) – Artegon

+0

エンティティを行うMananger。更新後にflush()を実行しますか? JPAはデータベースリクエストをキャッシュし、後で(トランザクションが終了した後)ただちにフラッシュします...単一ノード/アプリケーションでjpaを使用している限り問題ありません。 – Anton

答えて

0

「bal = balanceRepository.save(bal);」を設定してみてください。 ...これは保存されたオブジェクトを返し、生成されたIDを含みます...あなたが次の保存を実行すると、それは既存のオブジェクトであることがわかり、保存の代わりに更新を行います。

これでうまくいかない場合は、newBalanceオブジェクトを作成して最初の保存時に設定し、2回目のsaveおよびsetFinalBalance呼び出しで使用します。

@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

EntityManager.persist(最初の保存時に呼び出される)は、渡すオブジェクトを更新します。したがって、 'bal'は生成されたIDを持ちます。 – Deltharis

+0

@クイントン - それはすべての利点を打ち負かす.... – Artegon

+0

ええ...私はそれについて考えなかった。私の悪い。 8- { 私は通常、Spring BootのCrudRepositoryを使用しています。私のJPAリポジトリは少し錆びています。私の答えは無視してください。 8-} –

0

はあなたのコードような方法を書き換えるようにしてください。

+1

'@ Transactional'はjavaxかSpringか? – 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

この機能を無効にするには、EntityPersistableインターフェイスを実装します。私は、PKとしてgereneratedテーブルIDを使用しなかったので、これを行う必要がありました。

@DataJpaTestの間にデータを保存しようとしていますか?これはオープンなトランザクションにつながり、データベースには保存されないためです。

balanceRepository.save(bal);の戻り値はbalと同じですか?そうでない場合は、@Versionアノテーションを追加することができます。私は時々これが助けになることを読んだ。

@Version 
private Long version; 

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

@Override 
public boolean isNew() { 
    return version == null; 
} 
関連する問題