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 @ 44198
History | View | Annotate | Download (7.47 KB)
1 | 43020 | jjdelcerro | 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 | 43358 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
14 | 43020 | jjdelcerro | 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 | 43629 | jjdelcerro | import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase; |
19 | import org.gvsig.tools.dispose.Disposable; |
||
20 | import org.gvsig.tools.dispose.DisposeUtils; |
||
21 | 43020 | jjdelcerro | 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 | 43358 | jjdelcerro | private final FeatureAttributeDescriptor[] columns; |
35 | 43020 | jjdelcerro | |
36 | 43358 | jjdelcerro | public ResultSetEntryBase(ResultSet resulSet, FeatureAttributeDescriptor[] columns) { |
37 | this(resulSet,null, columns); |
||
38 | 43020 | jjdelcerro | } |
39 | |||
40 | 43358 | jjdelcerro | public ResultSetEntryBase(ResultSet resulSet, String sql, FeatureAttributeDescriptor[] columns) { |
41 | 43020 | jjdelcerro | this.resultSet = resulSet;
|
42 | this.id = nextid++;
|
||
43 | this.sql = sql;
|
||
44 | 43358 | jjdelcerro | this.columns = columns;
|
45 | 43020 | jjdelcerro | used(); |
46 | resulSets.put(this.getID(), this); |
||
47 | } |
||
48 | |||
49 | private void used() { |
||
50 | lastUse = System.currentTimeMillis();
|
||
51 | } |
||
52 | |||
53 | @Override
|
||
54 | public ResultSet get() { |
||
55 | used(); |
||
56 | return resultSet;
|
||
57 | } |
||
58 | |||
59 | @Override
|
||
60 | public int getID() { |
||
61 | return this.id; |
||
62 | } |
||
63 | |||
64 | @Override
|
||
65 | public boolean isZombie() { |
||
66 | if( this.resultSet == null ) { |
||
67 | return true; |
||
68 | } |
||
69 | return System.currentTimeMillis() - lastUse > mlsecondsToZombie; |
||
70 | } |
||
71 | |||
72 | @Override
|
||
73 | public String getSQL() { |
||
74 | return this.sql; |
||
75 | } |
||
76 | |||
77 | 43629 | jjdelcerro | @Override
|
78 | 43358 | jjdelcerro | public FeatureAttributeDescriptor[] getColumns() { |
79 | return this.columns; |
||
80 | } |
||
81 | |||
82 | 43020 | jjdelcerro | @Override
|
83 | public Object getObject(int columnIndex) throws SQLException { |
||
84 | used(); |
||
85 | return this.resultSet.getObject(columnIndex); |
||
86 | } |
||
87 | |||
88 | @Override
|
||
89 | public byte[] getBytes(int columnIndex) throws SQLException { |
||
90 | used(); |
||
91 | return this.resultSet.getBytes(columnIndex); |
||
92 | } |
||
93 | |||
94 | @Override
|
||
95 | public boolean next() throws SQLException { |
||
96 | return this.resultSet.next(); |
||
97 | } |
||
98 | |||
99 | @Override
|
||
100 | public void close() throws Exception { |
||
101 | if( this.resultSet == null ) { |
||
102 | // Already close
|
||
103 | return;
|
||
104 | } |
||
105 | Statement st = null; |
||
106 | Connection con = null; |
||
107 | try {
|
||
108 | resulSets.remove(this.getID());
|
||
109 | st = this.resultSet.getStatement();
|
||
110 | if( st != null ) { |
||
111 | con = st.getConnection(); |
||
112 | } |
||
113 | } catch(Exception ex) { |
||
114 | logger.warn("Problems closing ResulSetEntryBase.",ex);
|
||
115 | } |
||
116 | JDBCUtils.closeQuietly(this.resultSet);
|
||
117 | JDBCUtils.closeQuietly(st); |
||
118 | 43377 | jjdelcerro | helper.closeConnection(con); |
119 | 43020 | jjdelcerro | this.resultSet = null; |
120 | logger.debug( |
||
121 | "Close ResulSetEntryBase id {} (total {})",
|
||
122 | this.getID(),
|
||
123 | getOpenCount() |
||
124 | ); |
||
125 | pack(); |
||
126 | } |
||
127 | |||
128 | } |
||
129 | |||
130 | private int nextid = 1; |
||
131 | |||
132 | private Map<Integer, ResultSetEntryBase> resulSets; |
||
133 | |||
134 | private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min |
||
135 | |||
136 | private JDBCHelper helper = null; |
||
137 | |||
138 | public ResulSetControlerBase(JDBCHelper helper) {
|
||
139 | this.helper = helper;
|
||
140 | this.resulSets = new HashMap<>(); |
||
141 | this.nextid = 1; |
||
142 | } |
||
143 | |||
144 | @Override
|
||
145 | public long getTimeToZombie() { |
||
146 | return mlsecondsToZombie;
|
||
147 | } |
||
148 | |||
149 | @Override
|
||
150 | public void setTimeToZombie(long mlSeconds) { |
||
151 | mlsecondsToZombie = mlSeconds; |
||
152 | } |
||
153 | |||
154 | @Override
|
||
155 | public void close() throws Exception { |
||
156 | this.closeAll();
|
||
157 | this.helper = null; |
||
158 | this.resulSets = null; |
||
159 | this.nextid = -10; |
||
160 | } |
||
161 | |||
162 | @Override
|
||
163 | 43358 | jjdelcerro | public ResultSetEntryBase create(
|
164 | String sql,
|
||
165 | int fetchSize,
|
||
166 | FeatureAttributeDescriptor[] columns) throws DataException { |
||
167 | return create(sql, null, fetchSize, columns); |
||
168 | 43020 | jjdelcerro | } |
169 | |||
170 | @Override
|
||
171 | public synchronized ResultSetEntryBase create( |
||
172 | final String sql, |
||
173 | final List values, |
||
174 | 43358 | jjdelcerro | final int fetchSize, |
175 | FeatureAttributeDescriptor[] columns) throws DataException { |
||
176 | 43020 | jjdelcerro | |
177 | this.pack();
|
||
178 | ResultSet rs = null; |
||
179 | Connection conn = null; |
||
180 | PreparedStatement st = null; |
||
181 | 43629 | jjdelcerro | Disposable paramsDisposer = null;
|
182 | 43020 | jjdelcerro | try {
|
183 | conn = helper.getConnection(); |
||
184 | conn.setAutoCommit(false);
|
||
185 | st = conn.prepareStatement(sql); |
||
186 | |||
187 | 43629 | jjdelcerro | JDBCSQLBuilderBase sqlbuilder = helper.createSQLBuilder(); |
188 | paramsDisposer = sqlbuilder.setStatementParameters(st, values, helper.getGeometrySupportType()); |
||
189 | 43020 | jjdelcerro | |
190 | if (fetchSize > 0) { |
||
191 | 43358 | jjdelcerro | // See parameter "SelectMethod" of SQL Server Connection Properties
|
192 | // https://docs.oracle.com/cd/E13157_01/wlevs/docs30/jdbc_drivers/mssqlserver.html
|
||
193 | 43020 | jjdelcerro | st.setFetchSize(fetchSize); |
194 | } |
||
195 | rs = JDBCUtils.executeQuery(st, sql); |
||
196 | if (fetchSize > 0) { |
||
197 | rs.setFetchSize(fetchSize); |
||
198 | } |
||
199 | 43629 | jjdelcerro | ResultSetEntryBase rsentry = new ResultSetEntryBase(rs, sql, columns);
|
200 | return rsentry;
|
||
201 | 43020 | jjdelcerro | |
202 | } catch (SQLException e) { |
||
203 | JDBCUtils.closeQuietly(rs); |
||
204 | JDBCUtils.closeQuietly(st); |
||
205 | 44191 | jjdelcerro | this.helper.closeConnectionQuietly(conn);
|
206 | 43020 | jjdelcerro | throw new JDBCExecutePreparedSQLException(sql, values, e); |
207 | 43629 | jjdelcerro | } finally {
|
208 | DisposeUtils.disposeQuietly(paramsDisposer); |
||
209 | 43020 | jjdelcerro | } |
210 | } |
||
211 | |||
212 | @Override
|
||
213 | public synchronized void closeAll() { |
||
214 | |||
215 | // Para evitar problemas de concurrencia al eliminar elementos del
|
||
216 | // map mientras lo recorremos, cargamos las entredas en un List
|
||
217 | List<ResultSetEntryBase> entries = new ArrayList<>(); |
||
218 | entries.addAll(this.resulSets.values());
|
||
219 | |||
220 | for (ResultSetEntryBase entry : entries) {
|
||
221 | JDBCUtils.closeQuietly(entry); |
||
222 | } |
||
223 | } |
||
224 | |||
225 | @Override
|
||
226 | public synchronized void pack() { |
||
227 | // Para evitar problemas de concurrencia al eliminar elementos del
|
||
228 | // map mientras lo recorremos, cargamos las entredas en un List
|
||
229 | List<ResultSetEntryBase> entries = new ArrayList<>(); |
||
230 | entries.addAll(this.resulSets.values());
|
||
231 | |||
232 | int maxID = 0; |
||
233 | for (ResultSetEntryBase entry : entries) {
|
||
234 | if (entry.isZombie()) {
|
||
235 | JDBCUtils.closeQuietly(entry); |
||
236 | } else {
|
||
237 | if (entry.getID() > maxID) {
|
||
238 | maxID = entry.getID(); |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | this.nextid = maxID + 1; |
||
243 | } |
||
244 | |||
245 | @Override
|
||
246 | public synchronized int getOpenCount() { |
||
247 | return this.resulSets.size(); |
||
248 | } |
||
249 | } |