Voici le code:
@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {}
JpaRepository du projet Spring Data JPA.
Voici le code de test:
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\n", account.getId(), returnedAccount.getId());
}
}
Voici le résultat:
account ID is 0 and for returned account ID is 1
Voici de CrudReporsitory.save () javadoc:
Enregistre une entité donnée. Utilisez l'instance renvoyée pour d'autres opérations car l'opération de sauvegarde peut avoir complètement changé l'instance d'entité.
Voici le code réel pour SimpleJpaRepository de Spring Data JPA:
@Transactional
public T save(T entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
Donc, la question est pourquoi avons-nous besoin d'utiliser l'instance retournée au lieu de l'instance d'origine? (oui, nous devons le faire, sinon nous continuons à travailler avec une instance détachée, mais pourquoi)
La méthode originale EntityManager.persist () renvoie void, donc notre instance est attachée au contexte de persistance. Y a-t-il une magie de proxy lors du passage du compte pour enregistrer dans le référentiel? Est-ce la limitation de l'architecture du projet Spring Data JPA?
La méthode save(…)
de l'interface CrudRepository
est censée abstraire simplement le stockage d'une entité, quel que soit son état. Ainsi, elle ne doit pas exposer l'implémentation spécifique au magasin, même si (comme dans le cas JPA), le magasin fait la distinction entre les nouvelles entités à stocker et celles existantes à mettre à jour. C'est pourquoi la méthode est en fait appelée save(…)
pas create(…)
ou update(…)
. Nous retournons un résultat de cette méthode pour permettre à l'implémentation du magasin de renvoyer une instance complètement différente comme le fait JPA potentiellement lorsque merge(…)
est invoquée.
Donc, généralement, il s'agit plus d'une décision de l'API d'être indulgente (admissible, tolérante) concernant la mise en œuvre réelle et donc la mise en œuvre de la méthode pour JPA comme nous le faisons. Aucune messagerie proxy supplémentaire n'est envoyée aux entités transmises.
Vous avez manqué la deuxième partie: si l'entité n'est pas nouvelle, merge
est appelée. merge
copie l'état de son argument dans l'entité attachée avec le même ID et renvoie l'entité attachée. Si l'entité n'est pas nouvelle et que vous n'utilisez pas l'entité renvoyée, vous apporterez des modifications à une entité détachée.