hibernate Spring数据:CrudRepository的保存方法和更新

b91juud3  于 2023-08-06  发布在  Spring
关注(0)|答案(6)|浏览(299)

我想知道如果CrudRepository中的{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); } }

字符串
所以如果我在一个已经注册的条目上调用这个方法,如果它发现一个更改的属性,它会更新它吗?

  • 谢谢-谢谢
f1tvaqid

f1tvaqid1#

我想知道如果CrudRepository中的{保存}方法已经在数据库中找到了条目,它是否会进行更新
Spring文档对此并不精确:
保存给定图元。使用返回的示例进行进一步的操作,因为保存操作可能已经完全更改了实体示例。
但是,由于CrudRepository接口没有提出另一种方法来显式命名更新实体,我们可以假设是的,因为CRUD被期望执行所有CRUD操作(CREATE,READ,UPDATE,DELETE)。
CrudRepository的默认实现SimpleJpaRepository类的实现证实了这一假设,这表明这两种情况都是由以下方法处理的:

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

字符串
所以如果我在一个已经注册的条目上调用这个方法,如果它发现一个更改的属性,它会更新它?
在这种情况下,它将执行合并操作。因此,所有字段都将根据合并级联和只读选项的设置方式进行更新。

rqmkfv5c

rqmkfv5c2#

查看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);
        }
    }

字符串
保存方法管理两种情况:

  • 如果person Id为null(创建了一个新实体),则保存将调用persist method => insert query。
  • 如果person id不为null,则保存将调用merge:从entityManagerFactory(从2级缓存,如果它不存在,那么它将从数据库中获取)获取现有实体,并将分离的实体与托管实体进行比较,最后通过调用更新查询将更改传播到数据库。
vu8f3i0k

vu8f3i0k3#

确切地说,保存(obj)方法将在id为空时将obj视为记录(因此将执行插入操作),而在id为空时将obj视为现有记录(因此将执行合并操作)。

为什么这很重要?

假设Project对象包含一个自动生成的id和一个person_id,它必须是唯一的。创建一个Project对象,并填入person_id,而不是id,然后尝试保存。Hibernate会尝试插入这个记录,因为id是空的,但是如果这个人已经存在于数据库中,你会得到一个重复的键异常。

如何办理

要么执行findByPersonId(id)来检查obj是否已经在数据库中,如果找到了,则从数据库中获取id,
或者只是尝试保存并捕获异常,在这种情况下,您知道它已经在数据库中,并且您需要在保存之前获取并设置id。

jm81lzqq

jm81lzqq4#

我想知道CrudRepository中的{保存}方法是否会在数据库中找到条目时进行更新:
答案是肯定的,如果找到条目,它将更新:
Spring文档:这里https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
保存实体可以通过CrudRepository.save(...)-方法执行。它将使用底层JPA EntityManager持久化或合并给定实体。如果实体尚未持久化,Spring Data JPA将通过调用entityManager.persist(...)-Method保存实体,否则将调用entityManager.merge(...)-Method。

camsedfj

camsedfj5#

在我的例子中,我必须将id属性添加到Entity,并像这样将注解@Id。

@Id
private String id;

字符串
这样,当您获取对象时,该对象具有数据库中实体的ID,并执行Update操作而不是Create操作。

holgip5t

holgip5t6#

我怀疑-如果保存实体包含一个有效的主键值,crudrepository.save()试图更新它,现在,它创建一个新的,并从系统分配下一个可用的键。这就是为什么有时我们得到更新错误(500),当我们试图保存一个新的记录。

相关问题