JAVB외에도 XML과 클래스의 멤버에 데이터를 매핑하는 기술들이 있다고 한다.
그리고 XML을 더 자유롭게 읽어올 수도 있다고 한다.
알아보자.
OXM 서비스 추상화
OXM은 Object-XML Mapping으로 xml과 자바 오브젝트를 매핑해주는 기술이라고 한다.
JAXB는 자바 표준에 포함되어 있어서 사용했지만, 이 외에도 다음과 같은 XML 기술들이 있다.
Castor XML, JiBX, XmlBeans, Xstream...
이 모든 기술들의 목적은 XML에서 데이터를 가져오는 것이다.
그 중 어떤 기술을 사용할지 모르기에 추상화로 만들어두는 것도 좋은 방법이라고 생각된다.
자바 -> XML을 Marshaller라고 하고
XML -> 자바를 Unmarshaller라고 한다.
'우리는 XML에서 값을 불러와야 하기에 Unmarshaller를 사용해야 한다'가 목표였지만, xml에서 무언가 조작하기가 힘들어서 yml에서 가져와서 만드는 것으로 바꿨다...
기존에 작성했던 SqlMap으로 쿼리들을 불러와보자.
@Getter
@Setter
@ToString
@Configuration
@ConfigurationProperties(prefix = "sqlmap")
public class SqlMap {
private List<SqlType> queries;
}
@Getter
@Setter
@ToString
public class SqlType {
private String value;
private String key;
}
이렇게 해두고 우선 테스트를 돌려보자.
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = {"/test-applicationContext.xml"})
public class OxmTest {
@Test
public void unmarshallSqlMap() throws Exception {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try (InputStream inputStream = getClass().getResourceAsStream("/sqlmap.yml")) {
assert inputStream != null;
SqlMap sqlMap = mapper.readValue(inputStream, SqlMap.class);
System.out.println(sqlMap);
}
}
}
우선 이렇게 작성해두면
이렇게 제대로 출력되는 것을 볼 수 있다.
OXM 서비스 추상화 적용
yml을 읽어오는 기능을 바탕으로 SqlService를 만들어보자.
기존에 사용하던 SqlRegistry를 그대로 사용하면 될테니, Reader만 yml을 읽어오도록 추가해서 등록해주면 된다.
@RequiredArgsConstructor
public class YmlSqlService implements SqlService {
private final SqlReader sqlReader;
private final SqlRegistry sqlRegistry;
@PostConstruct
public void loadSql(){
this.sqlReader.read(this.sqlRegistry);
}
public String getSql(String key){
return this.sqlRegistry.findSql(key);
}
}
이렇게 껍데기를 만들어두고, SqlReader를 구현해보자.
@RequiredArgsConstructor
public class XmlSqlReader implements SqlReader {
private final String path;
@Override
public void read(SqlRegistry sqlRegistry) {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try (InputStream inputStream = getClass().getResourceAsStream(path)) {
assert inputStream != null;
SqlMap sqlMap = mapper.readValue(inputStream, SqlMap.class);
for(SqlType sqlType: sqlMap.getQueries())
{
sqlRegistry.registerSql(sqlType.getKey(), sqlType.getValue());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
이러면 저번에 만들었던 xml과는 동일하게 동작할 수 있을 것이다.
이렇게 서비스 자체를 추상화로 만들어두니 테스트도 성공했다.
'Spring > 토비의 스프링' 카테고리의 다른 글
[토비의 스프링] 7.5 DI를 이용해 다양한 구현 방법 적용하기 (2) | 2025.07.22 |
---|---|
[토비의 스프링] 7.4 인터페이스 상속을 통한 안전한 기능확장 (1) | 2025.07.22 |
[토비의 스프링] 7.2 인터페이스의 분리와 자기참조 빈 (2) | 2025.07.11 |
[토비의 스프링] 7.1 SQL과 DAO의 분리 (1) | 2025.07.07 |
[토비의 스프링] 6.8 트랜잭션 지원 테스트 (5) | 2025.07.07 |