1. DB IOException 메시지
대량의 데이터를 bulk insert 하면 PostgreSQL에서 Tried to send an out-of-range integer as a 2-byte value IOException이 발생한다.
PostgreSQL의 JDBC에서 바인딩할 수 있는 매개변수 갯수에 제한이 있기 때문이다.
2. 해결방법
Controller에서 select 데이터를 잘라서 insert 한다.
아래 소스는 2개의 DB에 연결하여 첫 번재 DB는 select, 두 번째 DB는 insert하는 소스이다. 따라서 두 개의 mapper가 존재한다.
1) Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  | @RestController
public class RetailController {
    @Resource
    private RetailService retailService;
    @GetMapping("/retailList")
    public ResponseEntity retailList() {
        // data select 40000건
        List<RetailDTO> selectRetailList = retailService.selectRetailList();
        ArrayList<RetailDTO> retailDataList = new ArrayList<RetailDTO>();
        int count;
        int insCount = 0;
        int selSize = selectRetailList.size();
        for (count = 0; count < selSize; count++) {
            RetailDTO retailDTO = new RetailDTO();
            retailDTO = selectRetailList.get(count);
            retailDataList.add(retailDTO);
            // 1000건씩 자른다.
            if (insCount == 1000 || selSize == count) {
                // 1000건씩 insert
                retailService.insertRetailList(retailDataList);
                retailDataList = new ArrayList<RetailDTO>();
                insCount = 0;
            } else {
                insCount++;
            }
        }
        return new ResponseEntity(HttpStatus.OK);
    }
}
 | 
2) Service.java
1
2
3
4
  | public interface RetailService {
    List<RetailDTO> selectRetailList();
    int insertRetailList(List<RetailDTO> list);
}
 | 
3) ServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  | @Service
public class RetailServiceImpl implements RetailService {
    @Autowired
    PrimaryMapper primaryMapper;
    @Autowired
    SecondaryMapper secondaryMapper;
    @Override
    public List<RetailDTO> selectRetailList() {
        return primaryMapper.selectRetailList();
    }
    @Override
    public int insertRetailList(List<RetailDTO> list) {
        return secondaryMapper.insertRetailList(list);
    }
}
 | 
4) SelectMapper.java
1
2
3
4
  | @Mapper
public interface SelectMapper {
    List<RetailDTO> selectRetailList();
}
 | 
5) InsertMapper.java
1
2
3
4
  | @Mapper
public interface InsertMapper {
    int insertRetailList(List<RetailDTO> list);
}
 | 
6) DTO.java
1
2
3
4
5
6
7
8
9
10
  | @Getter
@Setter
public class RetailDTO {
    private String bizplCd;
    private String bizplNm;
    private String bizplAddr;
    private String telNo;
    private String openDt;
    private String closeDt;
}
 | 
7) SelectQuery.xml
1
2
3
4
5
6
7
8
9
  | <select id="selectRetailList" resultType="com.example.dto.RetailDTO">
    SELECT DISTINCT BIZPL_CD
                  , BIZPL_NM
                  , BIZPL_ADDR
                  , TEL_NO
                  , OPEN_DT
                  , CLOSE_DT
    FROM TS_BIZPL
</select>
 | 
8) InsertQuery.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  | <insert id="insertRetailList" parameterType="java.util.List" useGeneratedKeys="true">
    INSERT INTO BIZPL ( BIZPL_CD
                     , BIZPL_NM
                     , BIZPL_ADDR
                     , TEL_NO
                     , OPEN_DT
                     , CLOSE_DT)
    VALUES
    <foreach collection="list" item="item" separator=",">
           ( #{item.bizplCd}
           , #{item.bizplNm}
           , #{item.bizplAddr}
           , #{item.telNo}
           , #{item.openDt}
           , #{item.closeDt})
    </foreach>
</insert>
 | 
[출처 및 참고]