user5959252
user5959252

Reputation:

Jpa Repository save() doesn't update existing data

I am trying to update data and as I know save() method saves entity if the id is null or update an existing entity in the database if the given id is found in DB.

However, when I try to save data it is not updated:

public Employer update() {
    Employer emp = Employer.builder()
        .id(2L) // it exists in database
        .name('new company name')
        .build();

    return repository.save(emp);
}

But, when I retrieve data from the database and update its fields and save again it updates:

public Employer update() {
    Employer emp = repository.getOne(2L);
    emp.setName('new company name');

    return repository.save(emp);
}

Can anyone explain the reason for this behavior? I read the documentation but couldn't find anything related to that.

Here is my repository:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface Employer extends JpaRepository<Employer, Long> {

}

and entity:

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(schema = "public", name = "employer")
public class Employer {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @NotBlank
  @Size(max = 50)
  private String name;

}

Upvotes: 11

Views: 63780

Answers (5)

IncogVito
IncogVito

Reputation: 71

For these who's struggling this issue with ReactiveMongoRepository. There's a better way to handle it faster without unnecessary loading entity from database. You would have to implement Persistable interface to indicate if the entity should be inserted or updated.

SimpleReactiveMongoRepository#save looks like this

@Override
public <S extends T> Mono<S> save(S entity) {

    Assert.notNull(entity, "Entity must not be null");

    if (entityInformation.isNew(entity)) {
        return mongoOperations.insert(entity, entityInformation.getCollectionName());
    }

    return mongoOperations.save(entity, entityInformation.getCollectionName());
}

So in your entity you need to provide information whether the Entity is a new one to be inserted or is the old one just to be updated.

@Data
@Document("ActionRequest")
@NoArgsConstructor
@AllArgsConstructor
public class ActionRequestEntity implements Persistable<String> {
@Id
private String requestId;
{...}

@Override
public String getId() {
    return requestId;
}

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

Then JPARepository will know how to handle your entity during the save operation.

Upvotes: 0

Prince
Prince

Reputation: 163

I was also facing the same issue. The thing is JPA doesn't update your data if new data is same as old one. If there is no change in the modified data, it won't run the update query.

Upvotes: 0

Nitin Sharma
Nitin Sharma

Reputation: 37

This question is already been answered but this is my understanding of topic, as I recently started working on it.

This can be answered on basis of Transient and Persistent/managed entities.

Transient entity : A new entity object created which is not associated with any session till now. This object is not related to any stored data in database since it is freshly created.

When you fetch a record from db it is fetched in managed or persistent state and any changes made to it will be reflected back to the record that it is mapped to.

Suggestion 1 : You should not be manually adding primary key values since it is already AutoIncremented.

Suggestion 2 : If you already have recirds id, fetch it from db first and then update it.

Here is a Stackoverflow discussion on the topic to get you some more insight : What are detached, persistent and transient objects in hibernate?

Upvotes: 1

R.G
R.G

Reputation: 7141

To update an existing entity object through JPA it should be made available to the entity manager first.

Read through the article

https://www.objectdb.com/java/jpa/query/jpql/update

excerpt from the same

1.Retrieving the entity objects into an EntityManager.
2.Updating the relevant entity object fields within an active transaction.
3.Applying changes to the database by calling the commit method.

I assume for the case where update does not happen , the entity is not a managed entity yet.

More on managed entity : https://www.baeldung.com/hibernate-entity-lifecycle#managed-entity

Upvotes: 1

codeworks elegant
codeworks elegant

Reputation: 1071

Your Entity Employer looks to be in detached/Transient state and you are passing id value manually which is not permitted, as it is marked as @GeneratedValue(strategy = GenerationType.IDENTITY).

What you need to do is when you know the primary key value i.e id value, first you fetch the Entity from the database using findById() method, by which Entity comes into Managed state and then try to update the Entity by calling save() method. This will update your Entity.

For more info on Entity state you can refer this: https://vladmihalcea.com/a-beginners-guide-to-jpa-hibernate-entity-state-transitions/

Upvotes: 27

Related Questions