songining

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๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค ํ˜•ํƒœ๋กœ ์ถ”์ƒํ™”ํ•˜์—ฌ ์ œ๊ณตํ•œ๋‹ค. 

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

 

 

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

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

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

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

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(๊ตฌํ˜„์ฒด) ๋ฐ˜ํ™˜

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

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

 

 

R2dbcRepositoryFactory

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

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

 

 

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

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

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

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

    ex) JPARepositoryFactoryBean, R2dbcRepositoryFactoryBean ..

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

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

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