maven项目配置mybatis的一些问题记录

1、maven项目mybatis依赖包配置(使用3.3.0版本的mybatis)

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>

2、mybatis配置文件

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases><!-- 别名配置,对应项目中的实体类,在sql.xml中可以直接使用别名对应到实体类 -->
<typeAlias alias="User" type="com.test.domain.User" />
</typeAliases>
<environments default="development"><!-- 数据库环境配置 -->
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED"><!-- 这种数据源的实现利用“池”的概念将JDBC连接对象组织起来, 避免了创建先的连接实例时所必须的初始化和认证时间。
这是一种使得并发WEb应用快速响应请求的流行的处理方式。 UNPOOLED - 这个数据源的实现只是每次请求时打开和关闭连接。 -->
<property name="driver" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://192.168.1.69:5432/li_db" />
<property name="username" value="dbuser" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 通过resource加载单个映射文件 -->
<mappers>
<mapper resource="com/unionbon/youlb/http/mapping/Base.xml" />
<mapper resource="com/unionbon/youlb/http/mapping/User.xml" />
</mappers>
<!-- 需要将mapper接口类名和mapper.xml映射文件名称保持一致且在同一个目录中, 注意:要使用的是mapper代理。两个文件要在同一个目录 -->
<!-- <mappers>
<mapper class="com.test.mapping.UserMapper" />
</mappers> -->
<!-- 需要将mapper接口类名和mapper.xml映射文件名称保持一致且在同一个目录中, 注意:要使用的是mapper代理。两个文件要在同一个目录 -->
<!-- <mappers>
<package name="com.test.mapping" />
</mappers> -->
</configuration>

文件为xml格式文件,可以直接放在maven项目的src/main/resources,这样读取的时候比较方便,
configuration节点里面的子节点是有顺序的,例如:mappers不能放在typeAliases前面,
子节点如果顺序有误,会报错,可将鼠标放在报错位置查看正确的子节点顺序。


3、读取mybatis配置文件,获取SqlSession

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void main(String[] args){
SqlSessionFactory sqlSessionFactory = null;
SqlSession session = null;
String resource = "Configuration.xml";//配置文件所在路径
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream(resource); //获取文件流
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //建立SqlSessionFactory则只需要启动项目初始化一次就行。
session = sqlSessionFactory.openSession(); //获取SqlSession都是线程不安全的,
System.out.println(session);
User user = (User)session.selectOne("cn.bj.mybatis.models.UserMapper.selectUser",1); //调用查询方法
System.out.println(user.getId());
System.out.println(user.getUsername());
//非查询方法需手动提交session.commit();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(session != null){
session.close(); //关闭SqlSession
}
}
}

以上只是测试mybatis配置文件是否正确的方法,在项目中,需要进行简单的封装,
而每一个SqlSession都是线程不安全的,SqlSessionFactory的工具类:则只需要启动项目初始化一次就行。
SqlSessionFactory的工具类:

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
package com.test.utils;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/**
*
*
* @author lmshe
* @time 2017年3月28日
* @desc 初始化SqlSessionFactory
*/
public class MyBatisUtil{
private MyBatisUtil(){
}
private static final String RESOURCE = "mybatis-config.xml";//mybatis配置文件所在路径
private static SqlSessionFactory sqlSessionFactory = null;
//使用静态块初始化SqlSessionFactory
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader(RESOURCE);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
sqlSessionFactory = builder.build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @return
* @author lmshe
* @time 2017年3月28日
* @desc 获取SqlSessionFactory
*/
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}


4、mybatis的CRUD的简单封装

对于spring MVC等主流框架项目来说,直接引入liuzh封装的Mapper,已经封装好大部分CRUD方法,当然更方便,
但是由于本人项目是main函数启动,并没有使用spring MVC,所以在抉择下,决定参考网上资料,自己封装部分CRUD,

(1)如何封装通用的BaseDao
mybatis通过配置可以将sql.xml和dao映射起来,通过xml中的id,能执行xml中的sql,
如果需要通用的方法,就需要使用泛型,然后产生CRUD的sql,直接传入xml中,执行,
mybatis框架提供的可以将参数传入,使用#{参数名}来获取传入的参数,
同时也提供了另一种方法,将sql传入,但是获取sql的方式与获取参数不同,使用${sql},
那么,重要的工作,就是如何使用泛型产生sql。

(2)定义BaseDao

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
package com.test.mapper;
import java.util.List;
public interface IBaseMapper<T,PK> {
/**
* 根据主键删除记录
* 物理删除,无法恢复
*/
int deleteByPrimaryKey(PK id);
/**
* 插入记录
* 字段为空,不插入
*/
int insertSelective(T obj);
/**
* 根据主键更新记录
* 字段为空,不更新
*/
int updateByPrimaryKeySelective(T obj);
/**
* 根据主键查询
* 此查询方法仅适用于表主键字段名为“id”,且其它字段以“f”开始
*/
T selectByPrimaryKey(PK id);
/**
* 条件查询
* 此查询方法仅适用于表主键字段名为“id”,且其它字段以“f”开始
*/
T selectByParams(T obj);
/**
* 条件查询
* 此查询方法仅适用于表主键字段名为“id”,且其它字段以“f”开始
*/
List<T> selectList(T obj);
}

(3)定义Base.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.IBaseMapper">
<!-- 删除数据 -->
<delete id="deleteByPrimaryKey">
${value}
</delete>
<!-- 插入数据 -->
<insert id="insertSelective">
${value}
</insert>
<!-- 根据主键更新记录 -->
<update id="updateByPrimaryKeySelective">
${value}
</update>
<!-- 根据主键查询记录 -->
<select id="selectByPrimaryKey" resultType="hashMap">
${value}
</select>
<!-- 条件查询记录 -->
<select id="selectByParams" resultType="hashmap">
${value}
</select>
<!-- 查询记录列表 -->
<select id="selectList" resultType="hashmap">
${value}
</select>
</mapper>

(4)BaseDao实现类

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
package com.test.mapper.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import com.test.mapper.IBaseMapper;
import com.test.utils.MyBatisUtil;
import com.test.utils.ReflectionUtils;
import com.test.utils.SQLGeneratorUtils;
public class BaseMapperImpl<T,PK> extends SqlSessionDaoSupport implements IBaseMapper<T,PK>{
SQLGeneratorUtils<T, PK> sqlGeneratorUtils = new SQLGeneratorUtils<T, PK>();
private Class<T> entityClass;
@SuppressWarnings("unchecked")
public BaseMapperImpl() {
super.setSqlSessionFactory(MyBatisUtil.getSqlSessionFactory());
Type genType = getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
entityClass = (Class<T>) params[0];
}
@Override
public int deleteByPrimaryKey(PK id) {
String sql = sqlGeneratorUtils.deleteByPrimaryKey(entityClass,id);
return this.getSqlSession().delete("deleteByPrimaryKey",sql);
}
@Override
public int insertSelective(T obj) {
String sql = sqlGeneratorUtils.insertSelective(obj);
return this.getSqlSession().insert("insertSelective",sql);
}
@Override
public int updateByPrimaryKeySelective(T obj) {
String sql = sqlGeneratorUtils.updateByPrimaryKeySelective(obj);
return this.getSqlSession().update("updateByPrimaryKeySelective",sql);
}
@Override
public T selectByPrimaryKey(PK id) {
String sql = sqlGeneratorUtils.selectByPrimaryKey(entityClass,id);
Map<String, Object> resultMap = this.getSqlSession().selectOne("selectByPrimaryKey",sql);
if(resultMap != null){
return handleResult(resultMap,entityClass);
}
return null;
}
@Override
public T selectByParams(T obj) {
String sql = sqlGeneratorUtils.selectByParams(obj);
Map<String, Object> resultMap = this.getSqlSession().selectOne("selectByParams",sql);
if(resultMap != null){
return handleResult(resultMap,entityClass);
}
return null;
}
@Override
public List<T> selectList(T obj) {
String sql = sqlGeneratorUtils.selectByParams(obj);
List<Map<String,Object>> resultMapList = this.getSqlSession().selectList("selectList",sql);
if(resultMapList != null){
List<T> tList = new ArrayList<T>(resultMapList.size());
for (Map<String, Object> resultMap : resultMapList) {
T t = handleResult(resultMap, entityClass);
tList.add(t);
}
return tList;
}
return null;
}
/**
*
* @param resultMap
* @param tClazz
* @return
* @author lmshe
* @time 2017年3月31日
* @desc 处理查询结果
*/
private T handleResult(Map<String, Object> resultMap, Class<T> tClazz) {
T t = null;
try {
t = tClazz.newInstance();
} catch (Exception e) {
logger.error("/********************************");
logger.error("封装查询结果时,实例化对象(" + this.entityClass + ")时,出现异常!"
+ e.getMessage());
logger.error("/********************************");
}
for (Map.Entry<String, Object> entry : resultMap.entrySet()) {
String key = entry.getKey();
Object val = entry.getValue();
ReflectionUtils.invokeSetterMethod(t, key, val);
}
return t;
}
}

关于基类Dao的实现,其实为了偷懒,而使用了spring的SqlSessionDaoSupport,
不然每个方法都要开SqlSession,关SqlSession,烦死,
由于没有使用spring配置,所以其实需要将SqlSessionFactory注入才可以正常调用,
于是使用了构造方法来实现,这样就可以使用this.getSqlSession()来直接调用方法,
而其中产生sql使用了另外一个工具类,关于实体类与泛型使用反射工具类来处理,
将Map对象转成实体类对象

(5)产生sql工具类

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
package com.test.utils;
import java.lang.reflect.Field;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import org.apache.commons.lang.StringUtils;
public class SQLGeneratorUtils<T,PK> {
/**
*
* @param id
* @return
* @author lmshe
* @time 2017年3月29日
* @desc 根据id删除记录,兼容id为Integer
*/
public String deleteByPrimaryKey(Class<T> entityClass,PK id){
String sql = "";
try {
Table table = entityClass.getAnnotation(Table.class);
if(table == null){
throw new RuntimeException("类-"+ entityClass + ",未用@Table注解标识!!");
}
String tableName = table.name();
Field[] fields = entityClass.getDeclaredFields();
String pkName = "";
for(Field field : fields){
field.setAccessible(true);
if(field.getAnnotation(Id.class) != null){
Column col = field.getAnnotation(Column.class);
pkName = col.name();
break;
}
}
if(StringUtils.isNotBlank(pkName)){
sql += "DELETE FROM " + tableName + " where " + pkName + "=" + handleValue(id);
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return sql;
}
/**
*
* @param obj
* @return
* @author lmshe
* @time 2017年3月29日
* @desc 插入记录,字段不为空的插入
*
*/
public String insertSelective(T obj){
String sql = "";
try {
Class<?> entityClass = obj.getClass();
Table table = entityClass.getAnnotation(Table.class);
if(table == null){
throw new RuntimeException("类-"+ entityClass + ",未用@Table注解标识!!");
}
String tableName = table.name();
Field[] fields = entityClass.getDeclaredFields();
String columnsStr = "";
String paramStr = "";
for(Field field : fields){
field.setAccessible(true);
Object param = field.get(obj);
Column col = field.getAnnotation(Column.class);
if(param != null && col != null){
param = this.handleValue(param);
columnsStr += ","+col.name();
paramStr += ","+param;
}
}
sql += "INSERT INTO " + tableName + "(" + columnsStr.substring(1) + ")values(" + paramStr.substring(1) + ")";
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return sql;
}
/**
*
* @param obj
* @return
* @author lmshe
* @time 2017年3月29日
* @desc 根据主键更新记录,字段为空,不更新
*/
public String updateByPrimaryKeySelective(T obj){
String sql = "";
try {
Class<?> entityClass = obj.getClass();
Table table = entityClass.getAnnotation(Table.class);
if(table == null){
throw new RuntimeException("类-"+ entityClass + ",未用@Table注解标识!!");
}
String tableName = table.name();
Field[] fields = entityClass.getDeclaredFields();
String sqlStr = "";
String pkName = "";
Object pkValue = "";
for(Field field : fields){
field.setAccessible(true);
Object param = field.get(obj);
Column col = field.getAnnotation(Column.class);
if(field.getAnnotation(Id.class) != null){
if(param != null && col != null){
pkValue = this.handleValue(param);
pkName = col.name();
}else{
throw new RuntimeException("主键不能为空!");
}
}else{
if(param != null && col != null){
param = this.handleValue(param);
sqlStr += ","+col.name() + "="+param;
}
}
}
sql += "update " + tableName + " set " + sqlStr.substring(1) + " where " + pkName + "=" + pkValue;
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return sql;
}
/**
*
* @param entityClass
* @param id
* @return
* @author lmshe
* @time 2017年3月30日
* @desc 根据主键查询
*/
public String selectByPrimaryKey(Class<T> entityClass,PK id){
String sql = "";
try {
Table table = entityClass.getAnnotation(Table.class);
if(table == null){
throw new RuntimeException("类-"+ entityClass + ",未用@Table注解标识!!");
}
String tableName = table.name();
Field[] fields = entityClass.getDeclaredFields();
String pkName = "";
for(Field field : fields){
field.setAccessible(true);
if(field.getAnnotation(Id.class) != null){
Column col = field.getAnnotation(Column.class);
pkName = col.name();
break;
}
}
sql += "select * from " + tableName + " where " + pkName + "=" + handleValue(id);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return sql;
}
/**
*
* @param obj
* @return
* @author lmshe
* @time 2017年3月30日
* @desc 条件查询
*/
public String selectByParams(T obj){
String sql = "";
try {
Class<?> entityClass = obj.getClass();
Table table = entityClass.getAnnotation(Table.class);
if(table == null){
throw new RuntimeException("类-"+ entityClass + ",未用@Table注解标识!!");
}
String tableName = table.name();
Field[] fields = entityClass.getDeclaredFields();
String sqlWhereStr = "";
for(Field field : fields){
field.setAccessible(true);
Object param = field.get(obj);
Column col = field.getAnnotation(Column.class);
if(param != null && col != null){
param = this.handleValue(param);
sqlWhereStr += " and "+col.name() + "="+param;
}
}
sql += "select * from " + tableName + " where " + sqlWhereStr.substring(4);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return sql;
}
/**
*
* @param param
* @return
* @author lmshe
* @time 2017年3月29日
* @desc 处理param
*/
private Object handleValue(Object param) {
if (param instanceof String || param instanceof Date) {
param = "\'" + param + "\'";
}else if (param instanceof Boolean) {
Boolean v = (Boolean) param;
param = v ? 1 : 0;
}
return param;
}
}

(6)反射工具类

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
package com.test.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Description:反射工具类
*/
public abstract class ReflectionUtils {
private static final Logger logger = LoggerFactory
.getLogger(ReflectionUtils.class);
/**
* 缓存方法
*/
private static final Map<Class<?>, Method[]> METHODS_CACHEMAP = new HashMap<Class<?>, Method[]>();
/**
* 反射 取值、设值,合并两个对象(Field same only )
*
* @param from
* @param to
*/
public static <T> void copyProperties(T fromobj, T toobj,
String... fieldspec) {
for (String filename : fieldspec) {
Object val = ReflectionUtils.invokeGetterMethod(fromobj, filename);
ReflectionUtils.invokeSetterMethod(toobj, filename, val);
}
}
/**
* 调用Getter方法
*
* @param obj
* 对象
* @param propertyName
* 属性名
* @return
*/
public static Object invokeGetterMethod(Object obj, String propertyName) {
String getterMethodName = "get" + capitalize(propertyName);
return invokeMethod(obj, getterMethodName, null, null);
}
/**
* 调用Setter方法,不指定参数的类型
*
* @param obj
* @param propertyName
* @param value
*/
public static void invokeSetterMethod(Object obj, String propertyName,
Object value) {
invokeSetterMethod(obj, propertyName, value, null);
}
/**
* 调用Setter方法,指定参数的类型
*
* @param obj
* @param propertyName 字段名
* @param value
* @param propertyType
* 为空,则取value的Class
*/
public static void invokeSetterMethod(Object obj, String propertyName,
Object value, Class<?> propertyType) {
value = handleValueType(obj,propertyName,value);
propertyType = propertyType != null ? propertyType : value.getClass();
String setterMethodName = "set" + capitalize(propertyName);
invokeMethod(obj, setterMethodName, new Class<?>[] { propertyType },
new Object[] { value });
}
private static Object handleValueType(Object obj, String propertyName,
Object value){
String getterMethodName = "get" + capitalize(propertyName);
Class<?> argsType = value.getClass();;
Class<?> returnType = obtainAccessibleMethod(obj, getterMethodName).getReturnType();
if(argsType == returnType){
return value;
}
if (returnType == Boolean.class) {
String temp = value.toString();
value = (StringUtils.isNotBlank(temp) && Long.valueOf(temp) > 0) ? true : false;
} else if (returnType == Long.class) {
value = Long.valueOf(value.toString());
}else if(returnType == Date.class){
try {
value = SimpleDateFormat.getDateInstance().parse(value.toString());
} catch (ParseException e) {
logger.error("类型转型Timpestap-->Date时,发生错误! " + e.getMessage() + "("+value.toString()+")");
}
} else if (returnType == Short.class) {
value = Short.valueOf(value.toString());
} else if (returnType == BigDecimal.class) {
value = BigDecimal.valueOf(Long.valueOf(value.toString()));
} else if (returnType == BigInteger.class) {
value = BigInteger.valueOf(Long.valueOf(value.toString()));
} else if(returnType == String.class){
value = String.valueOf(value);
}else if(returnType == Integer.class){
value = Integer.valueOf(value.toString());
}
return value;
}
public static void main(String[] args) throws Exception {
Timestamp ts = new Timestamp(System.currentTimeMillis());
System.out.println(SimpleDateFormat.getDateInstance().parse(ts.toString()));
}
/**
* 直接调用对象方法,忽视private/protected修饰符
*
* @param obj
* @param methodName
* @param parameterTypes
* @param params
* @return
*/
public static Object invokeMethod(final Object obj,
final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
Method method = obtainAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) { throw new IllegalArgumentException(
"Devkit: Could not find method [" + methodName
+ "] on target [" + obj + "]."); }
try {
return method.invoke(obj, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* 循环向上转型,获取对象的DeclaredMethod,并强制设置为可访问 如向上转型到Object仍无法找到,返回null
*
* 用于方法需要被多次调用的情况,先使用本函数先取得Method,然后调用Method.invoke(Object obj,Object...
* args)
*
* @param obj
* @param methodName
* @param parameterTypes
* @return
*/
public static Method obtainAccessibleMethod(final Object obj,
final String methodName, final Class<?>... parameterTypes) {
Class<?> superClass = obj.getClass();
Class<Object> objClass = Object.class;
for (; superClass != objClass; superClass = superClass.getSuperclass()) {
Method method = null;
try {
method = superClass.getDeclaredMethod(methodName,
parameterTypes);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException e) {
// Method不在当前类定义,向上转型
} catch (SecurityException e) {
// Method不在当前类定义,向上转型
}
}
return null;
}
/**
* 不能确定方法是否包含参数时,通过方法名匹配获得方法
*
* @param obj
* @param methodName
* @return
*/
public static Method obtainMethod(final Object obj, final String methodName) {
Class<?> clazz = obj.getClass();
Method[] methods = METHODS_CACHEMAP.get(clazz);
if (methods == null) { // 尚未缓存
methods = clazz.getDeclaredMethods();
METHODS_CACHEMAP.put(clazz, methods);
}
for (Method method : methods) {
if (method.getName().equals(methodName))
return method;
}
return null;
}
/**
* 直接读取对象属性值 忽视private/protected修饰符,不经过getter函数
*
* @param obj
* @param fieldName
* @return
*/
public static Object obtainFieldValue(final Object obj,
final String fieldName) {
Field field = obtainAccessibleField(obj, fieldName);
if (field == null) { throw new IllegalArgumentException(
"Devkit: could not find field [" + fieldName + "] on target ["
+ obj + "]"); }
Object retval = null;
try {
retval = field.get(obj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return retval;
}
/**
* 直接设置对象属性值 忽视private/protected修饰符,不经过setter函数
*
* @param obj
* @param fieldName
* @param value
*/
public static void setFieldValue(final Object obj, final String fieldName,
final Object value) {
Field field = obtainAccessibleField(obj, fieldName);
if (field == null) { throw new IllegalArgumentException(
"Devkit: could not find field [" + fieldName + "] on target ["
+ obj + "]"); }
try {
field.set(obj, value);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 循环向上转型,获取对象的DeclaredField,并强制设为可访问 如向上转型Object仍无法找到,返回null
*
* @param obj
* @param fieldName
* @return
*/
public static Field obtainAccessibleField(final Object obj,
final String fieldName) {
Class<?> superClass = obj.getClass();
Class<Object> objClass = Object.class;
for (; superClass != objClass; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
// Field不在当前类定义,向上转型
} catch (SecurityException e) {
// Field不在当前类定义,向上转型
}
}
return null;
}
/**
*
* @param str
* @return
* @author lmshe
* @time 2017年3月31日
* @desc 处理属性字段
*/
private static String capitalize(String str){
if(!"id".equals(str)){
while (str.indexOf("_") > 0) {
int index = str.indexOf("_");
str = str.substring(0, index) + str.substring(index + 1, index + 2).toUpperCase() + str.substring(index + 2);
}
str = str.substring(1);
}
return str = StringUtils.capitalize(str);
}
}


注意与参考

由于本人的数据库表名是以t_开头,且所有字段名,都是用“f”开头,所以在使用反射工具类的时候,
修改最后的capitalize()方法,适应自己用的表,
如果已经在xml中配置了resultMap,则不需要在配置文件配置别名,适用与表字段名与实体类属性名不一致的情况

Mybatis封装简单的CRUD


寄语

我低眉,藏起眼角的悲伤,笑颜渐起