jnemecz
jnemecz

Reputation: 3608

Why doesn't JpaRepository update my entity?

I have such Jpa repository:

public interface BalanceRepository extends JpaRepository<Balance, Long> {

}

As far as I know (and this answer it confirms) entity manager insert new record (when entity is new) and update entity record when is not new.

My entity class hierarchy:

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

and 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;
        }

 }

When I save new Balance entity, new record is inserted but not update is done, why?

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);

Update 1 - When I findOne(Long id) updated record, value seems to be updated, but value in database is not changed.

Upvotes: 4

Views: 15311

Answers (3)

neutron
neutron

Reputation: 373

Hei

This part looks weird to me:

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

Because this function is covered by the Persistable interface and is the default implementation. Read here: https://docs.spring.io/spring-data/jpa/docs/1.4.1.RELEASE/reference/html/jpa.repositories.html#jpa.entity-persistence.saving-entites

You can override this function by implementing the Persistable interface in your Entity. I needed to do this because I used an not gerenerated table id as PK.

Do you try to save the data during a @DataJpaTest? Because this can lead to open transactions and will not save to the database.

Is the return value from balanceRepository.save(bal); the same as bal? If not you can trie to add the @Version annotation. I read that this sometimes might help. You can also trie to implement the Persistable interface and add the @Version annotation and use it like this:

@Version
private Long version;

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

@Override
public boolean isNew() {
    return version == null;
}

Upvotes: 0

rvit34
rvit34

Reputation: 2106

Try to rewrite your code such way:

@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);

  }

}

And tell me does it help or not.

Upvotes: 0

Quinton Delpeche
Quinton Delpeche

Reputation: 236

Try setting "bal = balanceRepository.save(bal);" ... this will return the saved object and will include the generated id ... when you run the next save, it will know that it is an existing object and will then do an update instead of a save.

If that doesn't work, create a newBalance object, set it on the first save and use it for the second save and setFinalBalance call.

Upvotes: 2

Related Questions