为什么在 Spring Data JPA Repository 上使用 save() 之后返回的实例? [英] Why use returned instance after save() on Spring Data JPA Repository?

查看:47
本文介绍了为什么在 Spring Data JPA Repository 上使用 save() 之后返回的实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码如下:

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {}

JpaRepository 来自 Spring Data JPA 项目.

JpaRepository from Spring Data JPA project.

这是测试代码:

public class JpaAccountRepositoryTest extends JpaRepositoryTest {
    @Inject
    private AccountRepository accountRepository;

    @Inject
    private Account account;

    @Test
    @Transactional
    public void createAccount() {
        Account returnedAccount = accountRepository.save(account);

        System.out.printf("account ID is %d and for returned account ID is %d
", account.getId(), returnedAccount.getId());
    }
}

结果如下:

account ID is 0 and for returned account ID is 1

这里来自 CrudReporitory.save() javadoc:

Here is from CrudReporsitory.save() javadoc:

保存给定的实体.使用返回的实例进行进一步的操作,因为保存操作可能已经完全改变了实体实例.

Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.

这是 Spring Data JPA 中 SimpleJpaRepository 的实际代码:

Here is the actual code for SimpleJpaRepository from Spring Data JPA:

 @Transactional
    public T save(T entity) { 
            if (entityInformation.isNew(entity)) {
                    em.persist(entity);
                    return entity;
            } else {
                    return em.merge(entity);
            }
    }

那么,问题是为什么我们需要使用返回的实例而不是原始实例?(是的,我们必须这样做,否则我们将继续使用分离的实例,但为什么)

So, the question is why do we need to use the returned instance instead of the original one? (yes, we must do it, otherwise we continue to work with detached instance, but why)

原始的 EntityManager.persist() 方法返回 void,因此我们的实例附加到持久性上下文.传递帐户以保存到存储库时是否会发生一些代理魔术?是不是Spring Data JPA项目的架构限制?

The original EntityManager.persist() method returns void, so our instance is attached to the persistence context. Does some proxy magic happens while passing account to save to repository? Is it the architecture limitation of Spring Data JPA project?

推荐答案

CrudRepository 接口的 save(...) 方法应该抽象简单地存储一个实体没有不管它处于什么状态.因此它不能公开实际的商店特定实现,即使(如在 JPA 中)商店区分要存储的新实体和要更新的现有实体.这就是为什么该方法实际上被称为 save(…) 而不是 create(…)update(…).我们从该方法返回一个结果,实际上允许存储实现返回一个完全不同的实例,就像 JPA 在 merge(…) 被调用时可能做的那样.

The save(…) method of the CrudRepository interface is supposed to abstract simply storing an entity no matter what state it is in. Thus it must not expose the actual store specific implementation, even if (as in the JPA) case the store differentiates between new entities to be stored and existing ones to be updated. That's why the method is actually called save(…) not create(…) or update(…). We return a result from that method to actually allow the store implementation to return a completely different instance as JPA potentially does when merge(…) gets invoked.

此外,如果实际实现需要填充标识符等,实际上能够处理不可变对象(即不是 JPA)的持久性实现可能不得不返回一个新实例.IE.假设实现只会消耗实体状态通常是错误的.

Also, persistence implementations actually capable of dealing with immutable objects (i.e. not JPA) might have to return a fresh instance if the actual implementation requires populating an identifier or the like. I.e. it's generally wrong to assume that the implementation would just consume the entity state.

因此,一般而言,API 决定更像是对实际实现放宽(允许、容忍)的决定,从而像我们一样实现 JPA 的方法.没有对传递的实体进行额外的代理按摩.

So generally it's more of an API decision to be lenient (permissible, tolerant) regarding the actual implementation and thus implementing the method for JPA as we do. There's no additional proxy massaging done to the entities passed.

这篇关于为什么在 Spring Data JPA Repository 上使用 save() 之后返回的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆