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 @ 43377

History | View | Annotate | Download (7.07 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.slf4j.Logger;
19
import org.slf4j.LoggerFactory;
20

    
21
public class ResulSetControlerBase implements ResulSetControler {
22

    
23
    final static private Logger logger = LoggerFactory.getLogger(ResulSetControlerBase.class);
24

    
25
    public class ResultSetEntryBase implements ResultSetEntry {
26

    
27
        private ResultSet resultSet = null;
28
        private final int id;
29
        private long lastUse = 0;
30
        private String sql;
31
        private final FeatureAttributeDescriptor[] columns;
32

    
33
        public ResultSetEntryBase(ResultSet resulSet, FeatureAttributeDescriptor[] columns) {
34
            this(resulSet,null, columns);
35
        }
36

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

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

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

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

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

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

    
74
        public FeatureAttributeDescriptor[] getColumns() {
75
            return this.columns;
76
        }
77
        
78
        @Override
79
        public Object getObject(int columnIndex) throws SQLException {
80
            used();
81
            return this.resultSet.getObject(columnIndex);
82
        }
83

    
84
        @Override
85
        public byte[] getBytes(int columnIndex) throws SQLException {
86
            used();
87
            return this.resultSet.getBytes(columnIndex);
88
        }
89

    
90
        @Override
91
        public boolean next() throws SQLException {
92
            return this.resultSet.next();
93
        }
94

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

    
124
    }
125

    
126
    private int nextid = 1;
127

    
128
    private Map<Integer, ResultSetEntryBase> resulSets;
129

    
130
    private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
131

    
132
    private JDBCHelper helper = null;
133

    
134
    public ResulSetControlerBase(JDBCHelper helper) {
135
        this.helper = helper;
136
        this.resulSets = new HashMap<>();
137
        this.nextid = 1;
138
    }
139

    
140
    @Override
141
    public long getTimeToZombie() {
142
        return mlsecondsToZombie;
143
    }
144

    
145
    @Override
146
    public void setTimeToZombie(long mlSeconds) {
147
        mlsecondsToZombie = mlSeconds;
148
    }
149

    
150
    @Override
151
    public void close() throws Exception {
152
        this.closeAll();
153
        this.helper = null;
154
        this.resulSets = null;
155
        this.nextid = -10;
156
    }
157

    
158
    @Override
159
    public ResultSetEntryBase create(
160
            String sql, 
161
            int fetchSize, 
162
            FeatureAttributeDescriptor[] columns) throws DataException {
163
        return create(sql, null, fetchSize, columns);
164
    }
165

    
166
    @Override
167
    public synchronized ResultSetEntryBase create(
168
            final String sql,
169
            final List values,
170
            final int fetchSize, 
171
            FeatureAttributeDescriptor[] columns) throws DataException {
172

    
173
        this.pack();
174
        ResultSet rs = null;
175
        Connection conn = null;
176
        PreparedStatement st = null;
177
        try {
178
            conn = helper.getConnection();
179
            conn.setAutoCommit(false);
180
            st = conn.prepareStatement(sql);
181

    
182
            JDBCUtils.setObjects(st, values, helper.getGeometrySupportType());
183

    
184
            if (fetchSize > 0) {
185
                // See parameter "SelectMethod" of SQL Server Connection Properties
186
                // https://docs.oracle.com/cd/E13157_01/wlevs/docs30/jdbc_drivers/mssqlserver.html
187
                st.setFetchSize(fetchSize);
188
            }
189
            rs = JDBCUtils.executeQuery(st, sql);
190
            if (fetchSize > 0) {
191
                rs.setFetchSize(fetchSize);
192
            }
193

    
194
        } catch (SQLException e) {
195
            JDBCUtils.closeQuietly(rs);
196
            JDBCUtils.closeQuietly(st);
197
            JDBCUtils.closeQuietly(conn);
198
            throw new JDBCExecutePreparedSQLException(sql, values, e);
199
        }
200
        ResultSetEntryBase rsentry = new ResultSetEntryBase(rs, sql, columns);
201
        return rsentry;
202
    }
203

    
204
    @Override
205
    public synchronized void closeAll() {
206

    
207
        // Para evitar problemas de concurrencia al eliminar elementos del
208
        // map mientras lo recorremos, cargamos las entredas en un List
209
        List<ResultSetEntryBase> entries = new ArrayList<>();
210
        entries.addAll(this.resulSets.values());
211

    
212
        for (ResultSetEntryBase entry : entries) {
213
            JDBCUtils.closeQuietly(entry);
214
        }
215
    }
216

    
217
    @Override
218
    public synchronized void pack() {
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
        int maxID = 0;
225
        for (ResultSetEntryBase entry : entries) {
226
            if (entry.isZombie()) {
227
                JDBCUtils.closeQuietly(entry);
228
            } else {
229
                if (entry.getID() > maxID) {
230
                    maxID = entry.getID();
231
                }
232
            }
233
        }
234
        this.nextid = maxID + 1;
235
    }
236

    
237
    @Override
238
    public synchronized int getOpenCount() {
239
        return this.resulSets.size();
240
    }
241
}