스프링 배치로 수십개의 텍스트 파일을 업로드처리 하려 합니다.

540 views
Skip to first unread message

신승식

unread,
Jan 25, 2010, 9:47:25 PM1/25/10
to Korea Spring User Group
매번 도움을 받고 있습니다.

100여개의 텍스트 파일읅 스프링 배치로 DB에 업로드 하려고 합니다.
스프링 배치 형식으로
FlatFileItemReader , LineMapper, FieldSetMapper 를 사용하여 작업을 하려고 하니
작업해야 하는 파일의 수가 너무 많네요. 그리고 각각을 하나의 배치 JOB으로 하려니
관리해야 하는 JOB의 수가 너무 많아서 비효율적인거 같습니다.

그래서 100여개의 작업해야할 리스트를 읽어 오는 부분 을 ItemReader로
각각의 파일을 업로드 처리 하는 부분을
ItemProcessor을 상속 받아서 파일을 읽고 , 벨리데이션 체크하고 , DB에 업로드 하는 자바파일로 빼고
100여개의 작업처리를 업데이트 하는 부분으로 ItemWrite로 처리 하는 방식으로
하면 어떨가 생각하고 있습니다.

이렇게 되면 스프링배치에서 제공하는 좋은 기능들을 쓸수가 없게 되는데.
스프링 배치의 기능을 쓰면서 이렇게 많은 파일을 효과적으로 업로드 할수 있는 좋은 방법이 없을까요?

Sanghyuk Jung

unread,
Jan 25, 2010, 10:19:47 PM1/25/10
to ks...@googlegroups.com
MultiResourceItemReader나 이와 비슷한 구조를 이용하면 되지 않을까요?
 
100개의 파일형식이 똑같다면 MultiResourceItemReader를 바로 쓸 수 있을 것 같구요, 파일내용의 일부에 따라서 알아서 읽을 형식을 결정해야 한다면  PatternMatchingCompositeLineMapper를 같이 응용할 수도 있을 거 같구요.
 
아니면 파일의 명명규칙에 따라서 형식이 다르다면 MultiResourceItemReader와 유사한 구조 안에서 별도의 delegator된 reader와 연결해주는 응용도 가능해 보입니다.

2010년 1월 26일 오전 11:47, 신승식 <sssi...@gmail.com>님의 말:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.


신승식

unread,
Jan 25, 2010, 11:44:13 PM1/25/10
to ks...@googlegroups.com

100개의 파일의 형식이 모두 틀린데요.

이 파일형식에 대해서는 DB에 저장되어 잇습니다.

 

그런데  MultiResourceItemReader를 사용한다고 하더라고  FiletSetMapper Vo 들은 모두 만들어 야 하는거 같은데

이런 부분들을 Map이나 이런 방식으로 처리 할수 있는 없을까요?

 

100개의 VO를 만들고 , 100개의 FieldSetMappler를 만드는것도 장난이 아닌듯 한데요..

좋은 방법이 없을까요?

Sanghyuk Jung

unread,
Jan 25, 2010, 11:57:55 PM1/25/10
to ks...@googlegroups.com
아 입력만 하는 목적이라는 Map을 사용할만도 합니다.
 
Map을 사용하는 FieldSetMapper를 아래와 같이 만들어둔게 있어요. (플랫파일에서 읽어서 입력만 하고 끝나는 거라서 type은 무조건 String으로 했었습니다;)
 
public class MapFieldSetMapper implements FieldSetMapper<Map<String,String>>{
 private String[] columnNames;
 private Map<String,String> defaultValues;
 public void setColumnNames(String[] columnNames) {
  this.columnNames = columnNames;
 }
 
 public void setDefaultValues(Map<String, String> defaultValues) {
  this.defaultValues = defaultValues;
 }
 public Map<String, String> mapFieldSet(FieldSet fieldSet) {
  Map<String,String> item = new HashMap<String,String>();
  for(int i=0,n= columnNames.length;i<n;i++){
   String name = columnNames[i];
   String value = fieldSet.readString(i);
   if(StringUtils.isEmpty(value) && defaultValues !=null ){
    String defaultValue = defaultValues.get(name);
    if(defaultValue!=null){
     value = defaultValue;
    }
   }
   item.put(name, value);
  }
  return item;
 }
}

 
public class MapFieldSetMapperTest {
 
 MapFieldSetMapper mapper = new MapFieldSetMapper();
 
 @Before
 public void setUp(){
  String[] names = new String[]{"id","desc","status"};
  mapper.setColumnNames(names);
 }
 
 @Test
 public void testNonDefaultValue(){
  String[] values = new String[]{"stock","",null};
  FieldSet fs = new DefaultFieldSet(values);
  Map<String, String> item = mapper.mapFieldSet(fs);
  System.out.println(item);
  assertEquals("stock",item.get("id"));
  assertEquals("",item.get("desc"));
  assertNull(item.get("status"));
 }
 
 @Test
 public void testDefaultValue(){
  String[] values = new String[]{"stock","",null};
  Map<String,String> defaultValues = new HashMap<String,String>();
  defaultValues.put("desc", "0");
  defaultValues.put("status", "1");
  mapper.setDefaultValues(defaultValues);
  FieldSet fs = new DefaultFieldSet(values);
  Map<String, String> item = mapper.mapFieldSet(fs);
  System.out.println(item);
  assertEquals("stock",item.get("id"));
  assertEquals("0",item.get("desc"));
  assertEquals("1",item.get("status"));
 }
}
 
여기에서는 field값이 null일 경우 default value까지 지정해주는 기능까지 만들어서 코드가 좀 길어졌는데, 단순히 map에서 매핑한 한다면 더 간단할 거에요~
 
그리고 DB에 입력할때 JdbcItemWriter에 아래와 같이 ItemSqlParameterSourceProvider를 이용해서  Map에서 파라미터를 읽게 오게 할 수 있구요
 
  JdbcBatchItemWriter<Map<String, String>> writer = new JdbcBatchItemWriter<Map<String, String>>();
  writer.setDataSource(dataSource);
  writer.setSql(...);
  ItemSqlParameterSourceProvider<Map<String, String>> parameterProvider = new ItemSqlParameterSourceProvider<Map<String, String>>() {
   public SqlParameterSource createSqlParameterSource(
     Map<String, String> item) {
    return new MapSqlParameterSource(item);
   }
  };
  writer.setItemSqlParameterSourceProvider(parameterProvider);
이런 설정을 SimpleStepFactoryBean 확장한 클래스를 이용해서 단순하게도 만들 수 있습니다. 저는 이런 단순입력의 경우에 쿼리도 자동으로 만들어주는 기능까지 만들어서 플랫파일에 있는 순서대로의  컬럼명과 컬럼명만 파라미터로 넣으면 되게 하기도 했었습니다.
 
(설명이 대충인데, 필요하신 부분을 말씀하시면 나중에 더 자세한 설명을 달아드리겠습니다;)
 
 
 
2010년 1월 26일 오후 1:44, 신승식 <sssi...@gmail.com>님의 말:
Reply all
Reply to author
Forward
0 new messages