728x90

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과는 동일하게 동작할 수 있을 것이다.

 

이렇게 서비스 자체를 추상화로 만들어두니 테스트도 성공했다.

+ Recent posts