Dao层封装泛型实现(spring mvc,springjdbctemplate)

代码片段(6) [全屏查看所有代码]

1. [代码]BaseDao     跳至 [1] [2] [3] [4] [全屏预览]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package com.zjhc.commons.db.dao;
 
import java.util.List;
import java.util.Map;
 
import com.zjhc.commons.domain.condition.Condition;
import com.zjhc.commons.domain.mapper.MapRowMapper;
import com.zjhc.commons.domain.model.DataStore;
import com.zjhc.commons.domain.model.PagingParameter;
import com.zjhc.commons.exception.DaoAccessException;
 
/**
 * 数据查询DAO接口
 *
 * 创建日期:2012-9-26
 * @author wangk
 */
public interface BaseDao {
     
    /**
     * 查询SQL语句
     *
     * @param sql                        SQL语句
     * @param params                     SQL参数
     * @return List<Map<String, Object>> 查询结果
     * 创建日期:2012-9-26
     * 修改说明:
     * @author wangk
     */
    public List<Map<String, Object>> search(String sql, Object... params) throws DaoAccessException;
    public List<Map<String, Object>> search(String sql, List<Object> params) throws DaoAccessException;
    public List<Map<String, Object>> search(String sql, Map<String, Object> params) throws DaoAccessException;
     
    /**
     * 查询SQL语句
     *
     * @param <R>           行记录类型
     * @param sql           SQL语句
     * @param mapRowMapper  Map行数据映射对象
     * @param params        SQL参数
     * @return List<R>      查询结果
     * 创建日期:2012-9-26
     * 修改说明:
     * @author wangk
     */
    public <R> List<R> search(String sql, MapRowMapper<R> mapRowMapper, Object... params) throws DaoAccessException;
    public <R> List<R> search(String sql, MapRowMapper<R> mapRowMapper, List<Object> params) throws DaoAccessException;
    public <R> List<R> search(String sql, MapRowMapper<R> mapRowMapper, Map<String, Object> params) throws DaoAccessException;
     
    /**
     * 分页查询数据
     *
     * @param sql                             SQL语句
     * @param paging                          分页参数
     * @param params                          SQL参数
     * @return DataStore<Map<String, Object>> 分页数据
     * 创建日期:2012-9-26
     * 修改说明:
     * @author wangk
     */
    public DataStore<Map<String, Object>> search(String sql, PagingParameter paging, Object... params) throws DaoAccessException;
    public DataStore<Map<String, Object>> search(String sql, PagingParameter paging, List<Object> params) throws DaoAccessException;
    public DataStore<Map<String, Object>> search(String sql, PagingParameter paging, Map<String, Object> params) throws DaoAccessException;
     
    /**
     * 分页查询数据
     *
     * @param <R>           行记录类型
     * @param sql           SQL语句
     * @param mapRowMapper  Map行数据映射对象
     * @param paging        分页参数
     * @param params        SQL参数
     * @return DataStore<R> 分页数据
     * 创建日期:2012-9-26
     * 修改说明:
     * @author wangk
     */
    public <R> DataStore<R> search(String sql, MapRowMapper<R> mapRowMapper, PagingParameter paging, Object... params) throws DaoAccessException;
    public <R> DataStore<R> search(String sql, MapRowMapper<R> mapRowMapper, PagingParameter paging, List<Object> params) throws DaoAccessException;
    public <R> DataStore<R> search(String sql, MapRowMapper<R> mapRowMapper, PagingParameter paging, Map<String, Object> params) throws DaoAccessException;
 
    /**
     * 连接查询
     *
     * @param condition                  查询条件,指定列格式:表名.列名
     * @param classLink                  连接实体类类型链
     * @return List<Map<String, Object>> 查询结果,Map.key: 对象名(Class指定的类名的首字母小写形式).属性名
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public List<Map<String, Object>> join(Condition condition, Class<?>... classLink) throws DaoAccessException;
     
    /**
     * 连接查询
     *
     * @param condition 查询条件
     * @param orders    排序对象
     * @param classLink 连接实体类类型链
     * @return          查询结果
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public List<Map<String, Object>> join(Condition condition, String orders, Class<?>... classLink) throws DaoAccessException;
     
    /**
     * 连接查询(内连接)
     *
     * @param <R>          映射类型参数
     * @param condition    查询条件
     * @param mapRowMapper 行匹配对象
     * @param classLink    连接实体类型链(从子表到父表的顺序)
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public <R> List<R> join(Condition condition, MapRowMapper<R> mapRowMapper, Class<?>... classLink) throws DaoAccessException;   
     
    /**
     * 连接查询
     *
     * @param <R>          映射类型参数
     * @param condition    查询条件
     * @param orders       排序对象
     * @param mapRowMapper 行匹配对象
     * @param classLink    连接实体类型链
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public <R> List<R> join(Condition condition, String orders, MapRowMapper<R> mapRowMapper, Class<?>... classLink) throws DaoAccessException;
     
    /**
     * 连接查询
     *
     * @param condition   查询条件
     * @param paging      分页参数
     * @param classLink   连接实体类型链
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public DataStore<Map<String, Object>> join(Condition condition, PagingParameter paging, Class<?>... classLink) throws DaoAccessException;
     
    /**
     * 连接查询
     *
     * @param condition  查询条件
     * @param orders     排序对象
     * @param paging     分页参数
     * @param classLink  连接实体类型链
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public DataStore<Map<String, Object>> join(Condition condition, String orders, PagingParameter paging, Class<?>... classLink) throws DaoAccessException;
     
    /**
     * 连接查询
     *
     * @param <R>          映射类型参数
     * @param condition    查询条件
     * @param mapRowMapper 行匹配对象
     * @param paging       分页参数
     * @param classLink    连接实体类型链
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public <R> DataStore<R> join(Condition condition, MapRowMapper<R> mapRowMapper, PagingParameter paging, Class<?>... classLink) throws DaoAccessException;
     
    /**
     * 连接查询
     *
     * @param <R>          映射类型参数
     * @param condition    查询条件
     * @param orders       排序对象
     * @param mapRowMapper 行匹配对象
     * @param paging       分页参数
     * @param classLink    连接实体类型链
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    public <R> DataStore<R> join(Condition condition, String orders, MapRowMapper<R> mapRowMapper, PagingParameter paging, Class<?>... classLink) throws DaoAccessException;
 
}

2. [代码]BaseDaoSupport     跳至 [1] [2] [3] [4] [全屏预览]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
package com.zjhc.commons.db.dao;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.zjhc.commons.db.Entity;
import com.zjhc.commons.db.builder.PagingSqlBuilder;
import com.zjhc.commons.db.builder.SimpleSqlBuilder;
import com.zjhc.commons.domain.condition.Condition;
import com.zjhc.commons.domain.mapper.MapRowMapper;
import com.zjhc.commons.domain.model.DataStore;
import com.zjhc.commons.domain.model.PagingParameter;
import com.zjhc.commons.exception.DaoAccessException;
 
/**
 * 数据查询DAO支持类
 *
 * 创建日期:2012-9-26
 * @author wangk
 */
public abstract class BaseDaoSupport implements BaseDao, InitializingBean {
    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(BaseDaoSupport.class);
    /** 实现类日志对象 */
    protected final Logger log = Logger.getLogger(getClass());
     
    /** JDBC模版对象 */
    @Autowired
    protected JdbcTemplate jdbcTemplate;
    /** SQL语句参数带名称的JDBC模版对象 */
    protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    /** 分页SQL语句创建对象 */
    protected PagingSqlBuilder pagingSqlBuilder;
     
    /**
     * 获得JDBC模版对象
     *
     * @return
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }
 
    /**
     * 获得SQL语句参数带名称的JDBC模版对象
     *
     * @return
     * 创建日期:2012-12-19
     * 修改说明:
     * @author wangk
     */
    public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
        return namedParameterJdbcTemplate;
    }
 
    /**
     * 获得分页SQL语句创建对象
     *
     * @return
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public PagingSqlBuilder getPagingSqlBuilder() {
        return pagingSqlBuilder;
    }
 
    /**
     * 初始化非注入的属性
     *
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     * 创建日期:2012-12-19
     * 修改说明:
     * @author wangk
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //初始化namedParameterJdbcTemplate
        namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
        //初始化pagingSqlBuilder
        pagingSqlBuilder = new PagingSqlBuilder(((ComboPooledDataSource)
                jdbcTemplate.getDataSource()).getJdbcUrl().replaceAll("://.*$", ""));
    }
     
    @Override
    public List<Map<String, Object>> search(String sql, Object... params) throws DaoAccessException {
        try {
            logger.debug(sql);
            return jdbcTemplate.queryForList(sql, params);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public List<Map<String, Object>> search(String sql, List<Object> params) throws DaoAccessException {
        return search(sql, params.toArray());
    }
 
    @Override
    public List<Map<String, Object>> search(String sql, Map<String, Object> params) throws DaoAccessException {
        try {
            logger.debug(sql);
            return namedParameterJdbcTemplate.queryForList(sql, params);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
     
     
    @Override
    public <R> List<R> search(String sql, MapRowMapper<R> mapRowMapper, Object... params) throws DaoAccessException {
        List<Map<String, Object>> list = search(sql, params);
        if(list == null) {
            return null;
        }
        List<R> ret = new ArrayList<R>();
        for (int i = 0; i < list.size(); i++) {
            ret.add(mapRowMapper.mapRow(list.get(i), i));
        }
        return ret;
    }
 
    @Override
    public <R> List<R> search(String sql, MapRowMapper<R> mapRowMapper,
            List<Object> params) throws DaoAccessException {
        return search(sql, mapRowMapper, params.toArray());
    }
 
    @Override
    public <R> List<R> search(String sql, MapRowMapper<R> mapRowMapper,
            Map<String, Object> params) throws DaoAccessException {
        List<Map<String, Object>> list = search(sql, params);
        if(list == null) {
            return null;
        }
        List<R> ret = new ArrayList<R>();
        for (int i = 0; i < list.size(); i++) {
            ret.add(mapRowMapper.mapRow(list.get(i), i));
        }
        return ret;
    }
     
     
    @Override
    public DataStore<Map<String, Object>> search(String sql, PagingParameter paging,
            Object... params) throws DaoAccessException {
        try {
            PagingSqlBuilder pagingSqlBuilder = getPagingSqlBuilder();
            int records = jdbcTemplate.queryForInt(pagingSqlBuilder.getCountSql(sql), params);
            if(records < 0) {
                return null;
            }
            if(records == 0) {
                return new DataStore<Map<String, Object>>(records, new ArrayList<Map<String, Object>>());
            }
            return new DataStore<Map<String, Object>>(records, search(pagingSqlBuilder.getPagingSql(sql, paging), params));
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
         
    }
 
    @Override
    public DataStore<Map<String, Object>> search(String sql,
            PagingParameter paging, List<Object> params) throws DaoAccessException {
        return search(sql, paging, params.toArray());
    }
 
    @Override
    public DataStore<Map<String, Object>> search(String sql,
            PagingParameter paging, Map<String, Object> params) throws DaoAccessException {
        try {
            PagingSqlBuilder pagingSqlBuilder = getPagingSqlBuilder();
            int records = namedParameterJdbcTemplate.queryForInt(pagingSqlBuilder.getCountSql(sql), params);
            if(records < 0) {
                return null;
            }
            if(records == 0) {
                return new DataStore<Map<String, Object>>(records, new ArrayList<Map<String, Object>>());
            }
            return new DataStore<Map<String, Object>>(records, search(pagingSqlBuilder.getPagingSql(sql, paging), params));
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
     
 
    @Override
    public <R> DataStore<R> search(String sql, MapRowMapper<R> mapRowMapper, PagingParameter paging, Object... params) throws DaoAccessException {
        DataStore<Map<String, Object>> dataStore = search(sql, paging, params);
        if(dataStore == null) {
            return null;
        }
        if(dataStore.getDatas() == null) {
            return new DataStore<R>(dataStore.getRecords(), null);
        }
        List<R> list = new ArrayList<R>();
        for (int i = 0; i < dataStore.getDatas().size(); i++) {
            list.add(mapRowMapper.mapRow(dataStore.getDatas().get(i), i));
        }
        return new DataStore<R>(dataStore.getRecords(), list);
    }
 
    @Override
    public <R> DataStore<R> search(String sql, MapRowMapper<R> mapRowMapper,
            PagingParameter paging, List<Object> params) throws DaoAccessException {
        return search(sql, mapRowMapper, paging, params.toArray());
    }
 
    @Override
    public <R> DataStore<R> search(String sql, MapRowMapper<R> mapRowMapper,
            PagingParameter paging, Map<String, Object> params) throws DaoAccessException {
        DataStore<Map<String, Object>> dataStore = search(sql, paging, params);
        if(dataStore == null) {
            return null;
        }
        if(dataStore.getDatas() == null) {
            return new DataStore<R>(dataStore.getRecords(), null);
        }
        List<R> list = new ArrayList<R>();
        for (int i = 0; i < dataStore.getDatas().size(); i++) {
            list.add(mapRowMapper.mapRow(dataStore.getDatas().get(i), i));
        }
        return new DataStore<R>(dataStore.getRecords(), list);
    }
     
     
    @Override
    public List<Map<String, Object>> join(Condition condition,
            Class<?>... classLink) throws DaoAccessException {
        String orders = null;
        return join(condition, orders, classLink);
    }
 
    @Override
    public List<Map<String, Object>> join(Condition condition, String orders,
            Class<?>... classLink) throws DaoAccessException {
        String sql = buildJoinSql(condition, orders, classLink);
        List<Map<String, Object>> result = null;
        if(condition == null) {
            result = search(sql);
        } else {
            result = search(sql, condition.getParameters());
        }
        convertJoinResult(result, classLink);
        return result;
    }
 
    @Override
    public <R> List<R> join(Condition condition, MapRowMapper<R> mapRowMapper,
            Class<?>... classLink) throws DaoAccessException {
        return join(condition, null, mapRowMapper, classLink);
    }
 
    @Override
    public <R> List<R> join(Condition condition, String orders,
            MapRowMapper<R> mapRowMapper, Class<?>... classLink) throws DaoAccessException {
        List<Map<String, Object>> list = join(condition, orders, classLink);
        if(list == null) {
            return null;
        }
        List<R> ret = new ArrayList<R>();
        for (int i = 0; i < list.size(); i++) {
            ret.add(mapRowMapper.mapRow(list.get(i), i));
        }
        return ret;
    }
 
    @Override
    public DataStore<Map<String, Object>> join(Condition condition,
            PagingParameter paging, Class<?>... classLink) throws DaoAccessException {
        String orders = null;
        return join(condition, orders , paging, classLink);
    }
 
    @Override
    public DataStore<Map<String, Object>> join(Condition condition,
            String orders, PagingParameter paging,
            Class<?>... classLink) throws DaoAccessException {
        PagingSqlBuilder pagingSqlBuilder = getPagingSqlBuilder();
        String sql = buildJoinSql(condition, orders, classLink);
        Object[] params = new Object[0];
        if(condition != null) {
            params = condition.getParameters();
        }
        int records = 0;
        try {
            records = jdbcTemplate.queryForInt(pagingSqlBuilder.getCountSql(sql), params);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
        if(records < 0) {
            return null;
        }
        if(records == 0) {
            return new DataStore<Map<String, Object>>(records, new ArrayList<Map<String, Object>>());
        }
        List<Map<String, Object>> datas = null;
        datas = search(pagingSqlBuilder.getPagingSql(sql, paging), params);
        convertJoinResult(datas, classLink);
        return new DataStore<Map<String, Object>>(records, datas);
    }
 
    @Override
    public <R> DataStore<R> join(Condition condition,
            MapRowMapper<R> mapRowMapper, PagingParameter paging,
            Class<?>... classLink) throws DaoAccessException {
        return join(condition, null, mapRowMapper, paging, classLink);
    }
 
    @Override
    public <R> DataStore<R> join(Condition condition, String orders,
            MapRowMapper<R> mapRowMapper, PagingParameter paging,
            Class<?>... classLink) throws DaoAccessException {
        DataStore<Map<String, Object>> dataStore = join(condition, orders, paging, classLink);
        if(dataStore == null) {
            return null;
        }
        if(dataStore.getDatas() == null) {
            return new DataStore<R>(dataStore.getRecords(), null);
        }
        List<R> list = new ArrayList<R>();
        for (int i = 0; i < dataStore.getDatas().size(); i++) {
            list.add(mapRowMapper.mapRow(dataStore.getDatas().get(i), i));
        }
        return new DataStore<R>(dataStore.getRecords(), list);
    }
 
    /**
     * 构建(内)连接SQL语句
     *
     * @param condition
     * @param orders
     * @param classLink
     * @return
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private String buildJoinSql(Condition condition, String orders,
            Class<?>... classLink) throws DaoAccessException {
        try {
            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0;i < classLink.length;i++) {
                Class<? extends Entity> clazz = (Class<? extends Entity>)classLink[i];
                SimpleSqlBuilder<? extends Entity> sqlBuilder1 = new SimpleSqlBuilder(clazz);
                String tableName1 = sqlBuilder1.getTableName();
                Map<String, String> fieldColumnMapping1 = sqlBuilder1.getFieldColumnMapping();
                for (String field : sqlBuilder1.getFieldColumnMapping().keySet()) {
                    sb1.append(tableName1 +  "." + fieldColumnMapping1.get(field) + " AS " +
                            tableName1 +  "_" + fieldColumnMapping1.get(field) + ", ");
                }
                if(i == classLink.length - 1) {
                    break;
                }
                Class<? extends Entity> rClass = (Class<? extends Entity>)classLink[i+1];          
                SimpleSqlBuilder<? extends Entity> sqlBuilder2 = new SimpleSqlBuilder(rClass);
                String tableName2 = sqlBuilder2.getTableName();
                if(i == 0) {
                    sb2.append(tableName1);
                }
                sb2.append(" JOIN " + tableName2 + " ON " + tableName1 + "." +
                        fieldColumnMapping1.get(sqlBuilder1.getReferenceField(rClass)) +
                        " = " + tableName2 + "." + sqlBuilder1.getReferencedColumn(rClass));
            }
            sb1.delete(sb1.length() - 2, sb1.length());
            String sql = "SELECT " + sb1 + " FROM " + sb2;
            if(condition != null) {
                sql += " WHERE " + condition.toSqlString();
            }
            if(orders != null) {
                sql += " ORDER BY " + orders;
            }
            logger.debug(sql);
            return sql;
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
     
    /**
     * 转换连接查询结果,Map对象的key值为:对象名.属性名
     *
     * @param result
     * @param classLink
     * 创建日期:2012-10-19
     * 修改说明:
     * @author wangk
     */
    private void convertJoinResult(List<Map<String, Object>> result, Class<?>... classLink) throws DaoAccessException {
        if(CollectionUtils.isEmpty(result)) {
            return;
        }
        for (Map<String, Object> map : result) {
            try {
                for (Class<?> clazz : classLink) {
                    @SuppressWarnings({ "rawtypes", "unchecked" })
                    SimpleSqlBuilder<? extends Entity> sqlBuilder = new SimpleSqlBuilder(clazz);
                    String tableName = sqlBuilder.getTableName();
                    Map<String, String> fieldColumnMapping = sqlBuilder.getFieldColumnMapping();
                    String className = clazz.getSimpleName();
                    String variableName = className.substring(0, 1).toLowerCase() + className.substring(1);
                    for (String field : fieldColumnMapping.keySet()) {
                        map.put(variableName + "." + field, map.remove(tableName + "_" + fieldColumnMapping.get(field)));
                    }
                }
            } catch (Exception e) {
                throw new DaoAccessException(e);
            }
        }
    }
 
}

3. [代码]EntityDao     跳至 [1] [2] [3] [4] [全屏预览]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
package com.zjhc.commons.db.dao;
 
import java.util.List;
import java.util.Map;
 
import com.zjhc.commons.db.Entity;
import com.zjhc.commons.domain.condition.Condition;
import com.zjhc.commons.domain.model.DataStore;
import com.zjhc.commons.domain.model.PagingParameter;
import com.zjhc.commons.exception.DaoAccessException;
 
/**
 * 实体类DAO接口
 *
 * 创建日期:2012-9-24
 * @author wangk
 */
public interface EntityDao<E extends Entity> extends BaseDao {
     
    /**
     * 根据ID值获得实体对象,可选参数associationLink,如果不指定只查询单个实体对象
     * 否则使用左连接查询当前实体(左连接查询的主表)和associationLink指定的实体对象
     *
     * @param id               ID值
     * @param associationLink  <p>关联实体链,从当前实体的父表开始依次指定,必须按从子表到父表的顺序且不能间断
     *                             否则将抛出AnnotationNotFoundException
     *                             如果有多个分支,则各分支可以依次指定,各个分支之间没有顺序
     *                         </p>
     * @return E               实体对象,记录不存在时返回null
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public <K extends Number> E get(K id, Class<?>... associationLink) throws DaoAccessException;
     
    /**
     * 根据SQL语句获得实体对象,
     *
     * @param sql     SQL语句
     * @param params  查询参数
     * @return E 没有记录返回null, 仅有一条记录返回实体对象,否则抛出DuplicatedRecordException
     *            如果SQL语句指定了查询列,则返回的实体对象只有相应的属性有值,其他为null
     * 创建日期:2012-9-26
     * 修改说明:
     * @author wangk
     */
    public E get(String sql, Object... params) throws DaoAccessException;
    public E get(String sql, List<Object> params) throws DaoAccessException;
    public E get(String sql, Map<String, Object> params) throws DaoAccessException;
     
    /**
     * 根据Condition对象获得实体对象
     *
     * @param condition       <p>条件对象,条件出现的列如果没有指定所属表则默认为当前实体对应的表
     *                        associationLink中的实体的列必须带所属表前缀,其格式为:表名.列名
     *                          如果associationLink中有相同的实体(包括和当前实体相同)
     *                          则相同的实体必须在表名后加上实体序号后缀(第一个实体除外),其格式为:表名_序号.列名
     *                          当前实体的序号为0,associationLink中的第一个实体的序号为1,依次类推
     *                          如果associationLink中的实体对应的表名以‘_数字’结尾则指定列的所属表时必须加实体序号后缀
     *                        </p>
     * @param associationLink 关联实体链,参数说明请参考get(id, associationLink)
     * @return E
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public E get(Condition condition, Class<?>... associationLink) throws DaoAccessException;
     
    /**
     * 通过ID值删除记录
     *
     * @param id
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public <K extends Number> void delete(K id) throws DaoAccessException;
 
    /**
     * 新增记录(不指定ID值,ID值由数据库生成)
     *
     * @param <K>     ID属性的类型参数
     * @param entity  新增记录的实体对象,其ID属性值必须为空,否则将抛出DuplicateRecordException
     * @return K      数据库生成的ID值,接收返回值的变量类型必须和ID属性的类型相同,否则将抛出ClassCastException
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public <K extends Number> K save(E entity) throws DaoAccessException;
     
    /**
     * 新增记录(指定ID值)
     *
     * @param <K>    ID属性的类型参数
     * @param entity 新增记录的实体对象,其ID属性值必须为空,否则将抛出DuplicateRecordException
     * @param id     ID值,如果指定的ID值为null,则ID值由数据库生成
     * 创建日期:2012-12-7
     * 修改说明:
     * @author wangk
     */
    public <K extends Number> void save(E entity, K id) throws DaoAccessException;
 
    /**
     * 更新记录
     *
     * @param entity
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public void update(E entity) throws DaoAccessException;
 
    /**
     * 新增或更新记录,ID值为空做新增操作,ID值非空做更新操作
     *
     * @param entity
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public void saveOrUpdate(E entity) throws DaoAccessException;
 
    /**
     * 根据SQL语句查询记录
     *
     * @param sql       SQL语句,可以只是WHERE子句,为null或空字符串时表时查询全部记录
     * @param params    SQL参数
     * @return List<E>  实体集合,若SQL语句指定了查询列,则实体对象中没有被指定列对应的属性为空值
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public List<E> query(String sql, Object... params) throws DaoAccessException;
    public List<E> query(String sql, List<Object> params) throws DaoAccessException;
    public List<E> query(String sql, Map<String, Object> params) throws DaoAccessException;
     
    /**
     * 根据Condition对象查询记录
     *
     * @param condition        参数说明请参考get(condition, associationLink)
     * @param associationLink
     * @return
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public List<E> query(Condition condition, Class<?>... associationLink) throws DaoAccessException;
    public List<E> query(Condition condition, String orders, Class<?>... associationLink) throws DaoAccessException;
     
    /**
     * 根据SQL语句和分页参数查询记录
     *
     * @param sql           参数说明请参考query(sql, params)
     * @param paging
     * @param params
     * @return DataStore<E> 分页数据
     * 创建日期:2012-9-26
     * 修改说明:
     * @author wangk
     */
    public DataStore<E> query(String sql, PagingParameter paging, Object... params) throws DaoAccessException;
    public DataStore<E> query(String sql, PagingParameter paging, List<Object> params) throws DaoAccessException;
    public DataStore<E> query(String sql, PagingParameter paging, Map<String, Object> params) throws DaoAccessException;
     
    /**
     * 根据Condition对象和分页参数查询记录
     *
     * @param condition   参数说明请参考get(condition, associationLink)
     * @param paging
     * @return
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public DataStore<E> query(Condition condition, PagingParameter paging, Class<?>... associationLink) throws DaoAccessException;
    public DataStore<E> query(Condition condition, String orders, PagingParameter paging, Class<?>... associationLink) throws DaoAccessException;
     
    /**
     * 查询表里的所有记录
     *
     * @param associationLink  参数说明请参考get(condition, associationLink)
     * @return
     * 创建日期:2012-10-20
     * 修改说明:
     * @author wangk
     */
    public List<E> queryAll(Class<?>... associationLink) throws DaoAccessException;
    public List<E> queryAll(String orders, Class<?>... associationLink) throws DaoAccessException;
     
    /**
     * 分页查询表里的所有记录
     *
     * @param paging
     * @return
     * 创建日期:2012-10-20
     * 修改说明:
     * @author wangk
     */
    public DataStore<E> queryAll(PagingParameter paging, Class<?>... associationLink) throws DaoAccessException;
    public DataStore<E> queryAll(String orders, PagingParameter paging, Class<?>... associationLink) throws DaoAccessException;
     
    /**
     * 计算表里的记录数
     *
     * @return
     * 创建日期:2012-10-20
     * 修改说明:
     * @author wangk
     */
    public int count() throws DaoAccessException;
    public int count(Condition condition) throws DaoAccessException;
     
    /**
     * 批量删除
     *
     * @param ids
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public <K extends Number> void deletes(List<K> ids) throws DaoAccessException;
     
    /**
     * 批量新增
     *
     * @param <K>      ID属性类型参数
     * @param entitys  实体集合,各个对象的ID值必须为空,否则将抛出DuplicateRecordException
     * @param ids      指定ID集合,entitys的前ids.length个对象通过指定的ID值新增,其他的对象ID值由数据库生成
     * @return
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public <K extends Number> void saves(List<E> entitys, K... ids) throws DaoAccessException;
 
    /**
     * 批量更新
     *
     * @param entitys
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public void updates(List<E> entitys) throws DaoAccessException;
 
    /**
     * 批量新增或更新
     *
     * @param entitys
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public void saveOrUpdates(List<E> entitys) throws DaoAccessException;
 
    /**
     * 获得实体对象的被引用对象,被引用对象类型和E的类型相同
     *  例:获得某一地区的上一级地区
     *
     * @param entity     实体对象
     * @return E         被引用对象
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public E getReferenced(E entity) throws DaoAccessException;
    public E getReferenced(Object referenceValue) throws DaoAccessException;
     
    /**
     * 获得实体对象的被引用对象
     *
     * @param <R>              被引用对象参数
     * @param entity           实体对象
     * @param referencedClass  被引用对象类型
     * @return R               被引用对象
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public <R extends Entity> R getReferenced(E entity, Class<R> referencedClass) throws DaoAccessException;
    public <R extends Entity> R getReferenced(Object referenceValue, Class<R> referencedClass) throws DaoAccessException;
      
    /**
     * 查询被引用对象的所有引用对象,引用对象类型为E
     * (R可以和E相同,例:查询某一地区的所有下一级地区)
     *
     * @param <R>         被引用对象参数
     * @param referenced  被引用对象
     * @return List<E>    引用对象集合
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public <R extends Entity> List<E> queryReferences(R referenced) throws DaoAccessException;
    public <R extends Entity> List<E> queryReferences(Class<R> referencedClass, Object referencedValue) throws DaoAccessException;
 
    /**
     * 查询被引用对象的所有引用对象,引用对象类型由referenceClass指定
     * (应用于关联表的DAO中)
     *
     * @param <R>            被引用对象参数
     * @param <S>            引用对象参数
     * @param referenced     被引用对象
     * @param referenceClass 引用对象类型
     * @return List<S>       引用对象集合
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public <R extends Entity, S extends Entity> List<S> queryReferences(R referenced, Class<S> referenceClass) throws DaoAccessException;
    public <R extends Entity, S extends Entity> List<S> queryReferences(Class<R> referencedClass, Object referencedValue, Class<S> referenceClass) throws DaoAccessException;
     
    /**
     * 查询被引用对象的引用对象分页数据,引用对象类型为E
     *
     * @param <R>           被引用对象参数
     * @param referenced    被引用对象
     * @param paging        分页参数
     * @return DataStore<E> 引用对象分页数据
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public <R extends Entity> DataStore<E> queryReferences(R referenced, PagingParameter paging) throws DaoAccessException;
    public <R extends Entity> DataStore<E> queryReferences(Class<R> referencedClass, Object referencedValue, PagingParameter paging) throws DaoAccessException;
     
    /**
     * 查询被引用对象的引用对象分页数据,引用对象类型由referenceClass指定
     * (应用于关联表的DAO中)
     *
     * @param <R>             被引用对象参数
     * @param <S>             引用对象参数
     * @param referenced      被引用对象
     * @param referenceClass  引用对象类型
     * @param paging          分页参数
     * @return DataStore<S>   引用对象分页数据
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public <R extends Entity, S extends Entity> DataStore<S> queryReferences(R referenced, Class<S> referenceClass, PagingParameter paging) throws DaoAccessException;
    public <R extends Entity, S extends Entity> DataStore<S> queryReferences(Class<R> referencedClass, Object referencedValue, Class<S> referenceClass, PagingParameter paging) throws DaoAccessException;
 
}

4. [代码]EntityDaoSupport     跳至 [1] [2] [3] [4] [全屏预览]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
package com.zjhc.commons.db.dao;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
 
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
 
import com.zjhc.commons.db.Entity;
import com.zjhc.commons.db.annotation.Association;
import com.zjhc.commons.db.annotation.Reference;
import com.zjhc.commons.db.builder.SimpleSqlBuilder;
import com.zjhc.commons.db.exception.AnnotationNotFoundException;
import com.zjhc.commons.db.exception.DuplicateRecordException;
import com.zjhc.commons.db.exception.ErrorCode;
import com.zjhc.commons.db.exception.FieldColumnMappingException;
import com.zjhc.commons.db.exception.IllegalRecordException;
import com.zjhc.commons.domain.condition.Condition;
import com.zjhc.commons.domain.model.DataStore;
import com.zjhc.commons.domain.model.PagingParameter;
import com.zjhc.commons.exception.DaoAccessException;
import com.zjhc.commons.utils.ObjectUtil;
 
/**
 * 实体Dao支持类
 *
 * 创建日期:2012-9-24
 * @author wangk
 */
public abstract class EntityDaoSupport<E extends Entity> extends BaseDaoSupport implements EntityDao<E> {
    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(BaseDaoSupport.class);
    /** 条件关键字集合 */
    private static final List<String> CONDITION_KEYWORDS = new ArrayList<String>();
    /** 条件运算符(正则表达式形式)集合 */
    private static final List<String> CONDITION_OPERATORS = new ArrayList<String>();
 
    static {
        /** 初始化条件关键字集合 */
        CONDITION_KEYWORDS.add("IS");
        CONDITION_KEYWORDS.add("NOT");
        CONDITION_KEYWORDS.add("NULL");
        CONDITION_KEYWORDS.add("LIKE");
        CONDITION_KEYWORDS.add("BETWEEN");
        CONDITION_KEYWORDS.add("AND");
        CONDITION_KEYWORDS.add("OR");
        CONDITION_KEYWORDS.add("IN");
        CONDITION_KEYWORDS.add("ASC");
        CONDITION_KEYWORDS.add("DESC");
        /** 初始化条件运算符集合(= < > + - * / % ( ) , ?),组合符号(<> <= >=)需要特殊处理 */
        CONDITION_OPERATORS.add("=");
        CONDITION_OPERATORS.add("<");
        CONDITION_OPERATORS.add(">");
        CONDITION_OPERATORS.add("\\+");
        CONDITION_OPERATORS.add("\\-");
        CONDITION_OPERATORS.add("\\*");
        CONDITION_OPERATORS.add("/");
        CONDITION_OPERATORS.add("%");
        CONDITION_OPERATORS.add("\\(");
        CONDITION_OPERATORS.add("\\)");
        CONDITION_OPERATORS.add("\\,");
        CONDITION_OPERATORS.add("\\?");
    }
 
    /** SQL语句构建对象 */
    protected SimpleSqlBuilder<E> simpleSqlBuilder;
    /** 实体类类型 */
    private Class<E> entityClass;
 
    /**
     * 构造方法  通过反射初始化entityClass
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    public EntityDaoSupport() {
        //获得EntityDaoSupport包含泛型实参的类型
        ParameterizedType parameterizedType =
                (ParameterizedType)getClass().getGenericSuperclass();
        Type[] params = parameterizedType.getActualTypeArguments();
        @SuppressWarnings("unchecked")
        Class<E> entityClass = (Class<E>)params[0];
        init(entityClass);
    }
 
    /**
     * 构造方法
     * @param entityClass 实体类类型
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public EntityDaoSupport(Class<E> entityClass) {
        init(entityClass);
    }
 
    /**
     * 初始化方法
     *
     * @param entityClass  实体类类型
     * 创建日期:2012-10-11
     * 修改说明:
     * @author wangk
     */
    private void init(Class<E> entityClass) {
        this.entityClass = entityClass;
        //初始化simpleSqlBuilder
        simpleSqlBuilder = new SimpleSqlBuilder<E>(entityClass);
        //检查实体所有的引用属性列是否存在和引用属性类型和被引用属性类型是否相同
        simpleSqlBuilder.checkReferenceFields();
        //检查关联属性是否存在非自身循环关联并记录debug级别日志
        for (Class<?> association : simpleSqlBuilder.getAssociationLink()) {
            logger.debug(association.getName());
        }
    }
     
    /**
     * 获得SQL语句构建对象
     *
     * @return
     * 创建日期:2012-9-25
     * 修改说明:
     * @author wangk
     */
    public SimpleSqlBuilder<E> getSimpleSqlBuilder() {
        return simpleSqlBuilder;
    }
 
    @Override
    public <K extends Number> E get(K id, Class<?>... associationLink) throws DaoAccessException {
        if(associationLink != null && associationLink.length == 0) {
            try {
                return jdbcTemplate.queryForObject(simpleSqlBuilder.getQuerySimpleSql(),
                        simpleSqlBuilder.getRowMapper(), id);
            } catch (EmptyResultDataAccessException e) {
                //只处理空结果异常,表示没有对应的记录,返回null
                logger.warn(e);
                return null;
            } catch (Exception e) {
                throw new DaoAccessException(e);
            }
        }
        return get(Condition.eq(simpleSqlBuilder.getFieldColumnMapping().get(
                simpleSqlBuilder.getIdField()), id), associationLink);
    }
     
    @Override
    public E get(String sql, Object... params) throws DaoAccessException {
        return getUniqueEntity(query(sql, params));
    }
    @Override
    public E get(String sql, List<Object> params) throws DaoAccessException {
        return get(sql, params.toArray());
    }
    @Override
    public E get(String sql, Map<String, Object> params) throws DaoAccessException {
        return getUniqueEntity(query(sql, params));
    }
     
    @Override
    public E get(Condition condition, Class<?>... associationLink) throws DaoAccessException {
        return getUniqueEntity(query(condition, associationLink));
    }
     
    @Override
    public <K extends Number> K save(E entity) throws DaoAccessException {
        return saveWithId(entity, null);
    }
 
    @Override
    public <K extends Number> void save(E entity, K id) throws DaoAccessException {
        saveWithId(entity, id);
    }
 
    @Override
    public void update(E entity) throws DaoAccessException {
        try {
            if(entity.isTransient()) {
                throw new IllegalRecordException(ErrorCode.ILLEGAL_RECORD_AS_UPDATE_TRANSIENT,
                        "The record " + entity + " is transient!");
            }
            Map<String, Object> params = simpleSqlBuilder.getSqlParameters(entity);
            namedParameterJdbcTemplate.update(simpleSqlBuilder.getUpdateSql(params.keySet()), params);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public void saveOrUpdate(E entity) throws DaoAccessException {
        if(entity.isTransient()) {
            save(entity);
        } else {
            update(entity);
        }
    }
 
    @Override
    public <K extends Number> void delete(K id) throws DaoAccessException {
        try {
            jdbcTemplate.update(simpleSqlBuilder.getDeleteSql(), id);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public List<E> query(String sql, Object... params) throws DaoAccessException {
        return query(sql, null, params).getDatas();
    }
    @Override
    public List<E> query(String sql, List<Object> params) throws DaoAccessException {
        return query(sql, params.toArray());
    }
    @Override
    public List<E> query(String sql, Map<String, Object> params) throws DaoAccessException {
        return query(sql, null, params).getDatas();
    }
     
    @Override
    public List<E> query(Condition condition, Class<?>... associationLink) throws DaoAccessException {
        String orders = null;
        return query(condition, orders, associationLink);
    }
     
    @Override
    public List<E> query(Condition condition, String orders, Class<?>... associationLink) throws DaoAccessException {
        return query(condition, orders, null, associationLink).getDatas();
    }
 
    @Override
    public DataStore<E> query(String sql, PagingParameter paging, Object... params) throws DaoAccessException {
        sql = handleSimpleSql(sql);
        return queryDataStore(sql, params, getRowMapperBySql(sql), paging);
    }
    @Override
    public DataStore<E> query(String sql, PagingParameter paging,
            List<Object> params) throws DaoAccessException {
        return query(sql, paging, params.toArray());
    }
    @Override
    public DataStore<E> query(String sql, PagingParameter paging,
            Map<String, Object> params) throws DaoAccessException {
        sql = handleSimpleSql(sql);
        return queryDataStore(sql, params, getRowMapperBySql(sql), paging);
    }
 
    @Override
    public DataStore<E> query(Condition condition, PagingParameter paging, Class<?>... associationLink) throws DaoAccessException {
        return query(condition, null, paging, associationLink);
    }
     
    @Override
    public DataStore<E> query(Condition condition, String orders, PagingParameter paging, Class<?>... associationLink) throws DaoAccessException {
        Object[] params = new Object[0];
        if(condition != null) {
            params = condition.getParameters();
        }
        if(associationLink != null && associationLink.length == 0) {
            String sql = condition==null?"":condition.toSqlString();
            if(orders == null) {
                orders = simpleSqlBuilder.getFieldColumnMapping().get(simpleSqlBuilder.getIdField());
            }
            if(!sql.equals("")) {
                sql += " ";
            }
            sql += "ORDER BY " + orders;
            return query(sql, paging, params);
        }
        return queryDataStore(buildAssociationSql(condition, orders, associationLink), params,
                simpleSqlBuilder.getRowMapper(associationLink), paging);
    }
     
    @Override
    public List<E> queryAll(Class<?>... associationLink) throws DaoAccessException {
        String orders = null;
        return queryAll(orders, associationLink);
    }
 
    @Override
    public List<E> queryAll(String orders, Class<?>... associationLink) throws DaoAccessException {
        return query(null, orders, associationLink);
    }
 
    @Override
    public DataStore<E> queryAll(PagingParameter paging, Class<?>... associationLink) throws DaoAccessException {
        return queryAll(null, paging, associationLink);
    }
 
    @Override
    public DataStore<E> queryAll(String orders, PagingParameter paging, Class<?>... associationLink) throws DaoAccessException {
        return query(null, orders, paging, associationLink);
    }
 
    @Override
    public int count() throws DaoAccessException {
        return count(null);
    }
 
    @Override
    public int count(Condition condition) throws DaoAccessException {
        try {
            String sql = simpleSqlBuilder.getQueryCountSql();
            if(condition == null) {
                return jdbcTemplate.queryForInt(sql);
            }
            sql += " WHERE " + condition.toSqlString();
            logger.debug(sql);
            return jdbcTemplate.queryForInt(sql, condition.getParameters());
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public <K extends Number> void deletes(List<K> ids) throws DaoAccessException {
        if(CollectionUtils.isEmpty(ids)) {
            return;
        }
        try {
            List<Object[]> batchArgs = new ArrayList<Object[]>();
            for (K id : ids) {
                batchArgs.add(new Object[]{id});
            }
            jdbcTemplate.batchUpdate(simpleSqlBuilder.getDeleteSql(), batchArgs);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public <K extends Number> void saves(List<E> entitys, K... ids) throws DaoAccessException {
        if(CollectionUtils.isEmpty(entitys)) {
            return;
        }
        try {
            int entityCount = entitys.size();
            int idCount = ids.length;
            if(idCount > entityCount) {
                idCount = entityCount;
            }
            List<E> withIdEntitys = entitys.subList(0, idCount);
            List<E> withoutIdEntitys = entitys.subList(idCount, entityCount);
            if(CollectionUtils.isNotEmpty(withIdEntitys)) {
                @SuppressWarnings("unchecked")
                Map<String, Object>[] batchArgs = new Map[idCount];
                for (int i = 0; i < idCount; i++) {
                    E entity = withIdEntitys.get(i);
                    if(!entity.isTransient()) {
                        throw new DuplicateRecordException(ErrorCode.DUPLICATE_RECORDE_AS_SAVE_ENTITY,
                                "The record that whoes id equals " + entity.identityString() + " is already exist!");
                    }
                    batchArgs[i] = simpleSqlBuilder.getAllSqlParameter(entity);
                    batchArgs[i].put(simpleSqlBuilder.getIdField(), ids[i]);
                }
                namedParameterJdbcTemplate.batchUpdate(simpleSqlBuilder.getIncludeIdFieldInsertSql(), batchArgs);
            }
            if(CollectionUtils.isNotEmpty(withoutIdEntitys)) {
                @SuppressWarnings("unchecked")
                Map<String, Object>[] batchArgs = new Map[withoutIdEntitys.size()];
                for (int i = 0; i < batchArgs.length; i++) {
                    E entity = withoutIdEntitys.get(i);
                    if(!entity.isTransient()) {
                        throw new DuplicateRecordException(ErrorCode.DUPLICATE_RECORDE_AS_SAVE_ENTITY,
                                "The record that whoes id equals " + entity.identityString() + " is already exist!");
                    }
                    batchArgs[i] = simpleSqlBuilder.getAllSqlParameter(entity);
                }
                namedParameterJdbcTemplate.batchUpdate(simpleSqlBuilder.getInsertSql(), batchArgs);
            }
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public void updates(List<E> entitys) throws DaoAccessException {
        if(CollectionUtils.isEmpty(entitys)) {
            return;
        }
        try {
            @SuppressWarnings("unchecked")
            Map<String, Object>[] batchArgs = new Map[entitys.size()];
            for (int i = 0; i < batchArgs.length; i++) {
                E entity = entitys.get(i);
                if(entity.isTransient()) {
                    throw new IllegalRecordException(ErrorCode.ILLEGAL_RECORD_AS_UPDATE_TRANSIENT,
                            "The record " + entity + " is transient!");
                }
                batchArgs[i] = simpleSqlBuilder.getAllSqlParameter(entity);
            }
            namedParameterJdbcTemplate.batchUpdate(simpleSqlBuilder.getUpdateSql(), batchArgs);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    @Override
    public void saveOrUpdates(List<E> entitys) throws DaoAccessException {
        if(CollectionUtils.isEmpty(entitys)) {
            return;
        }
        List<E> saves = new ArrayList<E>();
        List<E> updates = new ArrayList<E>();
        for (E entity : entitys) {
            if(entity.isTransient()) {
                saves.add(entity);
            } else {
                updates.add(entity);
            }
        }
        saves(saves);
        updates(updates);
    }
 
    @Override
    public E getReferenced(E entity) throws DaoAccessException {
        return getReferenced(entity, entityClass);
    }
 
    @Override
    public E getReferenced(Object referenceValue) throws DaoAccessException {
        return getReferenced(referenceValue, entityClass);
    }
     
    @Override
    public <R extends Entity> R getReferenced(E entity, Class<R> referencedClass) throws DaoAccessException {
        Object value = null;
        try {
            String field = simpleSqlBuilder.getReferenceField(referencedClass);
            if(field == null) {
                throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_REFERENCE,
                        "Annotation " + Reference.class.getName() + " not found for referenced " +
                        referencedClass.getName() + " of " + entityClass.getName());
            }
            value = new PropertyDescriptor(field, entityClass).getReadMethod().invoke(entity);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
        if(value == null) {
            return null;
        }
        return getReferenced(value, referencedClass);
    }
 
    @Override
    public <R extends Entity> R getReferenced(Object referenceValue,
            Class<R> referencedClass) throws DaoAccessException {
        try {
            String referencedColumn = simpleSqlBuilder.getReferencedColumn(referencedClass);
            if(referencedColumn == null) {
                throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_REFERENCE,
                        "Annotation " + Reference.class.getName() + " not found for referenced " +
                        referencedClass.getName() + " of " + entityClass.getName());
            }
            SimpleSqlBuilder<R> referencedSqlBuilder = new SimpleSqlBuilder<R>(referencedClass);
            String sql = referencedSqlBuilder.getQueryAllSql() + " WHERE " + referencedColumn + " = ?";
            logger.debug(sql);
            return jdbcTemplate.queryForObject(sql, referencedSqlBuilder.getRowMapper(), referenceValue);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
     
    @Override
    public <R extends Entity> List<E> queryReferences(R referenced) throws DaoAccessException {
        PagingParameter paging = null;
        return queryReferences(referenced, paging).getDatas();
    }
 
    @Override
    public <R extends Entity> List<E> queryReferences(Class<R> referencedClass, Object referencedValue) throws DaoAccessException {
        PagingParameter paging = null;
        return queryReferences(referencedClass, referencedValue, paging).getDatas();
    }
     
    @Override
    public <R extends Entity, S extends Entity> List<S> queryReferences(
            R referenced, Class<S> referenceClass) throws DaoAccessException {
        return queryReferences(referenced, referenceClass, null).getDatas();
    }
 
    @Override
    public <R extends Entity, S extends Entity> List<S> queryReferences(
            Class<R> referencedClass, Object referencedValue,
            Class<S> referenceClass) throws DaoAccessException {
        return queryReferences(referencedClass, referencedValue, referenceClass, null).getDatas();
    }
     
    @Override
    public <R extends Entity> DataStore<E> queryReferences(R referenced,
            PagingParameter paging) throws DaoAccessException {
        Object value = getReferencedValue(referenced);
        if(value == null) {
            return null;
        }
        return queryReferences(referenced.getClass(), value, paging);
    }
 
    @Override
    public <R extends Entity> DataStore<E> queryReferences(
            Class<R> referencedClass, Object referencedValue,
            PagingParameter paging) throws DaoAccessException {
        String sql = null;
        try {
            String field = simpleSqlBuilder.getReferenceField(referencedClass);
            if(field == null) {
                throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_REFERENCE,
                        "Annotation " + Reference.class.getName() + " not found for referenced " +
                        referencedClass.getName() + " of " + entityClass.getName());
            }
            sql = simpleSqlBuilder.getQueryAllSql() + " WHERE " +
            simpleSqlBuilder.getFieldColumnMapping().get(field) + " = ? ORDER BY " +
            simpleSqlBuilder.getFieldColumnMapping().get(simpleSqlBuilder.getIdField());
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
        return queryDataStore(sql, new Object[]{referencedValue}, simpleSqlBuilder.getRowMapper(), paging);
    }
     
    @Override
    public <R extends Entity, S extends Entity> DataStore<S> queryReferences(
            R referenced, Class<S> referenceClass, PagingParameter paging) throws DaoAccessException {
        Object value = getReferencedValue(referenced);
        if(value == null) {
            return null;
        }
        return queryReferences(referenced.getClass(), value, referenceClass, paging);
    }
 
    @Override
    public <R extends Entity, S extends Entity> DataStore<S> queryReferences(
            Class<R> referencedClass, Object referencedValue,
            Class<S> referenceClass, PagingParameter paging) throws DaoAccessException {
        String sql = null;
        SimpleSqlBuilder<S> referenceSqlBuilder = null;
        try {
            String referencedColumn = simpleSqlBuilder.getReferencedColumn(referenceClass);
            if(referencedColumn == null) {
                throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_REFERENCE,
                        "Annotation " + Reference.class.getName() + " not found for referenced " +
                        referenceClass.getName() + " of " + entityClass.getName());
            }
            String field = simpleSqlBuilder.getReferenceField(referencedClass);
            if(field == null) {
                throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_REFERENCE,
                        "Annotation " + Reference.class.getName() + " not found for referenced " +
                        referencedClass.getName() + " of " + entityClass.getName());
            }
            referenceSqlBuilder = new SimpleSqlBuilder<S>(referenceClass);
            sql = referenceSqlBuilder.getQueryAllSql() + " WHERE " + referencedColumn + " IN (SELECT " +
                    simpleSqlBuilder.getFieldColumnMapping().get(simpleSqlBuilder.getReferenceField(referenceClass)) +
                    " FROM " + simpleSqlBuilder.getTableName() + " WHERE " +
                    simpleSqlBuilder.getFieldColumnMapping().get(field) + " = ?) ORDER BY " +
                    referenceSqlBuilder.getFieldColumnMapping().get(referenceSqlBuilder.getIdField());
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
        return queryDataStore(sql, new Object[]{referencedValue}, referenceSqlBuilder.getRowMapper(), paging);
    }
 
    /**
     * 根据被引用对象获得外键属性值
     *
     * @param <R>
     * @param referenced
     * @return
     * 创建日期:2012-10-8
     * 修改说明:
     * @author wangk
     */
    private <R extends Entity> Object getReferencedValue(R referenced) throws DaoAccessException {
        try {
            @SuppressWarnings("unchecked")
            Class<R> referencedClass = (Class<R>)referenced.getClass();
            String referencedColumn = simpleSqlBuilder.getReferencedColumn(referencedClass);
            if(referencedColumn == null) {
                throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_REFERENCE,
                        "Annotation " + Reference.class.getName() + " not found for referenced " +
                        referencedClass.getName() + " of " + entityClass.getName());
            }
            SimpleSqlBuilder<R> referencedSqlBuilder = new SimpleSqlBuilder<R>(referencedClass);
            String columnField = referencedSqlBuilder.getColumnField(referencedColumn);
            if(columnField == null) {
                throw new FieldColumnMappingException(ErrorCode.FIELD_COLUMN_MAPPING_AS_NOT_EXIST_COLUMN,
                        "ColumnName " + referencedColumn + " not exist for " + referencedClass.getName());
            }
            return new PropertyDescriptor(columnField, referencedClass).getReadMethod().invoke(referenced);
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    /**
     * 构建关联查询SQL语句
     *
     * @param condition       查询条件
     * @param orders          排序对象
     * @param associationLink 关联链
     * @return String         关联查询SQL语句
     * 创建日期:2012-12-5
     * 修改说明:
     * @author wangk
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private String buildAssociationSql(Condition condition, String orders, Class<?>[] associationLink) throws DaoAccessException {
        try {
            if(associationLink == null) {
                associationLink = simpleSqlBuilder.getAssociationLink();
            }
            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            String tableName = simpleSqlBuilder.getTableName() + "_0";
            Map<String, String> fieldColumnMapping = simpleSqlBuilder.getFieldColumnMapping();
            for (String field : fieldColumnMapping.keySet()) {
                sb1.append(tableName +  "." + fieldColumnMapping.get(field) + " AS " +
                        tableName +  "_" + fieldColumnMapping.get(field) + ", ");
            }
            sb2.append(simpleSqlBuilder.getTableName()).append(" AS ").append(tableName);
            //关联类型三标志(被关联类型下标、被关联类型、关联类型)集合
            List<List<Object>> associationFlags = new ArrayList<List<Object>>();
            for (int i = 0;i < associationLink.length;i++) {
                Class<?> tempClass = associationLink[i];
                if(!ObjectUtil.isExtends(tempClass, Entity.class)) {
                    throw new FieldColumnMappingException(ErrorCode.FIELD_COLUMN_MAPPING_AS_ASSOCIATION_TYPE_ERROR,
                            "Association " + tempClass.getName() + " type error for " +
                            entityClass.getName() + ", the type must extends Entity!");
                }
                Class<? extends Entity> associationClass = (Class<? extends Entity>)tempClass;
                SimpleSqlBuilder<? extends Entity> associationSqlBuilder = new SimpleSqlBuilder(associationClass);
                Class<? extends Entity> clazz = null;
                SimpleSqlBuilder<? extends Entity> sqlBuilder = null;
                int j = -1;
                for (; j < i; j++) {
                    if(j >= 0) {
                        clazz = (Class<? extends Entity>)associationLink[j];
                    } else {
                        clazz = entityClass;
                    }
                    sqlBuilder = new SimpleSqlBuilder(clazz);
                    if(sqlBuilder.getAssociationField(associationClass) != null) {
                        List<Object> associationFlag = new ArrayList<Object>();
                        associationFlag.add(j + 1);
                        associationFlag.add(clazz);
                        associationFlag.add(associationClass);
                        if(!associationFlags.contains(associationFlag)) {
                            //检查指定的关联类型对应的引用属性是否存在
                            sqlBuilder.checkExistReferenceField(associationClass);
                            associationFlags.add(associationFlag);
                            break;
                        }
                    }
                }
                if(j == i) {
                    throw new AnnotationNotFoundException(ErrorCode.ANNOTATION_NOT_FOUND_AS_ASSOCIATION,
                            "Annotation " + Association.class.getName() + " not found for association " +
                            associationClass.getName() + " of " + entityClass.getName());
                }
                String tableName2 = associationSqlBuilder.getTableName() + "_" + (i + 1);
                Map<String, String> fieldColumnMapping2 = associationSqlBuilder.getFieldColumnMapping();
                for (String field : fieldColumnMapping2.keySet()) {
                    sb1.append(tableName2 +  "." + fieldColumnMapping2.get(field) + " AS " +
                            tableName2 +  "_" + fieldColumnMapping2.get(field) + ", ");
                }
                String tableName1 = sqlBuilder.getTableName() + "_" + (j + 1);
                Map<String, String> fieldColumnMapping1 = sqlBuilder.getFieldColumnMapping();
                sb2.append(" LEFT JOIN " + associationSqlBuilder.getTableName() + " AS " + tableName2 + " ON " + tableName1 + "." +
                        fieldColumnMapping1.get(sqlBuilder.getReferenceField(associationClass)) +
                        " = " + tableName2 + "." + sqlBuilder.getReferencedColumn(associationClass));
            }
            sb1.delete(sb1.length() - 2, sb1.length());
            String sql = "SELECT " + sb1 + " FROM " + sb2;
            if(condition != null) {
                sql += " WHERE " + handleSqlColumnPrefix(condition.toSqlString(), associationLink);
            }
            if(orders == null) {
                orders = simpleSqlBuilder.getFieldColumnMapping().get(simpleSqlBuilder.getIdField());
            }
            sql += " ORDER BY " + handleSqlColumnPrefix(orders, associationLink);
            logger.debug(sql);
            return sql;
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
    /**
     * 处理SQL子句的列名前缀,以区分来自不同的表
     *  1. 没有前缀则加上:entityClass#tableName_0.
     *  2. 有前缀但没有下标则加上下标,如entityClass#tableName.处理成entityClass#tableName_0.
     *     (关联链中有两个相同的类型时如果没有下标则加上第一次出现的下标,要指定后面类型的列必须带下标)
     *  3. entityClass下标为0,associationLink的第一个元素下标为1,依次类批(即数组下标加一)
     *  4. 出现的表名不能以'_数字'结尾
     *
     * @param sql              条件SQL语句
     * @param associationLink  关联链
     * @return
     * 创建日期:2012-12-5
     * 修改说明:
     * @author wangk
     */
    private String handleSqlColumnPrefix(String sql, Class<?>[] associationLink) {
        if(sql == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        int start = 0;
        int end = 0;
        for (int i = 0; i < sql.length(); i++) {
            char ch = sql.charAt(i);
            if(ch == '\'') {
                end = i;
                sb.append(handleSubSqlColumnPrefix(sql.substring(start, end), associationLink));
                start = end;
                for (i++; i < sql.length(); i++) {
                    if(sql.charAt(i) == ch) {
                        end = i + 1;
                        sb.append(sql.substring(start, end));
                        start = end;
                        break;
                    }
                }
            } else if(ch == '(' && sql.substring(i+1).trim().toUpperCase().startsWith("SELECT")) {
                end = i;
                sb.append(handleSubSqlColumnPrefix(sql.substring(start, end), associationLink));
                start = end;
                Stack<Character> stack = new Stack<Character>();
                stack.push(ch);
                for (i++; i < sql.length(); i++) {
                    char ch2 = sql.charAt(i);
                    if(ch2 == ch) {
                        stack.push(ch);
                    } else if(ch2 == ')') {
                        stack.pop();
                    }
                    if(stack.isEmpty()) {
                        end = i + 1;
                        sb.append(sql.substring(start, end));
                        start = end;
                        break;
                    }
                }
            }
        }
        end = sql.length();
        sb.append(handleSubSqlColumnPrefix(sql.substring(start, end), associationLink));
        return sb.toString().trim();
    }
 
    /**
     * 处理一段SQL子句的列名前缀,不包含子查询和字符串数据
     *
     * @param subSql          一段SQL子句
     * @param associationLink 关联链
     * @return String         处理结果,结尾带空格
     * 创建日期:2012-12-6
     * 修改说明:
     * @author wangk
     */
    private String handleSubSqlColumnPrefix(String subSql, Class<?>[] associationLink) {
        //处理组合符号(= -> #, < -> @, > -> &)
        subSql = subSql.replaceAll("\\s*<>\\s*", " @& ").replaceAll("\\s*<=\\s*", " @# ").replaceAll("\\s*>=\\s*", " &# ");
        for (String operator : CONDITION_OPERATORS) {
            //处理单个符号
            subSql = subSql.replaceAll("\\s*" + operator + "\\s*", " " + operator + " ");
        }
        subSql = subSql.replaceAll("@&", "<>").replaceAll("@#", "<=").replaceAll("&#", ">=");
        String[] strings = subSql.split("\\s+");
        StringBuilder sb = new StringBuilder();
        for (String string : strings) {
            if(string.matches("^[A-Za-z_][\\w]*(\\.\\w+)?$") && !CONDITION_KEYWORDS.contains(string.toUpperCase())) {
                sb.append(handleColumnPrefix(string, associationLink));
            } else {
                sb.append(string);
            }
            sb.append(" ");
        }
        return sb.toString();
    }
     
    /**
     * 处理列名前缀
     *
     * @param column           列名
     * @param associationLink  关联链
     * @return String          带前缀的列名
     * 创建日期:2012-12-5
     * 修改说明:
     * @author wangk
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private String handleColumnPrefix(String column, Class<?>[] associationLink) {
        if(column.indexOf(".") < 0) {
            return simpleSqlBuilder.getTableName() + "_0." + column;
        }
        String[] strings = column.split("\\.");
        String tableName = strings[0];
        if(!tableName.matches("^.*_\\d+$")) {
            int index = 0;
            if(!tableName.equalsIgnoreCase(simpleSqlBuilder.getTableName())) {
                int i = 0;
                for (; i < associationLink.length; i++) {
                    if(tableName.equalsIgnoreCase(new SimpleSqlBuilder(associationLink[i]).getTableName())) {
                        break;
                    }
                }
                index = i + 1;
            }
            return tableName + "_" + index + "." + strings[1];
        }
        return column;
    }
 
    /**
     * 获得指定entitys的唯一实体对象,没有返回null,两个及以上抛出DuplicateRecordException
     *
     * @param entitys    实体集合
     * @return
     * 创建日期:2012-12-6
     * 修改说明:
     * @author wangk
     */
    private E getUniqueEntity(List<E> entitys) {
        if(CollectionUtils.isEmpty(entitys)) {
            return null;
        }
        if(entitys.size() == 1) {
            return entitys.get(0);
        }
        throw new DuplicateRecordException(ErrorCode.DUPLICATE_RECORDE_AS_GET_ENTITY);
    }
 
    /**
     * 保存实体对象,ID值由参数指定,如果ID指定为null则由数据库生成
     *
     * @param <K>     ID类型参数
     * @param entity  实体对象
     * @param id      ID值
     * @return
     * 创建日期:2012-12-3
     * 修改说明:
     * @author wangk
     */
    private <K extends Number> K saveWithId(E entity, K id) throws DaoAccessException {
        try {
            if(!entity.isTransient()) {
                throw new DuplicateRecordException(ErrorCode.DUPLICATE_RECORDE_AS_SAVE_ENTITY,
                        "The record " + entity + " is exist!");
            }
            @SuppressWarnings("unchecked")
            Class<K> idFieldType = (Class<K>)new PropertyDescriptor(simpleSqlBuilder.getIdField(), entityClass).getPropertyType();
            Map<String, Object> params = simpleSqlBuilder.getSqlParameters(entity);
            if(id == null) {
                String sql = simpleSqlBuilder.getInsertSql(params.keySet());
                KeyHolder keyHolder = new GeneratedKeyHolder();
                namedParameterJdbcTemplate.update(sql, new MapSqlParameterSource(params), keyHolder);
                id = idFieldType.getConstructor(String.class).newInstance(keyHolder.getKey().toString());
            } else {
                params.put(simpleSqlBuilder.getIdField(), id);
                String sql = simpleSqlBuilder.getIncludeIdFieldInsertSql(params.keySet());
                namedParameterJdbcTemplate.update(sql, params);
            }
            //设置entity的ID值
            new PropertyDescriptor(simpleSqlBuilder.getIdField(), entityClass).getWriteMethod().invoke(entity, id);
            return id;
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
     
    /**
     * 处理单表查询的SQL语句,SQL为null或空字符串或只指定WHERE子句时处理成查询全部记录
     *
     * @param sql       SQL语句
     * @return String   处理后的SQL语句
     * 创建日期:2012-12-6
     * 修改说明:
     * @author wangk
     */
    private String handleSimpleSql(String sql) {
        if(StringUtils.isBlank(sql)) {
            sql = simpleSqlBuilder.getQueryAllSql();
        } else if(!sql.trim().toUpperCase().startsWith("SELECT")) {
            if(!sql.trim().toUpperCase().startsWith("WHERE") && !sql.trim().toUpperCase().startsWith("ORDER")) {
                sql = "WHERE " + sql;
            }
            sql = simpleSqlBuilder.getQueryAllSql() + " " + sql;
        }
        logger.debug(sql);
        return sql;
    }
     
    /**
     * 根据SQL语句获取不同的RowMapper,如果指定了投影列则只映射指定列对应的属性,其他属性为null,否则映射全部属性
     *
     * @param sql           SQL语句
     * @return RowMapper<E> 记录映射对象
     * 创建日期:2012-12-6
     * 修改说明:
     * @author wangk
     */
    private RowMapper<E> getRowMapperBySql(String sql) {
        sql = sql.trim().toUpperCase();
        String projection = sql.substring(sql.indexOf("SELECT")+6, sql.indexOf("FROM")).trim();
        if(projection.indexOf("*") >=0) {
            return simpleSqlBuilder.getRowMapper();
        }
        Set<String> columns = new HashSet<String>();
        for (String column : projection.split(",")) {
            columns.add(column.trim().replaceAll("\\s.*$", ""));
        }
        return simpleSqlBuilder.getRowMapper(columns);
    }
 
    /**
     * 查询分页数据,如果指定的paging为null或参数不正确则查询出全部的数据
     *
     * @param <T>           SQL参数类型,限制只能使用Object[]或Map<String, Object>
     * @param sql           SQL语句
     * @param params        SQL参数
     * @param rowMapper     记录映射对象
     * @param paging        分页参数
     * @return DataStore<E> 分页数据
     * @throws DaoAccessException DAO访问异常
     * 创建日期:2012-12-6
     * 修改说明:
     * @author wangk
     */
    @SuppressWarnings("unchecked")
    private <P, S extends Entity> DataStore<S> queryDataStore(
            String sql, P params, RowMapper<S> rowMapper, PagingParameter paging) throws DaoAccessException {
        try {
            if(paging == null || paging.isInvalid()) {
                if(params instanceof Map) {
                    return new DataStore<S>(paging, namedParameterJdbcTemplate.query(sql, new MapSqlParameterSource((Map<String, Object>)params), rowMapper));
                }
                return new DataStore<S>(paging, jdbcTemplate.query(sql, rowMapper, (Object[])params));
            }
            int records = 0;
            if(params instanceof Map) {
                records = namedParameterJdbcTemplate.queryForInt(pagingSqlBuilder.getCountSql(sql), (Map<String, Object>)params);
            } else {
                records = jdbcTemplate.queryForInt(pagingSqlBuilder.getCountSql(sql), (Object[])params);
            }
            if(records < 0) {
                return null;
            }
            if(records == 0) {
                return new DataStore<S>(records, new ArrayList<S>());
            }
            if(params instanceof Map) {
                return new DataStore<S>(records, namedParameterJdbcTemplate.query(
                        pagingSqlBuilder.getPagingSql(sql, paging), new MapSqlParameterSource((Map<String, Object>)params), rowMapper));
            }
            return new DataStore<S>(records, jdbcTemplate.query(pagingSqlBuilder.getPagingSql(sql, paging), rowMapper, (Object[])params));
        } catch (Exception e) {
            throw new DaoAccessException(e);
        }
    }
 
}

5. [文件] commons.zip ~ 105KB     下载(886)     [全屏预览]

6. [文件] entityapp.zip ~ 825KB     下载(868)     [全屏预览]

posted @ 2018-01-04 10:24  星朝  阅读(425)  评论(0编辑  收藏  举报