[Spring JPA #14] 스프링 데이터 커스텀 리포지터리 만들기
- Spring/Spring JPA
- 2019. 1. 31. 05:06
반응형
| 스프링 데이터 커스텀 리포지터리
스프링 데이터에서 제공하는 쿼리 메서드로 어떤 특정 비즈니스 로직을 구현하는 데 어려움이 있을 경우 직접 코딩으로 구현할 수 있습니다.
| 스프링 데이터 커스텀 리포지터리 예제
프로젝트 구조
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── DemoApplication.java
│ │ │ └── post
│ │ │ ├── PostCustomRepositoryImpl.java
│ │ │ ├── PostCustomRepository.java
│ │ │ ├── Post.java
│ │ │ └── PostRepository.java
│ │ └── resources
│ │ └── application.properties
의존성 관리
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.properties
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type.descriptor.sql=trace
소스 코드
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@Entity
@Data
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@Lob
private String content;
@Temporal(TemporalType.TIMESTAMP)
private Date created;
}
public interface PostCustomRepository<T> {
List<Post> findMyPost();
void delete(T entity);
}
- 사용자가 정의한 커스텀 Repository 코드입니다. 스프링에서 제공하는 어떤 기능에 대한 의존성없이 존재하는 POJO입니다.
- 이 인터페이스를 구현한 접미사가 Impl 인 클래스를 작성하면 이 Repository를 쓸 때 해당 클래스의 구현체가 자동적으로 할당되어 사용되어 집니다.
- 스프링 데이터에서 기본 기능으로써 제공하는 delete 메서드도 Custom Repository에서 구현하면 덮어쓰기가 가능해집니다.
- @Data 어노테이션은 참고로 lombok에서 가져온 기능입니다. Setter, Getter, ToString, Constructor에 대한 정보를 자동적으로 생성해줍니다.
@Repository
@Transactional
public class PostCustomRepositoryImpl implements PostCustomRepository {
@Autowired
EntityManager entityManager;
@Override
public List<Post> findMyPost() {
System.out.println("custom findMyPost");
return entityManager.createQuery("SELECT p FROM Post as p", Post.class)
.getResultList();
}
@Override
public void delete(Object entity) {
System.out.println("custom delete");
entityManager.remove(entity);
}
}
- PostCustomRepository를 구현한 클래스입니다. 위 코드에서 EntityManager는 엔티티를 저장하고 관리하는 역할을 합니다.
- PostCustomRepository를 구현한 메서드들은 PostRepository에 의존성이 주입될 때 사용할 수 있게 됩니다.
public interface PostRepository extends JpaRepository<Post, Long>, PostCustomRepository<Post> {
}
- PostCustomRepository 인터페이스를 확장한 PostRepository를 통하여 PostCustomRepository에서 정의한 메서드들을 사용할 수 있습니다.
테스트 코드
@RunWith(SpringRunner.class)
@DataJpaTest
public class DemoApplicationTests {
@Autowired
PostRepository postRepository;
@Test
public void crud() {
postRepository.findMyPost();
Post post = new Post();
post.setTitle("hibernate");
postRepository.save(post);
postRepository.findMyPost();
postRepository.delete(post);
postRepository.flush();
}
}
만일 접미사를 Impl이 아닌 것으로 Custom Repository를 구현하고 싶다면 다음과 같이 접미사에 대한 설정을 다르게 해야합니다.
@SpringBootApplication
@EnableJpaRepositories(repositoryImplementationPostfix = "Default")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
| 기본 리포지터리 커스터마이징
프로젝트 구조
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── tutorial
│ │ │ └── springdatarepository
│ │ │ ├── MyRepositoryImpl.java
│ │ │ ├── MyRepository.java
│ │ │ ├── Post.java
│ │ │ ├── PostRepository.java
│ │ │ └── SpringDataRepositoryApplication.java
│ │ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── tutorial
│ └── springdatarepository
│ └── DemoApplicationTests.java
소스 코드
@NoRepositoryBean
public interface MyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
boolean contains(T entity);
}
- JpaRepository 인터페이스를 확장한 Repository 인터페이스를 작성하였습니다. @NoRepositoryBean은 이 인터페이스가 Repository로서 직접적으로 기능하지 않을 것이라는 것을 명시합니다.
public class MyRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID>{
private EntityManager entityManager;
public MyRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
@Override
public boolean contains(T entity) {
return entityManager.contains(entity);
}
}
- 위 Repository의 구현체는 JpaRepository 구현체중 Default 구현체인 SimpleJpaRepository를 상속받아 작성할 수 있습니다. 이것을 통해 개발자에게 노출되는 Repository 인터페이스에서 JpaRepository를 따로 인터페이스를 확장하지 않고 아래와 같이 MyRepository 인터페이스만 확장하여 쓸 수 있습니다.
public interface PostRepository extends MyRepository<Post, Long> {
}
테스트 코드
@RunWith(SpringRunner.class)
@DataJpaTest
public class DemoApplicationTests {
@Autowired
PostRepository postRepository;
@Test
public void crud() {
Post post = new Post();
post.setTitle("hibernate");
assertThat(postRepository.contains(post)).isFalse();
postRepository.save(post);
assertThat(postRepository.contains(post)).isTrue();
}
}
https://www.inflearn.com/course/스프링-데이터-jpa
반응형
'Spring > Spring JPA' 카테고리의 다른 글
[Spring JPA #16] 스프링 데이터 QueryDsl (0) | 2019.01.31 |
---|---|
[Spring JPA #15] 스프링 데이터 도메인 이벤트 (0) | 2019.01.31 |
[Spring JPA #13] 스프링 데이터 쿼리 만들기 (0) | 2019.01.29 |
[Spring JPA #12] 스프링 데이터 Null 체크 (0) | 2019.01.29 |
[Spring JPA #11] 스프링 데이터 리포지터리 인터페이스 정의하기(Spring Repository Interface) (0) | 2019.01.29 |
이 글을 공유하기