Database 春季数据:Crudepository';s保存方法和更新
我想知道Database 春季数据:Crudepository';s保存方法和更新,database,hibernate,spring-mvc,spring-data,spring-data-jpa,Database,Hibernate,Spring Mvc,Spring Data,Spring Data Jpa,我想知道crudepository中的{save}方法如果已经在数据库中找到条目,是否会执行更新,如: @Repository public interface ProjectDAO extends CrudRepository<Project, Integer> {} @Service public class ProjectServiceImpl { @Autowired private ProjectDAO pDAO; public void save(Project p
crudepository
中的{save}
方法如果已经在数据库中找到条目,是否会执行更新,如:
@Repository
public interface ProjectDAO extends CrudRepository<Project, Integer> {}
@Service
public class ProjectServiceImpl {
@Autowired private ProjectDAO pDAO;
public void save(Project p) { pDAO.save(p); } }
@存储库
公共接口项目DAO扩展了CRUDEPository{}
@服务
公共类ProjectServiceImpl{
@自连线私人项目DAO pDAO;
公共无效保存(项目p){pDAO.save(p);}
所以,如果我在一个已经注册的条目上调用该方法,它会在发现一个已更改的属性时更新它吗
谢谢。查看CRUDepository接口的默认实现
/*
* (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);
}
}
/*
*(非Javadoc)
*@see org.springframework.data.repository.crudepository#save(java.lang.Object)
*/
@交易的
公共存储(S实体){
if(entityInformation.isNew(实体)){
em.persist(实体);
返回实体;
}否则{
返回em.merge(实体);
}
}
保存方法管理两种情况:
-如果人员Id为null(创建了一个新实体),则将执行save调用persist method=>insert查询
-如果人员id不为null,则save将调用merge:从entityManagerFactory获取现有实体(如果不存在,则从2级缓存获取),并将分离的实体与托管实体进行比较,最后通过调用update query将更改传播到数据库
我想知道crudepository中的{save}方法是否进行了更新 如果它已经在数据库中找到该条目 关于它的Spring文档并不精确: 保存给定的实体。将返回的实例用于进一步的操作 因为保存操作可能已更改实体实例 完全是 但是由于
crudepository
接口没有提出另一种具有显式命名的方法来更新实体,我们可以假设是,因为CRUD需要执行所有CRUD操作(创建、读取、更新、删除)
通过实现SimpleJpaRepository
类,该类是crudepository
的默认实现,它显示这两种情况都由以下方法处理:
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
@Transactional
公共存储(S实体){
if(entityInformation.isNew(实体)){
em.persist(实体);
返回实体;
}否则{
返回em.merge(实体);
}
}
因此,如果我对已注册的条目调用该方法,它将更新
如果它发现了一个更改的属性,它会怎么做
在这种情况下,它将执行合并操作。因此,所有字段都会根据合并级联和只读选项的设置进行更新。我想知道Crudepository中的{save}方法是否会在数据库中找到条目时进行更新: 答案是肯定的,如果找到条目,它将更新: 来自Spring文档:这里 可以通过crudepository.save(…)-方法保存实体。它将使用底层JPA EntityManager持久化或合并给定实体。如果实体尚未被持久化,Spring Data JPA将通过调用entityManager.persist(…)-方法保存实体,否则将调用entityManager.merge(…)-方法。准确地说,如果id为空,则save(obj)方法将obj视为新的记录(因此将进行插入)如果填写了id,则将obj视为现有的记录(因此将进行合并)
为什么这很重要?
假设项目对象包含一个自动生成的id和一个必须唯一的person_id。创建一个项目对象并填写person_id,但不填写id,然后尝试保存。Hibernate将尝试插入此记录,因为id为空,但如果数据库中已经存在此人,则会出现重复密钥异常
如何处理
执行findByPersonId(id)检查obj是否已经在数据库中,如果找到它,则从中获取id,
或者只是尝试保存并捕获异常,在这种情况下,您知道它已经在数据库中,您需要在保存之前获取并设置id 在我的例子中,我必须将id属性添加到实体中,并像这样放置注释@id
@Id
private String id;
这样,当您获取对象时,该对象在数据库中具有实体的Id,并且执行更新操作而不是创建。因此,如果该实体具有复杂类型,比如说图像,那么我想我需要徒手更新。图像是什么意思?如果它不是jpa关系字段,则在任何情况下都会进行更新。因此,如果要保存的实体中的字段为null,那么它将在现有行中将其值覆盖为null。另一件事,这里我看到了'@Transactionel',因此我不需要将该注释添加到服务类no?
@Transactional
默认使用Progration:Propagation.REQUIRED,它支持当前事务,如果不存在,则创建一个新事务。因此,是的,在您的服务中不需要使用@Transactional,但是如果您希望从服务方法手动处理回滚,则不需要使用@Transactional。如果我回答了你的问题,不要犹豫,接受它。