代码之家  ›  专栏  ›  技术社区  ›  mk_89

Spring hibernate Crudepository根据唯一约束更新保存方法

  •  3
  • mk_89  · 技术社区  · 6 年前

    我理解默认情况下 CrudRepository.save 方法基于主键插入和更新。

    考虑以下实体

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

    因为表中不能有具有相同isbn的书籍,而且我不想担心生成ID,所以我通常将以下json发布到enpoint

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

    返回以下带有自动生成id的

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

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

    但事实上,我想用相同的isbn更新这本书,而不必在post json中指定自动生成的id,因为这对我来说并不重要。有没有一种不用向服务类添加逻辑就可以做到这一点的方法?

    2 回复  |  直到 6 年前
        1
  •  2
  •   htshame    6 年前

    BookEntity ,将其更改并保存。

    自从你 isbn 是独一无二的,您可以这样做:

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

    您可以使用创建一个方法 @Query 注释 BookRepository

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

    bookRepository.updateBook(value, isbn);
    
        2
  •  1
  •   C. Weber    6 年前

    由于您使用的是Hibernate,因此还可以查看Hibernate提供的归化API。除了生成的ID之外,您还将isbn注释为@naturaid,然后使用naturaid API检索您的书籍。

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

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

    关于博物学的进一步阅读,请看 this article this one .

    NaturalIds的一大优点是您可以受益于hibernate缓存机制。

        3
  •  1
  •   lepe    4 年前

    in this article using @NaturalId :

    CrudRepository 通过 JpaRepository ... 但是等等,不是那么简单,但也不是那么难。只需遵循以下步骤:

    1.创建一个 NaturalRepository 接口:

    @NoRepositoryBean
    interface NaturalRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
        Optional<T> findBySimpleNaturalId(ID naturalId);
    }
    

    2.创建此类接口的实现:

    @Transactional(readOnly = true)
    class NaturalRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements NaturalRepository<T, ID> {
        final EntityManager entityManager;
    
        NaturalRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
            super(entityInformation, entityManager);
            this.entityManager = entityManager;
        }
    
        @Override
        Optional<T> findBySimpleNaturalId(ID naturalId) {
            Optional<T> entity = entityManager.unwrap(Session.class)
                    .bySimpleNaturalId(this.getDomainClass())
                    .loadOptional(naturalId);
            return entity;
        }
    }
    

    3.在Spring应用程序中启用它:

    @SpringBootApplication
    @EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl.class)
    class MySpringApp {
    ...
    

    @NaturalId 你的领域:

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

    5.转换你的 积垢的 接口:

    @Repository
    interface BookRepository extends NaturalRepository<Book, String> {
        // You can add other methods here like:
        List<Book> findByTitle(String title);
        List<Book> findByAuthor(String author);
    }
    

    确保:

    • 它现在正在使用 @Repository (而不是 @RepositoryRestResource )
    • 自然保存 (而不是积垢)
    • 第二类应该是 String

    6.最后,您可以将其用作:

    ...
    @Autowired
    BookRepository repository;
    ...
    String isbn = "...";
    try {
        Book book = repository.findBySimpleNaturalId(isbn).get();
        book.author = "gal";
        repository.save(book);
    } catch(NoSuchElementException notfound) {
        ...
    }
    

    很好的一点是,您可以重用 自然保存 NaturalRepositoryImpl 在任何其他项目中,或使用任何其他存储库存储其他表。