默认情况下,我理解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的图书,并且我不想担心生成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,因为这对我来说并不重要。有没有一种方法可以在不向服务类添加逻辑的情况下完成此操作?
发布于 2018-06-15 19:53:22
您可以获取BookEntity,更改它并保存它。
因为你的isbn是独一无二的,所以你可以这样做:
BookEntity book = bookRepository.findByIsbn(isbn);
book.setWhateverFieldYouWant(value);
bookRepository.save(book);.或其他解决方案
您可以在BookRepository中创建带有@Query注释的方法
@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);发布于 2018-06-15 22:18:21
既然您正在使用Hibernate,那么您还可以看看Hibernate提供的NaturalId应用程序接口。除了生成的ID之外,还需要将isbn注释为@NaturalId,然后使用NaturalId 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");有关NaturalIds的更多信息,请查看this article (其示例包含isbns)或this one。
NaturalIds的一大优点是您可以受益于hibernate缓存机制。
发布于 2020-04-11 16:17:09
我找到的最好的方法是基于in this article using @NaturalId
它的工作原理是用JpaRepository替换CrudRepository ...但是等等,并不是那么简单,但也不是那么难。只需执行以下步骤:
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 App中启用:
@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl.class)
class MySpringApp {
...4.用@NaturalId注释你的字段:
@Entity
public class BookEntity {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@NaturalId
@Column(name = "isbn")
private String isbn;5.转换您的CrudRepository接口:
@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)NaturalRepository (而不是CrudRepository)String6.最后,您可以将其用作:
...
@Autowired
BookRepository repository;
...
String isbn = "...";
try {
Book book = repository.findBySimpleNaturalId(isbn).get();
book.author = "gal";
repository.save(book);
} catch(NoSuchElementException notfound) {
...
}好的一点是,您可以在任何其他项目中重用NaturalRepository和NaturalRepositoryImpl,或者将任何其他存储库用于其他表。
https://stackoverflow.com/questions/50874911
复制相似问题