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 @ 46315
History | View | Annotate | Download (8.86 KB)
1 | 43020 | jjdelcerro | package org.gvsig.fmap.dal.store.jdbc2.impl; |
---|---|---|---|
2 | |||
3 | import java.sql.PreparedStatement; |
||
4 | import java.sql.ResultSet; |
||
5 | import java.sql.SQLException; |
||
6 | import java.sql.Statement; |
||
7 | import java.util.ArrayList; |
||
8 | import java.util.HashMap; |
||
9 | import java.util.List; |
||
10 | import java.util.Map; |
||
11 | import org.gvsig.fmap.dal.exception.DataException; |
||
12 | 43358 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
13 | 43020 | jjdelcerro | import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException; |
14 | 46315 | jjdelcerro | import org.gvsig.fmap.dal.store.jdbc2.JDBCConnection; |
15 | 43020 | jjdelcerro | 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 | 45736 | fdiaz | import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase; |
19 | 43629 | jjdelcerro | import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase; |
20 | import org.gvsig.tools.dispose.Disposable; |
||
21 | import org.gvsig.tools.dispose.DisposeUtils; |
||
22 | 43020 | jjdelcerro | import org.slf4j.Logger; |
23 | import org.slf4j.LoggerFactory; |
||
24 | |||
25 | public class ResulSetControlerBase implements ResulSetControler { |
||
26 | |||
27 | 44375 | jjdelcerro | final static private Logger LOGGER = LoggerFactory.getLogger(ResulSetControlerBase.class); |
28 | 43020 | jjdelcerro | |
29 | public class ResultSetEntryBase implements ResultSetEntry { |
||
30 | |||
31 | private ResultSet resultSet = null; |
||
32 | private final int id; |
||
33 | private long lastUse = 0; |
||
34 | 45766 | fdiaz | private final String sql; |
35 | 43358 | jjdelcerro | private final FeatureAttributeDescriptor[] columns; |
36 | 44376 | jjdelcerro | private final String[] extraValueNames; |
37 | 45425 | jjdelcerro | private Throwable closeCause ; |
38 | |||
39 | 45766 | fdiaz | private final String connId; |
40 | private final String hexId; |
||
41 | 46315 | jjdelcerro | private final JDBCConnection conn; |
42 | 43020 | jjdelcerro | |
43 | 46315 | jjdelcerro | public ResultSetEntryBase(JDBCConnection conn, ResultSet resulSet, String sql, FeatureAttributeDescriptor[] columns, String[] extraValueNames) { |
44 | this.conn = conn;
|
||
45 | 45425 | jjdelcerro | this.closeCause = null; |
46 | 43020 | jjdelcerro | this.resultSet = resulSet;
|
47 | 45425 | jjdelcerro | this.connId = JDBCUtils.getConnId(this.resultSet); |
48 | this.hexId = JDBCUtils.getHexId(this); |
||
49 | 43020 | jjdelcerro | this.id = nextid++;
|
50 | this.sql = sql;
|
||
51 | 43358 | jjdelcerro | this.columns = columns;
|
52 | 44376 | jjdelcerro | this.extraValueNames = extraValueNames;
|
53 | 43020 | jjdelcerro | used(); |
54 | 45766 | fdiaz | synchronized(resulSets){
|
55 | resulSets.put(this.getID(), this); |
||
56 | } |
||
57 | 45097 | jjdelcerro | if( LOGGER.isDebugEnabled() ) {
|
58 | 45425 | jjdelcerro | LOGGER.debug("["+JDBCUtils.getConnId(resulSet)+"] ResultSetEntryBase "+this.hexId+" "+sql); |
59 | 45097 | jjdelcerro | } |
60 | 45736 | fdiaz | LOGGER.debug(((JDBCHelperBase)helper).getConnectionProviderStatus()); |
61 | 43020 | jjdelcerro | } |
62 | |||
63 | private void used() { |
||
64 | lastUse = System.currentTimeMillis();
|
||
65 | } |
||
66 | |||
67 | @Override
|
||
68 | public ResultSet get() { |
||
69 | used(); |
||
70 | return resultSet;
|
||
71 | } |
||
72 | |||
73 | @Override
|
||
74 | public int getID() { |
||
75 | return this.id; |
||
76 | } |
||
77 | |||
78 | @Override
|
||
79 | public boolean isZombie() { |
||
80 | if( this.resultSet == null ) { |
||
81 | return true; |
||
82 | } |
||
83 | return System.currentTimeMillis() - lastUse > mlsecondsToZombie; |
||
84 | } |
||
85 | |||
86 | @Override
|
||
87 | public String getSQL() { |
||
88 | return this.sql; |
||
89 | } |
||
90 | |||
91 | 43629 | jjdelcerro | @Override
|
92 | 44376 | jjdelcerro | public String[] getExtraValueNames() { |
93 | return this.extraValueNames; |
||
94 | } |
||
95 | |||
96 | @Override
|
||
97 | 43358 | jjdelcerro | public FeatureAttributeDescriptor[] getColumns() { |
98 | return this.columns; |
||
99 | } |
||
100 | |||
101 | 43020 | jjdelcerro | @Override
|
102 | public Object getObject(int columnIndex) throws SQLException { |
||
103 | used(); |
||
104 | return this.resultSet.getObject(columnIndex); |
||
105 | } |
||
106 | |||
107 | @Override
|
||
108 | public byte[] getBytes(int columnIndex) throws SQLException { |
||
109 | used(); |
||
110 | return this.resultSet.getBytes(columnIndex); |
||
111 | } |
||
112 | |||
113 | @Override
|
||
114 | public boolean next() throws SQLException { |
||
115 | 45425 | jjdelcerro | if( this.closeCause!=null ) { |
116 | LOGGER.debug("["+this.connId+"] ResultSetEntryBase already closed "+this.hexId); |
||
117 | throw new IllegalStateException("ResultSetEntryBase already closed, connId="+this.connId+", id="+this.hexId+" (sql="+sql+")", closeCause); |
||
118 | } |
||
119 | 43020 | jjdelcerro | return this.resultSet.next(); |
120 | } |
||
121 | |||
122 | @Override
|
||
123 | public void close() throws Exception { |
||
124 | 45097 | jjdelcerro | if( LOGGER.isDebugEnabled() ) {
|
125 | 45425 | jjdelcerro | LOGGER.debug("["+this.connId+"] ResultSetEntryBase close "+this.hexId); |
126 | 45097 | jjdelcerro | } |
127 | 43020 | jjdelcerro | if( this.resultSet == null ) { |
128 | // Already close
|
||
129 | return;
|
||
130 | } |
||
131 | 45425 | jjdelcerro | this.closeCause = new Throwable(); |
132 | |||
133 | 43020 | jjdelcerro | Statement st = null; |
134 | try {
|
||
135 | 45766 | fdiaz | synchronized(resulSets){
|
136 | resulSets.remove(this.getID());
|
||
137 | } |
||
138 | 43020 | jjdelcerro | st = this.resultSet.getStatement();
|
139 | } catch(Exception ex) { |
||
140 | 44375 | jjdelcerro | LOGGER.warn("Problems closing ResulSetEntryBase.",ex);
|
141 | 43020 | jjdelcerro | } |
142 | JDBCUtils.closeQuietly(this.resultSet);
|
||
143 | JDBCUtils.closeQuietly(st); |
||
144 | 46315 | jjdelcerro | this.conn.closeQuietly();
|
145 | 43020 | jjdelcerro | this.resultSet = null; |
146 | 45736 | fdiaz | LOGGER.debug( |
147 | 43020 | jjdelcerro | "Close ResulSetEntryBase id {} (total {})",
|
148 | this.getID(),
|
||
149 | getOpenCount() |
||
150 | ); |
||
151 | 45736 | fdiaz | LOGGER.debug(((JDBCHelperBase)helper).getConnectionProviderStatus()); |
152 | 43020 | jjdelcerro | pack(); |
153 | } |
||
154 | |||
155 | } |
||
156 | |||
157 | private int nextid = 1; |
||
158 | |||
159 | 45766 | fdiaz | private final Map<Integer, ResultSetEntryBase> resulSets; |
160 | 43020 | jjdelcerro | |
161 | private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min |
||
162 | |||
163 | private JDBCHelper helper = null; |
||
164 | |||
165 | public ResulSetControlerBase(JDBCHelper helper) {
|
||
166 | this.helper = helper;
|
||
167 | this.resulSets = new HashMap<>(); |
||
168 | this.nextid = 1; |
||
169 | } |
||
170 | |||
171 | @Override
|
||
172 | public long getTimeToZombie() { |
||
173 | return mlsecondsToZombie;
|
||
174 | } |
||
175 | |||
176 | @Override
|
||
177 | public void setTimeToZombie(long mlSeconds) { |
||
178 | mlsecondsToZombie = mlSeconds; |
||
179 | } |
||
180 | |||
181 | @Override
|
||
182 | public void close() throws Exception { |
||
183 | this.closeAll();
|
||
184 | this.helper = null; |
||
185 | 45766 | fdiaz | this.resulSets.clear();
|
186 | 43020 | jjdelcerro | this.nextid = -10; |
187 | } |
||
188 | |||
189 | @Override
|
||
190 | 43358 | jjdelcerro | public ResultSetEntryBase create(
|
191 | String sql,
|
||
192 | int fetchSize,
|
||
193 | 44376 | jjdelcerro | FeatureAttributeDescriptor[] columns,
|
194 | String[] extraValueNames) throws DataException { |
||
195 | return create(sql, null, fetchSize, columns, extraValueNames); |
||
196 | 43020 | jjdelcerro | } |
197 | |||
198 | @Override
|
||
199 | public synchronized ResultSetEntryBase create( |
||
200 | 44376 | jjdelcerro | String sql,
|
201 | List<Object> values, |
||
202 | int fetchSize,
|
||
203 | FeatureAttributeDescriptor[] columns,
|
||
204 | String[] extraValueNames) throws DataException { |
||
205 | 43020 | jjdelcerro | this.pack();
|
206 | ResultSet rs = null; |
||
207 | 46315 | jjdelcerro | JDBCConnection conn = null;
|
208 | 43020 | jjdelcerro | PreparedStatement st = null; |
209 | 43629 | jjdelcerro | Disposable paramsDisposer = null;
|
210 | 43020 | jjdelcerro | try {
|
211 | conn = helper.getConnection(); |
||
212 | 46315 | jjdelcerro | conn.begin(); |
213 | 43020 | jjdelcerro | st = conn.prepareStatement(sql); |
214 | |||
215 | 43629 | jjdelcerro | JDBCSQLBuilderBase sqlbuilder = helper.createSQLBuilder(); |
216 | paramsDisposer = sqlbuilder.setStatementParameters(st, values, helper.getGeometrySupportType()); |
||
217 | 43020 | jjdelcerro | |
218 | if (fetchSize > 0) { |
||
219 | 43358 | jjdelcerro | // See parameter "SelectMethod" of SQL Server Connection Properties
|
220 | // https://docs.oracle.com/cd/E13157_01/wlevs/docs30/jdbc_drivers/mssqlserver.html
|
||
221 | 43020 | jjdelcerro | st.setFetchSize(fetchSize); |
222 | } |
||
223 | rs = JDBCUtils.executeQuery(st, sql); |
||
224 | if (fetchSize > 0) { |
||
225 | rs.setFetchSize(fetchSize); |
||
226 | } |
||
227 | 46315 | jjdelcerro | ResultSetEntryBase rsentry = new ResultSetEntryBase(conn, rs, sql, columns, extraValueNames);
|
228 | 43629 | jjdelcerro | return rsentry;
|
229 | 43020 | jjdelcerro | |
230 | } catch (SQLException e) { |
||
231 | JDBCUtils.closeQuietly(rs); |
||
232 | JDBCUtils.closeQuietly(st); |
||
233 | 46315 | jjdelcerro | JDBCConnection.closeQuietly(conn); |
234 | conn.closeQuietly(); |
||
235 | 43020 | jjdelcerro | throw new JDBCExecutePreparedSQLException(sql, values, e); |
236 | 43629 | jjdelcerro | } finally {
|
237 | DisposeUtils.disposeQuietly(paramsDisposer); |
||
238 | 43020 | jjdelcerro | } |
239 | } |
||
240 | 45766 | fdiaz | |
241 | private List<ResultSetEntryBase> getResultSetValues() { |
||
242 | synchronized(this.resulSets){ |
||
243 | List<ResultSetEntryBase> values = new ArrayList<>(); |
||
244 | values.addAll(this.resulSets.values());
|
||
245 | return values;
|
||
246 | } |
||
247 | } |
||
248 | 43020 | jjdelcerro | |
249 | @Override
|
||
250 | public synchronized void closeAll() { |
||
251 | |||
252 | 45766 | fdiaz | List<ResultSetEntryBase> values = getResultSetValues();
|
253 | 43020 | jjdelcerro | |
254 | 45766 | fdiaz | for (ResultSetEntryBase entry : values) {
|
255 | 43020 | jjdelcerro | JDBCUtils.closeQuietly(entry); |
256 | } |
||
257 | } |
||
258 | |||
259 | @Override
|
||
260 | public synchronized void pack() { |
||
261 | |||
262 | 45766 | fdiaz | List<ResultSetEntryBase> values = getResultSetValues();
|
263 | |||
264 | 43020 | jjdelcerro | int maxID = 0; |
265 | 45766 | fdiaz | for (ResultSetEntryBase entry : values) {
|
266 | 43020 | jjdelcerro | if (entry.isZombie()) {
|
267 | JDBCUtils.closeQuietly(entry); |
||
268 | } else {
|
||
269 | if (entry.getID() > maxID) {
|
||
270 | maxID = entry.getID(); |
||
271 | } |
||
272 | } |
||
273 | } |
||
274 | this.nextid = maxID + 1; |
||
275 | } |
||
276 | |||
277 | @Override
|
||
278 | 45766 | fdiaz | public int getOpenCount() { |
279 | synchronized(resulSets){
|
||
280 | return this.resulSets.size(); |
||
281 | } |
||
282 | 43020 | jjdelcerro | } |
283 | } |