Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc2 / impl / ResulSetControlerBase.java @ 44376

History | View | Annotate | Download (7.67 KB)

1
package org.gvsig.fmap.dal.store.jdbc2.impl;
2

    
3
import java.sql.Connection;
4
import java.sql.PreparedStatement;
5
import java.sql.ResultSet;
6
import java.sql.SQLException;
7
import java.sql.Statement;
8
import java.util.ArrayList;
9
import java.util.HashMap;
10
import java.util.List;
11
import java.util.Map;
12
import org.gvsig.fmap.dal.exception.DataException;
13
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
14
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
15
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
16
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
17
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler;
18
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
19
import org.gvsig.tools.dispose.Disposable;
20
import org.gvsig.tools.dispose.DisposeUtils;
21
import org.slf4j.Logger;
22
import org.slf4j.LoggerFactory;
23

    
24
public class ResulSetControlerBase implements ResulSetControler {
25

    
26
    final static private Logger LOGGER = LoggerFactory.getLogger(ResulSetControlerBase.class);
27

    
28
    public class ResultSetEntryBase implements ResultSetEntry {
29

    
30
        private ResultSet resultSet = null;
31
        private final int id;
32
        private long lastUse = 0;
33
        private String sql;
34
        private final FeatureAttributeDescriptor[] columns;
35
        private final String[] extraValueNames;
36

    
37
        public ResultSetEntryBase(ResultSet resulSet, String sql, FeatureAttributeDescriptor[] columns, String[] extraValueNames) {
38
            this.resultSet = resulSet;
39
            this.id = nextid++;
40
            this.sql = sql;
41
            this.columns = columns;
42
            this.extraValueNames = extraValueNames;
43
            used();
44
            resulSets.put(this.getID(), this);
45
        }
46

    
47
        private void used() {
48
            lastUse = System.currentTimeMillis();
49
        }
50

    
51
        @Override
52
        public ResultSet get() {
53
            used();
54
            return resultSet;
55
        }
56

    
57
        @Override
58
        public int getID() {
59
            return this.id;
60
        }
61

    
62
        @Override
63
        public boolean isZombie() {
64
            if( this.resultSet == null ) {
65
                return true;
66
            }
67
            return System.currentTimeMillis() - lastUse > mlsecondsToZombie;
68
        }
69

    
70
        @Override
71
        public String getSQL() {
72
            return this.sql;
73
        }
74

    
75
        @Override
76
        public String[] getExtraValueNames() {
77
            return this.extraValueNames;
78
        }
79
        
80
        @Override
81
        public FeatureAttributeDescriptor[] getColumns() {
82
            return this.columns;
83
        }
84
        
85
        @Override
86
        public Object getObject(int columnIndex) throws SQLException {
87
            used();
88
            return this.resultSet.getObject(columnIndex);
89
        }
90

    
91
        @Override
92
        public byte[] getBytes(int columnIndex) throws SQLException {
93
            used();
94
            return this.resultSet.getBytes(columnIndex);
95
        }
96

    
97
        @Override
98
        public boolean next() throws SQLException {
99
            return this.resultSet.next();
100
        }
101

    
102
        @Override
103
        public void close() throws Exception {
104
            if( this.resultSet == null ) {
105
                // Already close
106
                return;
107
            }
108
            Statement st = null;
109
            Connection con = null;
110
            try {
111
                resulSets.remove(this.getID());
112
                st = this.resultSet.getStatement();
113
                if( st != null ) {
114
                    con = st.getConnection();
115
                }
116
            } catch(Exception ex) {
117
                LOGGER.warn("Problems closing ResulSetEntryBase.",ex);
118
            }
119
            JDBCUtils.closeQuietly(this.resultSet);
120
            JDBCUtils.closeQuietly(st);
121
            helper.closeConnection(con);
122
            this.resultSet = null;
123
            LOGGER.debug(
124
                    "Close ResulSetEntryBase id {} (total {})",
125
                    this.getID(),
126
                    getOpenCount()
127
            );
128
            pack();
129
        }
130

    
131
    }
132

    
133
    private int nextid = 1;
134

    
135
    private Map<Integer, ResultSetEntryBase> resulSets;
136

    
137
    private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
138

    
139
    private JDBCHelper helper = null;
140

    
141
    public ResulSetControlerBase(JDBCHelper helper) {
142
        this.helper = helper;
143
        this.resulSets = new HashMap<>();
144
        this.nextid = 1;
145
    }
146

    
147
    @Override
148
    public long getTimeToZombie() {
149
        return mlsecondsToZombie;
150
    }
151

    
152
    @Override
153
    public void setTimeToZombie(long mlSeconds) {
154
        mlsecondsToZombie = mlSeconds;
155
    }
156

    
157
    @Override
158
    public void close() throws Exception {
159
        this.closeAll();
160
        this.helper = null;
161
        this.resulSets = null;
162
        this.nextid = -10;
163
    }
164

    
165
    @Override
166
    public ResultSetEntryBase create(
167
            String sql, 
168
            int fetchSize, 
169
            FeatureAttributeDescriptor[] columns,
170
            String[] extraValueNames) throws DataException {
171
        return create(sql, null, fetchSize, columns, extraValueNames);
172
    }
173

    
174
    @Override
175
    public synchronized ResultSetEntryBase create(
176
            String sql, 
177
            List<Object> values, 
178
            int fetchSize, 
179
            FeatureAttributeDescriptor[] columns, 
180
            String[] extraValueNames) throws DataException {
181
        this.pack();
182
        ResultSet rs = null;
183
        Connection conn = null;
184
        PreparedStatement st = null;
185
        Disposable paramsDisposer = null;
186
        try {
187
            conn = helper.getConnection();
188
            conn.setAutoCommit(false);
189
            st = conn.prepareStatement(sql);
190

    
191
            JDBCSQLBuilderBase sqlbuilder = helper.createSQLBuilder();
192
            paramsDisposer = sqlbuilder.setStatementParameters(st, values, helper.getGeometrySupportType());
193

    
194
            if (fetchSize > 0) {
195
                // See parameter "SelectMethod" of SQL Server Connection Properties
196
                // https://docs.oracle.com/cd/E13157_01/wlevs/docs30/jdbc_drivers/mssqlserver.html
197
                st.setFetchSize(fetchSize);
198
            }
199
            rs = JDBCUtils.executeQuery(st, sql);
200
            if (fetchSize > 0) {
201
                rs.setFetchSize(fetchSize);
202
            }
203
            ResultSetEntryBase rsentry = new ResultSetEntryBase(rs, sql, columns,  extraValueNames);
204
            return rsentry;
205

    
206
        } catch (SQLException e) {
207
            JDBCUtils.closeQuietly(rs);
208
            JDBCUtils.closeQuietly(st);
209
            this.helper.closeConnectionQuietly(conn);
210
            throw new JDBCExecutePreparedSQLException(sql, values, e);
211
        } finally {
212
            DisposeUtils.disposeQuietly(paramsDisposer);
213
        }
214
    }
215

    
216
    @Override
217
    public synchronized void closeAll() {
218

    
219
        // Para evitar problemas de concurrencia al eliminar elementos del
220
        // map mientras lo recorremos, cargamos las entredas en un List
221
        List<ResultSetEntryBase> entries = new ArrayList<>();
222
        entries.addAll(this.resulSets.values());
223

    
224
        for (ResultSetEntryBase entry : entries) {
225
            JDBCUtils.closeQuietly(entry);
226
        }
227
    }
228

    
229
    @Override
230
    public synchronized void pack() {
231
        // Para evitar problemas de concurrencia al eliminar elementos del
232
        // map mientras lo recorremos, cargamos las entredas en un List
233
        List<ResultSetEntryBase> entries = new ArrayList<>();
234
        entries.addAll(this.resulSets.values());
235

    
236
        int maxID = 0;
237
        for (ResultSetEntryBase entry : entries) {
238
            if (entry.isZombie()) {
239
                JDBCUtils.closeQuietly(entry);
240
            } else {
241
                if (entry.getID() > maxID) {
242
                    maxID = entry.getID();
243
                }
244
            }
245
        }
246
        this.nextid = maxID + 1;
247
    }
248

    
249
    @Override
250
    public synchronized int getOpenCount() {
251
        return this.resulSets.size();
252
    }
253
}