<토비의스프링> 7.5~7.6.1 내장형 데이터베이스
by BFine7.5 DI를 이용해 다양한 구현방법 적용하기
7.5.1 ConcurrentHashMap을 이용한 수정 가능 SQL 레지스트리
- 운영시스템에서 실시간 변경 작업을 할때 항상 생각해야 하는 것은 동시성이다.
=> 안전한 업데이트가 가능하도록 SqlRegistry로 변경하자!
- 기존 HashMap보다는 ConcurrentHashMap을 사용하자
=> 데이터 조작시 전체데이터에 락을 걸지 않으며 조회에는 락이 없다!, 성능 Good
7.5.2 내장형 데이터 베이스
- ConcurrentHashMap 성능이 좋기 하지만 데이터양이 많아지거나 복잡한 데이터를 조회 할 경우에 한계가 있다.
- 어플리케이션에 내장돼서 어플리케이션과 함께 시작 종료되는 DB(H2,HSQL)
- 메모리에 저장되기 때문에 IO로 인한 부하가 적어서 성능이 뛰어남
- 어플리케이션 내에서 DB를 기동시키고 데이터를 실행하는 등 초기화 작업이 별도로 필요
=> 초기화 작업을 지원하는 내장형 DB 빌더를 제공 (URL, 드라이버 등 초기화)
- DB 빌더는 엔진 생성하고 초기화 하며 Connection을 생성해주는 DataSource 객체를 돌려준다.
new EmbeddedDatabaseBuilder() // 빌더오브젝트 생성
.setType(내장형DB종류)
.addScript(초기화에 사용할 DB 스크립트의 리소스)// 하나이상 저장가능
.build();
- EmbeddedDatabaseBuilder 는 적절한 메소드를 호출해주는 초기화 코드가 필요
=> 초기화 코드가 필요하면 팩토리 빈으로 만드는 것이 좋다.
- Spring은 Xml 전용 코드로 팩토리 빈을 쉽게 만들 수 있다.
- Test Class도 상속이 가능 하다.
public abstract class AbstractUpdatableSqlRegistryTest {
UpdatableSqlRegistry sqlRegistry;
@Before
public void setUp() {
sqlRegistry = createUpdatableSqlRegistry();
sqlRegistry.registerSql("KEY1", "SQL1");
sqlRegistry.registerSql("KEY2", "SQL2");
sqlRegistry.registerSql("KEY3", "SQL3");
}
abstract protected UpdatableSqlRegistry createUpdatableSqlRegistry();
@Test(expected=SqlNotFoundException.class)
public void unknownKey() {
sqlRegistry.findSql("SQL9999!@#$");
}
protected void checkFind(String expected1, String expected2, String expected3) {
assertThat(sqlRegistry.findSql("KEY1"), is(expected1));
assertThat(sqlRegistry.findSql("KEY2"), is(expected2));
assertThat(sqlRegistry.findSql("KEY3"), is(expected3));
}
@Test(expected=SqlUpdateFailureException.class)
public void updateWithNotExistingKey() {
sqlRegistry.updateSql("SQL9999!@#$", "Modified2");
}
}
public class EmbeddedDbSqlRegistryTest extends AbstractUpdatableSqlRegistryTest {
EmbeddedDatabase db;
@Override
protected UpdatableSqlRegistry createUpdatableSqlRegistry() {
db = new EmbeddedDatabaseBuilder()
.setType(HSQL)
.addScript("classpath:springbook/user/sqlservice/updatable/sqlRegistrySchema.sql")
.build();
EmbeddedDbSqlRegistry embeddedDbSqlRegistry = new EmbeddedDbSqlRegistry();
embeddedDbSqlRegistry.setDataSource(db);
return embeddedDbSqlRegistry;
}
@After
public void tearDown() {
db.shutdown();
}
}
7.5.3 트랜잭션 적용
- 하나이상의 SQL을 맵으로 한번에 수정해야하는 경우 심각한 문제 생길 수도 있음
- 템플릿/콜백 패턴을 적용하여 Transcation을 적용하자
public class EmbeddedDbSqlRegistry implements UpdatableSqlRegistry {
SimpleJdbcTemplate jdbc;
TransactionTemplate transactionTemplate;
public void setDataSource(DataSource dataSource) {
jdbc = new SimpleJdbcTemplate(dataSource);
transactionTemplate = new TransactionTemplate(
new DataSourceTransactionManager(dataSource));
transactionTemplate.
setIsolationLevel(TransactionTemplate.ISOLATION_READ_COMMITTED);
}
}
public void updateSql(final Map<String, String> sqlmap) throws SqlUpdateFailureException {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
for(Map.Entry<String, String> entry : sqlmap.entrySet()) {
updateSql(entry.getKey(), entry.getValue());
}
}
});
}
7.6 스프링 3.1의 DI
- 어노테이션이 활성화 되면서 메타정보를 이용한 프로그래밍 방식으로 많이 사용됨
- 자바는 소스코드가 컴파일된 이후에 클래스 파일에 저장됐다가 JVM에 의해 메모리로 로딩되어 실행된다.
=> 이외에도 다른 자바코드에 의해 데이터처럼 취급되기도함
- 어노테이션은 자바코드가 실행되는데에는 직접 참여하지 못함
=> 복잡한 리플렉션 API를 이용해 메타정보를 조회하고 설정된값을 가져와 참고하는 방법이 전부
- 이런데도 활용이 늘어난 이유는?
=> 핵심로직을 담은 자바코드, 이를 활용한 IoC 프레임워크, 프레임워크가 참조하는 메타정보 세가지로
구성하는 방식에 잘어울리기 때문
- UserDao가 한가지가 아니라면 DaoFactory 같은 단순 자바코드로 만든 관계설정은 불편함
=> Xml 설정으로 진화(작성하기 편함, 빌드과정 필요없음)
=> 하지만 어노테이션은 자바코드로 작성
- XML 보다 어노테이션이 유리한점
1. 직관적으로 타입레벨에 적용하는지 알 수 있음
2. 해당 타깃의 다양한 부가 메타정보를 얻을 수 있음 (패키지,접근제한자, 구현 인터페이스, 필드&메서드구성)
7.6.1 자바코드를 이용한 빈설정
- 스프링 3.1 부터는 XML을 어노테이션으로 대체하여 사용이 가능하다.
- @ContextConfiguration(location=) 은 DI 정보를 어디서 가져오는지 지정
- XML을 대신하여 자바 클래스에 @Configration을 사용
- @ImportResource로는 DI 설정정보를 xml로 가져와서 주입( 이것도 제거됨 )
- 클래스로 변경하면 기존의 <context: annotation-config/> 코드는 제거해도 된다.
=> 컨테이너가 직접 @PostConstruct 를 처리하는 빈후처리기를 등록해줌
- @Resource는 필드 이름 기준, @Autowired 필드 타입 기준 으로 DI
- <tx:annotation-driven/>은 @EnableTransactionManagement로 사용 가능
'개발서적 > 토비의스프링' 카테고리의 다른 글
<토비의스프링> 8.1~8.4 스프링이란 (0) | 2021.03.13 |
---|---|
<토비의스프링> 7.6.2~7.6.6 어노테이션 (0) | 2021.03.07 |
<토비의스프링> 7.3~7.4 서비스 추상화 (0) | 2021.02.20 |
<토비의스프링> 7.1~7.2 SQL DAO 분리하기 (0) | 2021.02.20 |
<토비의스프링> 6.7~6.8 트랜잭션 어노테이션 (0) | 2021.02.20 |
블로그의 정보
57개월 BackEnd
BFine