1 | /* |
2 | * Copyright 2006-2012 the original author or authors. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | package org.springframework.batch.item.database.support; |
17 | |
18 | import static org.springframework.batch.support.DatabaseType.DB2; |
19 | import static org.springframework.batch.support.DatabaseType.DB2ZOS; |
20 | import static org.springframework.batch.support.DatabaseType.DERBY; |
21 | import static org.springframework.batch.support.DatabaseType.H2; |
22 | import static org.springframework.batch.support.DatabaseType.HSQL; |
23 | import static org.springframework.batch.support.DatabaseType.MYSQL; |
24 | import static org.springframework.batch.support.DatabaseType.ORACLE; |
25 | import static org.springframework.batch.support.DatabaseType.POSTGRES; |
26 | import static org.springframework.batch.support.DatabaseType.SQLSERVER; |
27 | import static org.springframework.batch.support.DatabaseType.SYBASE; |
28 | |
29 | import java.util.HashMap; |
30 | import java.util.LinkedHashMap; |
31 | import java.util.Map; |
32 | |
33 | import javax.sql.DataSource; |
34 | |
35 | import org.springframework.batch.item.database.Order; |
36 | import org.springframework.batch.item.database.PagingQueryProvider; |
37 | import org.springframework.batch.support.DatabaseType; |
38 | import org.springframework.beans.factory.FactoryBean; |
39 | import org.springframework.jdbc.support.MetaDataAccessException; |
40 | import org.springframework.util.Assert; |
41 | import org.springframework.util.StringUtils; |
42 | |
43 | /** |
44 | * Factory bean for {@link PagingQueryProvider} interface. The database type |
45 | * will be determined from the data source if not provided explicitly. Valid |
46 | * types are given by the {@link DatabaseType} enum. |
47 | * |
48 | * @author Dave Syer |
49 | * @author Michael Minella |
50 | */ |
51 | @SuppressWarnings("rawtypes") |
52 | public class SqlPagingQueryProviderFactoryBean implements FactoryBean { |
53 | |
54 | private DataSource dataSource; |
55 | |
56 | private String databaseType; |
57 | |
58 | private String fromClause; |
59 | |
60 | private String whereClause; |
61 | |
62 | private String selectClause; |
63 | |
64 | private String groupClause; |
65 | |
66 | private Map<String, Order> sortKeys; |
67 | |
68 | private Map<DatabaseType, AbstractSqlPagingQueryProvider> providers = new HashMap<DatabaseType, AbstractSqlPagingQueryProvider>(); |
69 | |
70 | |
71 | { |
72 | providers.put(DB2, new Db2PagingQueryProvider()); |
73 | providers.put(DB2ZOS, new Db2PagingQueryProvider()); |
74 | providers.put(DERBY,new DerbyPagingQueryProvider()); |
75 | providers.put(HSQL,new HsqlPagingQueryProvider()); |
76 | providers.put(H2,new H2PagingQueryProvider()); |
77 | providers.put(MYSQL,new MySqlPagingQueryProvider()); |
78 | providers.put(ORACLE,new OraclePagingQueryProvider()); |
79 | providers.put(POSTGRES,new PostgresPagingQueryProvider()); |
80 | providers.put(SQLSERVER,new SqlServerPagingQueryProvider()); |
81 | providers.put(SYBASE,new SybasePagingQueryProvider()); |
82 | } |
83 | |
84 | /** |
85 | * @param groupClause SQL GROUP BY clause part of the SQL query string |
86 | */ |
87 | public void setGroupClause(String groupClause) { |
88 | this.groupClause = groupClause; |
89 | } |
90 | |
91 | /** |
92 | * @param databaseType the databaseType to set |
93 | */ |
94 | public void setDatabaseType(String databaseType) { |
95 | this.databaseType = databaseType; |
96 | } |
97 | |
98 | /** |
99 | * @param dataSource the dataSource to set |
100 | */ |
101 | public void setDataSource(DataSource dataSource) { |
102 | this.dataSource = dataSource; |
103 | } |
104 | |
105 | /** |
106 | * @param fromClause the fromClause to set |
107 | */ |
108 | public void setFromClause(String fromClause) { |
109 | this.fromClause = fromClause; |
110 | } |
111 | |
112 | /** |
113 | * @param whereClause the whereClause to set |
114 | */ |
115 | public void setWhereClause(String whereClause) { |
116 | this.whereClause = whereClause; |
117 | } |
118 | |
119 | /** |
120 | * @param selectClause the selectClause to set |
121 | */ |
122 | public void setSelectClause(String selectClause) { |
123 | this.selectClause = selectClause; |
124 | } |
125 | |
126 | /** |
127 | * @param sortKeys the sortKeys to set |
128 | */ |
129 | public void setSortKeys(Map<String, Order> sortKeys) { |
130 | this.sortKeys = sortKeys; |
131 | } |
132 | |
133 | public void setSortKey(String key) { |
134 | Assert.doesNotContain(key, ",", "String setter is valid for a single ASC key only"); |
135 | |
136 | Map<String, Order> keys = new LinkedHashMap<String, Order>(); |
137 | keys.put(key, Order.ASCENDING); |
138 | |
139 | this.sortKeys = keys; |
140 | } |
141 | |
142 | /** |
143 | * Get a {@link PagingQueryProvider} instance using the provided properties |
144 | * and appropriate for the given database type. |
145 | * |
146 | * @see FactoryBean#getObject() |
147 | */ |
148 | @Override |
149 | public Object getObject() throws Exception { |
150 | |
151 | DatabaseType type; |
152 | try { |
153 | type = databaseType != null ? DatabaseType.valueOf(databaseType.toUpperCase()) : DatabaseType |
154 | .fromMetaData(dataSource); |
155 | } |
156 | catch (MetaDataAccessException e) { |
157 | throw new IllegalArgumentException( |
158 | "Could not inspect meta data for database type. You have to supply it explicitly.", e); |
159 | } |
160 | |
161 | AbstractSqlPagingQueryProvider provider = providers.get(type); |
162 | Assert.state(provider!=null, "Should not happen: missing PagingQueryProvider for DatabaseType="+type); |
163 | |
164 | provider.setFromClause(fromClause); |
165 | provider.setWhereClause(whereClause); |
166 | provider.setSortKeys(sortKeys); |
167 | if (StringUtils.hasText(selectClause)) { |
168 | provider.setSelectClause(selectClause); |
169 | } |
170 | if(StringUtils.hasText(groupClause)) { |
171 | provider.setGroupClause(groupClause); |
172 | } |
173 | |
174 | provider.init(dataSource); |
175 | |
176 | return provider; |
177 | |
178 | } |
179 | |
180 | /** |
181 | * Always returns {@link PagingQueryProvider}. |
182 | * |
183 | * @see FactoryBean#getObjectType() |
184 | */ |
185 | @Override |
186 | public Class<PagingQueryProvider> getObjectType() { |
187 | return PagingQueryProvider.class; |
188 | } |
189 | |
190 | /** |
191 | * Always returns true. |
192 | * @see FactoryBean#isSingleton() |
193 | */ |
194 | @Override |
195 | public boolean isSingleton() { |
196 | return true; |
197 | } |
198 | |
199 | } |