songining

1. Spring Data ๋ž€?

Spring ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ•˜์œ„ ํ”„๋กœ์ ํŠธ ์ค‘ ํ•˜๋‚˜๋กœ ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ธฐ์ˆ ์„ ์ง€์›ํ•œ๋‹ค. 

Repository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด ๋งคํ•‘์„ ์ถ”์ƒํ™” ํ˜•ํƒœ๋กœ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ข€ ๋” ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผ ๋ฐ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

Main Module

  • Spring Data Commons : ๋ชจ๋“  Spring Module์„ ๋’ท๋ฐ›์นจํ•˜๋Š” ํ•ต์‹ฌ Spring ๊ฐœ๋…
    • CrudRepository, PagingAndSortingRepository
  • Spring Data JDBC : spring-jdbc์— ๋Œ€ํ•œ Spring Data ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“ˆ
    • CrudRepository๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” SimpleJdbcRepository ํด๋ž˜์Šค
  • Spring Data JPA : JPA๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์ง€์›
    • JpaRepository ์ธํ„ฐํŽ˜์ด์Šค, SimpleJpaRepository ํด๋ž˜์Šค
  • Spring Data R2dbc : R2dbc ๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์ง€์›
    • R2dbcRepository ์ธํ„ฐํŽ˜์ด์Šค, SimpleR2dbcRepository ํด๋ž˜์Šค
  • Spring Data REST
  • Spring Data Redis
  • Spring Data MongoDB
  • ... 

๋“ฑ ๋‹ค์–‘ํ•œ ๋ชจ๋“ˆ์„ ์ง€์›ํ•œ๋‹ค.

๊ทธ ์™ธ์˜ ๋ชจ๋“ˆ์€ ์•„๋ž˜ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

https://spring.io/projects/spring-data#overview

 

Spring Data

Spring Dataโ€™s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It makes it easy to use data access technologies, relational and non-rela

spring.io

 

 

Spring ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ํ˜•ํƒœ๋กœ Repository๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค ํ˜•ํƒœ๋กœ ์ถ”์ƒํ™”ํ•˜์—ฌ ์ œ๊ณตํ•œ๋‹ค. 

์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋Œ€ํ‘œ์ ์ธ ํด๋ž˜์Šค๋“ค์„ ๋ช‡ ๊ฐœ ์•Œ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

 

2. RepositoryFactorySupport ์ถ”์ƒ ํด๋ž˜์Šค

- ์ฃผ์–ด์ง„ Repository ์ธํ„ฐํŽ˜์ด์Šค์˜ ์‹ค์ œ ํ”„๋ก์‹œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ

- ์ด ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜์—ฌ ๋‹ค์–‘ํ•œ spring-data-xxx ์—์„œ Repository๋ฅผ ์ƒ์„ฑ

- getRepository ํ•จ์ˆ˜์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ตฌํ˜„ํ•œ repository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ๋‚ด๋ถ€์ ์œผ๋กœ proxy ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜

<kotlin />
public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, BeanFactoryAware { public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) { ... (์ƒ๋žต) Object target = getTargetRepository(information); // Create proxy (ํ”„๋ก์‹œ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ) ProxyFactory result = new ProxyFactory(); result.setTarget(target); result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class); if (MethodInvocationValidator.supports(repositoryInterface)) { result.addAdvice(new MethodInvocationValidator()); } result.addAdvisor(ExposeInvocationInterceptor.ADVISOR); postProcessors.forEach(processor -> processor.postProcess(result, information)); if (DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(repositoryInterface)) { result.addAdvice(new DefaultMethodInvokingMethodInterceptor()); } ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory); Optional<QueryLookupStrategy> queryLookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey, evaluationContextProvider); result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory, queryLookupStrategy, namedQueries, queryPostProcessors)); composition = composition.append(RepositoryFragment.implemented(target)); result.addAdvice(new ImplementationMethodExecutionInterceptor(composition)); T repository = (T) result.getProxy(classLoader); ... (์ƒ๋žต) return repository; }

 

RepositoryFactorySupport ์ƒ์† ํด๋ž˜์Šค ์˜ˆ์‹œ

 

JpaRepositoryFactory

- ๋‚ด๋ถ€์ ์œผ๋กœ SimpleJpaRepository(๊ตฌํ˜„์ฒด) ๋ฐ˜ํ™˜

<java />
@Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return SimpleJpaRepository.class; }

- JpaRepositoryFactoryBean ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด RepositoryFactory ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐ entityManager ์ฃผ์ž… (RepositoryFactoryBeanSupport ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด Factory ์ปค์Šคํ…€๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.)

 

 

R2dbcRepositoryFactory

- ๋‚ด๋ถ€์ ์œผ๋กœ SimpleR2dbcRepository(๊ตฌํ˜„์ฒด) ๋ฐ˜ํ™˜

<java />
@Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return SimpleR2dbcRepository.class; }

 

 

3. Repository ์ปค์Šคํ…€ํ•˜๊ธฐ

1. RepositoryFactorySupport ํ•˜์œ„ ์ปค์Šคํ…€ Factory ํด๋ž˜์Šค ๊ตฌํ˜„

2. RepositoryFactoryBeanSupport ์˜ ํ•˜์œ„ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์ด ์กด์žฌ. 

    - ํ•ด๋‹น Bean์„ ์ƒ์†๋ฐ›์•„ getFactoryInstance๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ RepositoryFactory ๋ฅผ ๋ณ€๊ฒฝํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

    ex) JPARepositoryFactoryBean, R2dbcRepositoryFactoryBean ..

3. RepositoryFactoryBeanSupport ํด๋ž˜์Šค ๋˜๋Š” ํ•˜์œ„ ํด๋ž˜์Šค ์ƒ์†๋ฐ›์•„ ๊ตฌ์ฒด์ ์ธ ํ”„๋ก์‹œ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

4. getFactoryInstance ํ•จ์ˆ˜์— ์ปค์Šคํ…€ํ•œ Factory ํด๋ž˜์Šค๋ฅผ ๋ฐ˜ํ™˜

<kotlin />
class CustomRepositoryFactoryBean<T : Repository<S, ID>, S, ID : Serializable>( repositoryInterface: Class<T> ) : R2dbcRepositoryFactoryBean<T, S, ID>(repositoryInterface) { override fun setMappingContext(mappingContext: MappingContext<*, *>) { super.setMappingContext(mappingContext) } override fun getFactoryInstance(operations: R2dbcEntityOperations): RepositoryFactorySupport { return CustomRepositoryFactory(operations) } } /* * Ex) R2dbcRepository๋ฅผ ์ปค์Šคํ…€ํ–ˆ๋‹ค๋ฉด */ class CustomRepositoryFactory( operations: R2dbcEntityOperations ) : R2dbcRepositoryFactory(operations) { override fun getRepositoryBaseClass(metadata: RepositoryMetadata): Class<*> { // ์ปค์Šคํ…€ํ•œ Repository ๊ตฌํ˜„์ฒด (๋Ÿฐํƒ€์ž„์— ๋™์ ์œผ๋กœ ์‹คํ–‰๋  Repository ๊ตฌํ˜„์ฒด) return R2dbcCoroutineRepository::class.java } }

 

 

์ฐธ๊ณ 

https://imbf.github.io/spring/2020/04/30/Spring-Data.html

https://brunch.co.kr/@anonymdevoo/40