首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring hibernate CrudRepository根据唯一约束更新保存方法

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

Stack Overflow用户
提问于 2018-06-15 19:42:44
回答 3查看 3.4K关注 0票数 5

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

考虑以下实体

代码语言:javascript
运行
复制
@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的图书,并且我不想担心生成in,所以我通常将以下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进行第二次调用,我会得到一个约束错误

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

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

EN

Stack Overflow用户

发布于 2020-04-11 16:17:09

我找到的最好的方法是基于in this article using @NaturalId

它的工作原理是用JpaRepository替换CrudRepository ...但是等等,并不是那么简单,但也不是那么难。只需执行以下步骤:

1.创建NaturalRepository接口:

代码语言:javascript
运行
复制
@NoRepositoryBean
interface NaturalRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
    Optional<T> findBySimpleNaturalId(ID naturalId);
}

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

代码语言:javascript
运行
复制
@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 App中启用:

代码语言:javascript
运行
复制
@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl.class)
class MySpringApp {
...

4.用@NaturalId注释你的字段:

代码语言:javascript
运行
复制
@Entity
public class BookEntity {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

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

5.转换您的CrudRepository接口:

代码语言:javascript
运行
复制
@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)
  • that ),它现在应该扩展NaturalRepository (而不是CrudRepository)
  • the第二种类型应该是String

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

代码语言:javascript
运行
复制
...
@Autowired
BookRepository repository;
...
String isbn = "...";
try {
    Book book = repository.findBySimpleNaturalId(isbn).get();
    book.author = "gal";
    repository.save(book);
} catch(NoSuchElementException notfound) {
    ...
}

好的一点是,您可以在任何其他项目中重用NaturalRepositoryNaturalRepositoryImpl,或者将任何其他存储库用于其他表。

票数 1
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50874911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档