实现一个微型的 Mybatis-注解版
# 60.实现一个微型的 Mybatis-注解版
有了之前的基础,使用注解的方式来读取配置就很简单了,本文就简单说说使用注解的情况下如何获取。
# 修改主配置文件
SqlMapConfig.xml,修改 mapper 的属性为 class:
<mappers>
<!-- <mapper resource="com/peterjxl/dao/IUserDao.xml"/>-->
<mapper class="com.peterjxl.dao.IUserDao"/>
</mappers>
1
2
3
4
2
3
4
# 新建 Select 注解
package com.peterjxl.mybatis.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 查询的注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
/**
* 配置 SQL 语句的
* @return
*/
String value();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 在 IUserDao 接口上配置注解
package com.peterjxl.dao;
import com.peterjxl.domain.User;
import com.peterjxl.mybatis.annotations.Select;
import java.util.List;
public interface IUserDao {
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
List<User> findAll();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 修改工具类 XMLConfigBuilder
我们之前注释掉了 XMLConfigBuilder
类中,关于解析注解的方法 loadMapperAnnotation
,现在我们取消注释,并引入缺失的类(例如注解)
该方法会获取到主配置文件的 mapper 标签,然后读取配置的全限定类名,再读取注解属性,存储到 mapper 对象里。
private static Map<String,Mapper> loadMapperAnnotation(String daoClassPath)throws Exception{
//定义返回值对象
Map<String,Mapper> mappers = new HashMap<String, Mapper>();
//1.得到 dao 接口的字节码对象
Class daoClass = Class.forName(daoClassPath);
//2.得到 dao 接口中的方法数组
Method[] methods = daoClass.getMethods();
//3.遍历 Method 数组
for(Method method : methods){
//取出每一个方法,判断是否有 select 注解
boolean isAnnotated = method.isAnnotationPresent(Select.class);
if(isAnnotated){
//创建 Mapper 对象
Mapper mapper = new Mapper();
//取出注解的 value 属性值
Select selectAnno = method.getAnnotation(Select.class);
String queryString = selectAnno.value();
mapper.setQueryString(queryString);
//获取当前方法的返回值,还要求必须带有泛型信息
Type type = method.getGenericReturnType();//List <User>
//判断 type 是不是参数化的类型
if(type instanceof ParameterizedType){
//强转
ParameterizedType ptype = (ParameterizedType)type;
//得到参数化类型中的实际类型参数
Type[] types = ptype.getActualTypeArguments();
//取出第一个
Class domainClass = (Class)types[0];
//获取 domainClass 的类名
String resultType = domainClass.getName();
//给 Mapper 赋值
mapper.setResultType(resultType);
}
//组装 key 的信息
//获取方法的名称
String methodName = method.getName();
String className = method.getDeclaringClass().getName();
String key = className+"."+methodName;
//给 map 赋值
mappers.put(key,mapper);
}
}
return mappers;
}
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
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
# 测试
我们再次运行测试方法,可以看到能正常运行
使用的是注解
User{id=41, username='张三', birthday=2018-02-27T17:47:08, sex='男', address='北京'}
User{id=42, username='李四', birthday=2018-03-02T15:09:37, sex='女', address='北京'}
User{id=43, username='王五', birthday=2018-03-04T11:34:34, sex='女', address='北京'}
User{id=45, username='赵六', birthday=2018-03-04T12:04:06, sex='男', address='北京'}
User{id=46, username='小七', birthday=2018-03-07T17:37:26, sex='男', address='北京'}
User{id=48, username='老八', birthday=2018-03-08T11:44, sex='男', address='北京'}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 源码
所有代码已上传到了 GitHub (opens new window) 和 Gitee (opens new window) 上,并且创建了分支 demo5,读者可以通过切换分支来查看本文的示例代码。
上次更新: 2024/10/1 21:14:36