Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring hibernate CrudRepository make the save method update based on a unique constraint

Tags:

I understand by default that the CrudRepository.save method inserts and updates based on a primary key.

Consider the following entity

@Entity
public class BookEntity {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @Basic
    @Column(name = "isbn", unique = true)
    private String isbn;

    @Basic
    @Column(name = "title")
    private String title;

    @Basic
    @Column(name = "author")
    private String author;

    @Basic
    @Column(name = "publication_date")
    private Date publicationDate;

    @Basic
    @Column(name = "rank")
    private Integer rank;
}

Because I can not have books with the same isbn in the table and I don't want to worry about generating ids I normally post the following json to an enpoint

{ "isbn": "10932011", "title": "harry", "author": "jk", "publicationDate": "2018-10-10", "rank": 1000 }

Which returns the following with an auto generated id

{ "id": 3, "isbn": "10932011", "title": "harry", "author": "jk", "publicationDate": "2018-10-10T00:00:00.000+0000", "rank": 1000 }

If I make second call using the same isbn I'll get a constraint error

{ "isbn": "10932011", "title": "harry", "author": "jk3", "publicationDate": "2018-10-10", "rank": 1000 }

But I would like to in fact update the book with the same isbn and not have to specify the auto generated id in the post json as this is not important to me. Is there a way of doing this without having to add logic to a service class?

like image 761
mk_89 Avatar asked Jun 15 '18 11:06

mk_89


People also ask

Does CrudRepository save update?

CrudRepository save() to Update an Instance We can use the same save() method to update an existing entry in our database.

What happens if the argument for Save () method of CrudRepository is null?

So if the field is null in the entity to save , it will overwrite its value to null in the existing row.

What is the difference between a CrudRepository and a JpaRepository?

Each of these defines its own functionality: CrudRepository provides CRUD functions. PagingAndSortingRepository provides methods to do pagination and sort records. JpaRepository provides JPA related methods such as flushing the persistence context and delete records in a batch.

How does JpaRepository save work?

The save operation performs a merge on the underlying EntityManager . This on its own doesn't perform any SQL but just returns a managed version of the entity. If that isn't already loaded into the EntityManager it might do this or it might identify the entity as a new one and make it a managed entity.


2 Answers

You can get the BookEntity, change it and save it.

Since your isbn is unique, you can do something like this:

BookEntity book = bookRepository.findByIsbn(isbn);
book.setWhateverFieldYouWant(value);
bookRepository.save(book);.

Or another solution

You can create a method with @Query annotation in BookRepository:

@Query("UPDATE BookEntity b SET b.whateverField = :value WHERE b.isbn = :isbn")
void updateBook(@Param("value") String value, @Param("isbn") String isbn);

and call it from service:

bookRepository.updateBook(value, isbn);
like image 53
htshame Avatar answered Sep 28 '22 06:09

htshame


Since you are using Hibernate, you can also take a look at the NaturalId API Hibernate provides. In addition to your generated ID you annotate your isbn as a @NaturalId and then use the NaturalId API to retrieve your books.

@Entity
public class BookEntity {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @NaturalId
    @Column(name = "isbn")
    private String isbn;

Load example:

BookEntity book = entityManager.unwrap(Session.class)
.bySimpleNaturalId(BookEntity.class)
.load("your isbn goes here");

For further reading on NaturalIds take a look at this article (its sample is with isbns) or this one.

A big plus of NaturalIds is you can benefit of hibernate caching mechanisms.

like image 32
C. Weber Avatar answered Sep 28 '22 05:09

C. Weber