概要
SpringBootではJpaRepositoryを継承したInterfaceを作っただけなのにCRUDのメソッドたちを使えます。
public interface MemberRepository extends JpaRepository<Member, Long> {
}
一般的にInterfaceを実装した実装クラスがないと動作しないはず。
→結論、SpringDataJpaが動作するようにしてくれました!
SpringDataJpaがMemberRepositoryの実装クラスを作る
SpringDataJpaはJpaRepositoryを継承したInterfaceを探し、実装クラスを生成してくれます。
Proxyクラスを生成してくれた?
テストで実験してみよう
@Autowired
MemberRepository memberRepository;
@Test
public void test() {
System.out.println(memberRepository.getClass());
System.out.println(memberRepository.getClass().getName);
}
// 結果
class com.sun.proxy.$Proxy123 // Proxyオブジェクト!
org.springframework.data.jpa.repository.support.SimpleJpaRepository // ClassName
Proxyオブジェクトが生成され、SimpleJpaRepositoryを基に動作していることがわかりました。
SimpleJpaRepository(JpaRepositoryの実装クラス)
@Repository
@Transactional(
readOnly = true
)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
public List<T> findAll() {
return this.getQuery((Specification)null,(Sort)Sort.unsorted()).getResultList();
}
@Transactional
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null");
if (this.entityInformation.isNew(entity)) {
this.entityManager.persist(entity);
return entity;
} else {
return (S)this.entityManager.merge(entity);
}
}
@Transactional
public void delete(T entity) {
Assert.notNull(entity, "Entity must not be null");
if (!this.entityInformation.isNew(entity)) {
Class<?> type = ProxyUtils.getUserClass(entity);
T existing = (T)this.entityManager.find(type, this.entityInformation.getId(entity));
if (existing != null) {
this.entityManager.remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
}
}
}
...
SimpleJpaRepositoryはCRUD機能を含め、JpaRepositoryの実装をしていることがわかりました。
結局EntityManager
使って実装していますね。
つまり、純粋Jpaで実装されていて、PersistenceContextを活用していることがわかります。
おかげで開発者はEntity管理の面倒をしなくてもJpaの強さを丸ごと使って開発ができます。
HibernateもProxyオブジェクトを使う