database Spring data : CrudRepository 的保存方法和更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38893831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring data : CrudRepository's save method and update
提问by Moatez Bouhdid
I wanted to know if the {save}
method in CrudRepository
do an update if it finds already the entry in the database like :
我想知道该{save}
方法CrudRepository
是否进行更新,如果它已经在数据库中找到了如下条目:
@Repository
public interface ProjectDAO extends CrudRepository<Project, Integer> {}
@Service
public class ProjectServiceImpl {
@Autowired private ProjectDAO pDAO;
public void save(Project p) { pDAO.save(p); } }
So if I call that method on an already registred entry, it'll update it if it finds a changed attribute ?
因此,如果我在已注册的条目上调用该方法,它会在找到更改的属性时更新它吗?
Thanks.
谢谢。
回答by davidxxx
I wanted to know if the {save} method in CrudRepository do an update if it finds already the entry in the database
我想知道 CrudRepository 中的 {save} 方法是否进行更新,如果它已经找到了数据库中的条目
The Spring documentation about it is not precise :
关于它的 Spring 文档并不准确:
Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.
保存给定的实体。使用返回的实例进行进一步的操作,因为保存操作可能已经完全改变了实体实例。
But as the CrudRepository
interface doesn't propose another method with an explicit naming for updating an entity, we may suppose that yes since CRUD is expected to do all CRUD operations (CREATE, READ, UPDATE, DELETE).
但是由于CrudRepository
接口没有提出另一种具有显式命名的方法来更新实体,我们可能会假设是的,因为 CRUD 应该执行所有 CRUD 操作(CREATE、READ、UPDATE、DELETE)。
This supposition is confirmed by the implementation of the SimpleJpaRepository
class which is the default implementation of CrudRepository
which shows that both cases are handled by the method :
该假设由SimpleJpaRepository
类的实现证实,该类是默认实现CrudRepository
,表明这两种情况都由方法处理:
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
So if I call that method on an already registered entry, it'll update it if it finds a changed attribute?
因此,如果我在已注册的条目上调用该方法,它会在找到更改的属性时更新它吗?
It will do a merge operation in this case. So all fields are updated according to how the merging cascade and read-only option are set.
在这种情况下,它将执行合并操作。因此,所有字段都根据合并级联和只读选项的设置方式进行更新。
回答by SEY_91
Looking at the default implemantation of CrudRepository interface
查看 CrudRepository 接口的默认实现
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
Save method manage two situations:
Save方法管理两种情况:
-If the person Id is null (a new entity is created) then save will call persist method => insert query will be executed.
- 如果人员 ID 为空(创建了一个新实体),则 save 将调用 persist 方法 => 将执行插入查询。
-If the person id is not null then save will call merge: fetch the existing entity from entityManagerFactory(from the 2 level cache if it doesn't exist then it will be fetched from the database) and comparing the detached entity with the managed and finally propagate the changes to the database by calling update query.
- 如果人员 ID 不为空,则保存将调用合并:从 entityManagerFactory 中获取现有实体(如果不存在则从 2 级缓存中获取)并将分离的实体与托管和最后通过调用更新查询将更改传播到数据库。
回答by Harry
I wanted to know if the {save} method in CrudRepository do an update if it finds already the entry in the database:
我想知道 CrudRepository 中的 {save} 方法是否进行更新,如果它已经在数据库中找到了条目:
The Answer is Yes, It will update if it finds an entry:
答案是肯定的,如果找到条目,它会更新:
From Spring Documentation: Herehttps://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html?
来自 Spring 文档:这里https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html?
Saving an entity can be performed via the CrudRepository.save(…)-Method. It will persist or merge the given entity using the underlying JPA EntityManager. If the entity has not been persisted yet Spring Data JPA will save the entity via a call to the entityManager.persist(…)-Method, otherwise the entityManager.merge(…)-Method will be called.
保存实体可以通过 CrudRepository.save(…)-Method 执行。它将使用底层 JPA EntityManager 持久化或合并给定实体。如果实体尚未持久化,Spring Data JPA 将通过调用 entityManager.persist(...)-Method 保存实体,否则将调用 entityManager.merge(...)-Method。
回答by LConrad
To be precise, the save(obj) method will treat obj as a newrecord if the id is empty(therefore will do an insert) and will treat obj as an existingrecord if the id is filled in(therefore will do the merge).
Why is this important?
Let's say the Project object contains an auto-generated id and also a person_id which must be unique. You make a Project object and fill in the person_id but not the id and then try to save. Hibernate will try to insert this record, since the id is empty, but if that person exists in the database already, you will get a duplicate key exception.
How to handle
Either do a findByPersonId(id) to check if the obj is in the db already, and get the id from that if it is found,
Or just try the save and catch the exception in which case you know it's in the db already and you need to get and set the id before saving.
准确地说,如果id 为空, save(obj) 方法会将 obj 视为新记录(因此会进行插入),如果填写了id,则将 obj 视为现有记录(因此会进行合并) . 为什么这很重要?假设 Project 对象包含一个自动生成的 id 和一个必须是唯一的 person_id。您创建一个 Project 对象并填写 person_id 而不是 id ,然后尝试保存。Hibernate 会尝试插入这条记录,因为 id 是空的,但是如果那个人已经存在于数据库中,你会得到一个重复键异常。如何处理
要么做一个 findByPersonId(id) 来检查 obj 是否已经在 db 中,如果找到了,则从中获取 id,
或者只是尝试保存并捕获异常,在这种情况下,您知道它已经在 db 中,并且您在保存之前需要获取并设置 id。
回答by Santiago
In my case I had to add the id property to the Entity, and put the annotation @Id like this.
在我的情况下,我必须将 id 属性添加到实体,并像这样放置注释@Id。
@Id
private String id;
This way when you get the object has the Id of the entity in the database, and does the Update operation instead of the Create.
这样当你得到对象在数据库中具有实体的Id时,并执行更新操作而不是创建操作。