Notice
Recent Posts
Recent Comments
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
10-10 22:21
Archives
Today
Total
관리 메뉴

Developer_Neo

[Spring 입문] - 스프링 데이터 JPA 본문

Spring

[Spring 입문] - 스프링 데이터 JPA

_Neo_ 2022. 8. 6. 21:25
반응형

스프링 데이터 JPA란?

JPA를 한 단계 더 추상화 시켜 개발 용이성을 상당히 올려주는 인터페이스
JPA말고 스프링 데이터 JPA를 사용하면, 리포지토리의 인터페이스만으로(구현 클래스 없이) 개발을 완료 할 수 있다.
반복 개발해온 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공해서 코드를 적을 것이 없다.

Spring Data JPA는 Repository라는 인터페이스를 제공합니다.
이 Repository는 정해진 규칙으로 인터페이스를 선언하기만 해도 자동으로 내부에서 구현체를 만들어 동작시켜줍니다.
특히 자주 사용하는 매서드들(findAll(), save(), delete() 등...)은 별도로 선언하지 않아도 사용 할 수 있습니다.


우리는 이전의 글에서 JPA를 사용하였고, JpaMemberRepository에 해당하는 구현 클래스를 만들어 사용하였다.
밑에 이전 글을 참고하겠다. 

2022.08.05 - [분류 전체보기] - [Spring 입문] - JPA

 

[Spring 입문] - JPA

JPA란? Java Persistence API로 자바 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용되는 인터페이스의 모음  반복적인 CRUD SQL을 처리해준다 SQL과 데이터 중심의 설계에서 객체 중심의 설계로..

devloper-dreaming.tistory.com

 

스프링 Data JPA를 사용하기 위해서는 인터페이스로 제공하면 된다.
이때 인터페이스를 작성할 때 상속받아야하는 인터페이스가 있다. 그것은 JpaRepository<?,?>라고 하는 것이다.
그런데 <?,?>에 해당하는 것을 전달해야하는데
첫번째 인자에는 우리가 테이블로써 저장하고 있는 것을 작성한 도메인에 해당하는 코드인 Member
두번째 인자에는 Member의 Pk의 타입인 long타입으로 넣어주어야한다.
그리고 인터페이스는 클래스와 달리 다중상속이 되기에 우리가 작성했던 MemberRepository에 해당하는 것을 다중 상속해준다.
위와 같이 해주면 우리가 작성한 인터페이스만 있게 되는데 이것이 JpaRepository<?,?>라는 것을 상속 받고 있으면,  우리가 작성한 인터페이스에 대한 구현체를 자동으로 만들어준다.
그리고 스프링 빈에 자동 등록해준다.(스프링 데이터 JPA가 JpaRepository<?,?>를 상속한 것을 보고 자동으로 등록해준다.)

위와 같이 적는다.

 

이미 구현되어져 있는 JpaRepository의 코드들을 보자

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll()
	 */
	@Override
	List<T> findAll();

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
	 */
	@Override
	List<T> findAll(Sort sort);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
	 */
	@Override
	List<T> findAllById(Iterable<ID> ids);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
	 */
	@Override
	<S extends T> List<S> saveAll(Iterable<S> entities);

	/**
	 * Flushes all pending changes to the database.
	 */
	void flush();

	/**
	 * Saves an entity and flushes changes instantly.
	 *
	 * @param entity entity to be saved. Must not be {@literal null}.
	 * @return the saved entity
	 */
	<S extends T> S saveAndFlush(S entity);

	/**
	 * Saves all entities and flushes changes instantly.
	 *
	 * @param entities entities to be saved. Must not be {@literal null}.
	 * @return the saved entities
	 * @since 2.5
	 */
	<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

	/**
	 * Deletes the given entities in a batch which means it will create a single query. This kind of operation leaves JPAs
	 * first level cache and the database out of sync. Consider flushing the {@link EntityManager} before calling this
	 * method.
	 *
	 * @param entities entities to be deleted. Must not be {@literal null}.
	 * @deprecated Use {@link #deleteAllInBatch(Iterable)} instead.
	 */
	@Deprecated
	default void deleteInBatch(Iterable<T> entities){deleteAllInBatch(entities);}

	/**
	 * Deletes the given entities in a batch which means it will create a single query. This kind of operation leaves JPAs
	 * first level cache and the database out of sync. Consider flushing the {@link EntityManager} before calling this
	 * method.
	 *
	 * @param entities entities to be deleted. Must not be {@literal null}.
	 * @since 2.5
	 */
	void deleteAllInBatch(Iterable<T> entities);


	/**
	 * Deletes the entities identified by the given ids using a single query. This kind of operation leaves JPAs first
	 * level cache and the database out of sync. Consider flushing the {@link EntityManager} before calling this method.
	 *
	 * @param ids the ids of the entities to be deleted. Must not be {@literal null}.
	 * @since 2.5
	 */
	void deleteAllByIdInBatch(Iterable<ID> ids);

	/**
	 * Deletes all entities in a batch call.
	 */
	void deleteAllInBatch();

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 * @deprecated use {@link JpaRepository#getById(ID)} instead.
	 */
	@Deprecated
	T getOne(ID id);

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 * @since 2.5
	 */
	T getById(ID id);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);
}

위와 같이 기본 메서드들에 대해 제공을 한다.

 

그리고 JpaRepository 인터페이스에 대해 다중 상속되어 있는 PagingAndSortingRepository 인터페이스로 들어가보면 또 해당 메서드들이 존재하고 PagingAndSortingRepository 인터페이스를 상속하는 CrudRepository 인터페이스로 들어가보면 또 메서드(기본적인 CRUD메서드들 제공)들이 존재하게 된다

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {

	<S extends T> S save(S entity);

	<S extends T> Iterable<S> saveAll(Iterable<S> entities);

	Optional<T> findById(ID id);

	boolean existsById(ID id);

	Iterable<T> findAll();

	Iterable<T> findAllById(Iterable<ID> ids);

	long count();

	void deleteById(ID id);

	void delete(T entity);

	void deleteAllById(Iterable<? extends ID> ids);

	void deleteAll(Iterable<? extends T> entities);

	void deleteAll();
}

 

 

위의 인터페이스들에서 제공되는 메서드들 중 제공안되는 메서드들에 대해서는 우리가 작성한 인터페이스에 해주면 동작이 된다. 즉, 위의 메서드들에는 findByName대한 메서드가 없기에 밑과 같이 해주면 된다는 것이다.

이런 것들을 적을 때 규칙이 있다.. 나중에 더 배워보자.. findByNameandId와 같이...

반응형
Comments