본문 바로가기
JAVA

[Java] 여러개의 Select 구현 방법 (PreparedStatement + Union All)

by GoodDayDeveloper 2022. 9. 28.
반응형


PreparedStatement를 이용하여 insert뿐만 아니라 select도 이용할 수가 있습니다.
더군다나 자바를 이용하기 때문에 조건식에 맞춰 복수의 select를 한번에 불러올 수가 있습니다.

복수의 select를 각각 디비에서 불러와서 데이터를 담는 것 보다,
한번에 불러올 수 있는 PreparedStatement 사용이 매력적이라 말할 수 있습니다.

일반적으로 간단한 select방식과
이것을 응용하여 여러개의 select를 적용하는 방법에 대해 정리해보겠습니다.



일반적인 select 방식

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
 
private Map<String, Object> getData(List<VO> chartInfoArr) throws SQLException {
 
    PreparedStatement pstmt = null;
    Connection con = null;
    ResultSet resultSet = null;
 
    Map<String, Object> dataSet = new HashMap<String, Object>();
    List<String> timeSet = new ArrayList<String>();
    List<String> valueSet = new ArrayList<String>();
    
    try {
       
        con =  DriverManager.getConnection(url,db_id,db_pwd);
//ex) con =  DriverManager.getConnection(jdbc:postgresql://203.333.222.11/dbname,test,test); 
        Class.forName("org.postgresql.Driver");
        con.setAutoCommit(false);
        Map<Integer, Object> map = new HashMap<Integer, Object>();
                
        String sql = "select"
                    + " TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY-MM'),"
                    + "SUM(CAST(mc_value AS DOUBLE PRECISION)) as mc_value "
                    + " from an_meta_chart"
                    + " where mt_idx = ? and code_idx = ?"
           
 
        pstmt = con.prepareStatement(sql);
        
        //pstmt.setString(key, value);
        pstmt.setInt(17);
        pstmt.setInt(225);       
        
        resultSet = pstmt.executeQuery();
            
        while(resultSet.next()) {
            timeSet.add(resultSet.getString(1));
            valueSet.add(resultSet.getString(2));
        }
        
        dataSet.put("timeSet", timeSet);
        dataSet.put("valueSet", valueSet);
        
    }catch(Exception e){
        con.rollback();
    }finally{
        if(pstmt != null) pstmt.close();
        if(con != null) con.close();
    }
        
    return dataSet;
}
cs


우선 PreparedStatement와 Connection,ResultSet를 선언해줍니다.
데이터를 담을 리스트배열의 timeSet과 valueSet를 만들어주고,
최종적으로 데이터를 담을 맵 형태의 dataSet를 생성해줍니다.


DriverManager를 이용하여 디비 정보를 담은 뒤,
sql 변수에 sql를 작성하여 prepareStatement에 넣어줍니다.
sql를 작성할 때에는 들어갈 매개변수 ?를 작성합니다.
(여기서 ?가 String이더라도 "?" 이런 형태의 따움표를 붙여서는 안됩니다.)


그리고 prepareStatement의 변수인 pstmt에
set으로 sql의 ?표에 넣어줄 데이터를 바인딩해줍니다.
(int형은 setInt로, String형은 setString으로 선언하여 작성하면 됩니다.)


pstmt.executeQuery();로 resultSet에 담은 뒤, 반복문으로 데이터를 꺼내줍니다.
순서대로 괄호안에 1, 2를 작성해주면 되고
데이터를 set할때와 똑같이 get도 int는 getInt, String은 getString으로 사용하면 됩니다.



데이터를 담을때 리스트배열에 add하여 담아준 다음,
최종적으로 맵에 put하여 담아주면 편리하게 데이터를 사용할 수 있습니다.





반응형




복수 select 적용 방식

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
 
private Map<String, Object> getData(List<VO> chartInfoArr) throws SQLException {
 
    PreparedStatement pstmt = null;
    Connection con = null;
    ResultSet resultSet = null;    
 
    Map<String, Object> dataSet = new HashMap<String, Object>();
    List<String> timeSet = new ArrayList<String>();
    List<String> valueSet = new ArrayList<String>();
    
    try {
       
        con =  DriverManager.getConnection(url,db_id,db_pwd);
        Class.forName("org.postgresql.Driver");
        con.setAutoCommit(false);
        Map<Integer, Object> map = new HashMap<Integer, Object>();
        int chkCount = 1;
        int ct = 1;
 
        String base = "select "
        + "TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY-MM-DD HH24:MI:SS') AS mc_timezone ,  "
        + "CAST(mc_value AS DOUBLE PRECISION) as mc_value"
        + " from an_meta_chart"
        + " where mt_idx = ? and code_idx = ?";
 
        String sql = "";
        
        for(CommonCodeVO v : chartInfoArr){
        
        if(StringUtils.isNullOrEmpty(v.getMt_keywd5())) {
            if("1".equals(v.getMt_keywd3())) {
                
                sql += "select"
                        + " TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY-MM'),"
                        + "SUM(CAST(mc_value AS DOUBLE PRECISION)) as mc_value "
                        + " from an_meta_chart"
                        + " where mt_idx = ? and code_idx = ?"
                        + " AND " 
                        + "TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY') = ?"
                        + " GROUP BY TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY-MM')";
                
                map.put(ct, v.getMt_idx());
                map.put(++ct, v.getCode_idx());
                map.put(++ct, v.getMt_keywd4());
                
            }else if("2".equals(v.getMt_keywd3())) {
                
                sql += base
                    + " AND " + 
                        "TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY') = ?"
                
                map.put(ct, v.getMt_idx());
                map.put(++ct, v.getCode_idx());
                map.put(++ct, v.getMt_keywd4());
                    
            }else {
                sql += base;
                map.put(ct, v.getMt_idx());
                map.put(++ct, v.getCode_idx());
            }
            
        }else{
            
            if("1".equals(v.getMt_keywd3())) {
                
                sql += "select"
                        + " TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY-MM'),"
                        + "SUM(CAST(mc_value AS DOUBLE PRECISION)) as mc_value "
                        + " from an_meta_chart"
                        + " where mt_idx = ? and code_idx = ?"
                        + " AND " 
                        +"TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY')    between  ? and ? "
                        + " GROUP BY TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY-MM')";
                
                map.put(ct, v.getMt_idx());
                map.put(++ct, v.getCode_idx());
                map.put(++ct, v.getMt_keywd4());
                map.put(++ct, v.getMt_keywd5());
 
                
            }else if("2".equals(v.getMt_keywd3())) {
                
                sql += base
                        +" AND " 
                        +"TO_CHAR(TO_TIMESTAMP(CONCAT(mc_date, ' ' ,mc_time),'YYYY-MM-DD HH24:MI:SS') - cast(mc_timezone || 'hour' as INTERVAL)  , 'YYYY')    between  ? and ? "
                    
                    map.put(ct, v.getMt_idx());
                    map.put(++ct, v.getCode_idx());
                    map.put(++ct, v.getMt_keywd4());
                    map.put(++ct, v.getMt_keywd5());
                
            }
            
        }
            
            if(chartInfoArr.size() > chkCount) { 
                sql += " UNION ALL ";
            }else if(chartInfoArr.size()-1 == chkCount) {
                sql += " ORDER BY mc_timezone";
            }
            
            ct++;
            chkCount++;
        }
        
        pstmt = con.prepareStatement(sql);
        
        
        for(Integer key : map.keySet()){
            
            switch ((map.get(key).getClass().getName())) {
            case "java.lang.String":
                    pstmt.setString(key, (String) map.get(key));
                break;
                
            case "java.lang.Integer":
                    pstmt.setInt(key,  (int) map.get(key));
                break;    
            } 
        }
        
        resultSet = pstmt.executeQuery();
            
        while(resultSet.next()) {
            timeSet.add(resultSet.getString(1));
            valueSet.add(resultSet.getString(2));
        }
        
        dataSet.put("timeSet", timeSet);
        dataSet.put("valueSet", valueSet);
        
        
    }catch(Exception e){
        con.rollback();
    }finally{
        if(pstmt != null) pstmt.close();
        if(con != null) con.close();
    }
    
    return dataSet;
}
cs


이곳에서는 리스트배열의 각각의 값들에 대한 조건을 모아서
union으로 합쳐 sql변수에 담은 다음,
PreparedStatement를 이용하여 한번에 데이터를 뽑는 코드입니다.

이곳의 포인트는 반복문으로 각 조건에 마다 sql문을 추가하여
union all을 해주며select를 합쳐주었고,
map을 통해서 set할 바인딩 데이터를 담아주었습니다.

나머지는 동일하구요.
간단히만 참고하시면 될 것 같습니다~~





[Java] 대용량 Insert 상세 설명 (Batch, Dynamic sql)

[Java]  대용량 Insert 상세 설명 (Batch, Dynamic sql)

대용량 Insert 기능을 찾아보다가 부족한 내용이 많아 직접 정리해보려합니다. 자바에서 제공하는 PreparedStatement의 addBatch를 이용한 대용량 Insert 방법과 함께 아래와 같이 다양한 Insert에 대해 알아

chobopark.tistory.com




반응형

댓글