1 import cn.itcast.utils.Column;
2 import cn.itcast.utils.Id;
3 import cn.itcast.utils.Table;
4
5 // Admin=a_admin
6 @Table(tableName="a_admin")
7 public class Admin {
8
9 @Id
10 @Column(columnName = "a_id")
11 private int id;
12
13 @Column(columnName = "a_userName")
14 private String userName;
15
16 @Column(columnName = "a_pwd")
17 private String pwd;
18
19 public int getId() {
20 return id;
21 }
22 public void setId(int id) {
23 this.id = id;
24 }
25 public String getUserName() {
26 return userName;
27 }
28 public void setUserName(String userName) {
29 this.userName = userName;
30 }
31 public String getPwd() {
32 return pwd;
33 }
34 public void setPwd(String pwd) {
35 this.pwd = pwd;
36 }
37 @Override
38 public String toString() {
39 return "Admin [id=" + id + ", pwd=" + pwd + ", userName=" + userName
40 + "]";
41 }
42
43 }
2
3 import java.lang.annotation.Retention;
4 import java.lang.annotation.RetentionPolicy;
5 import java.lang.annotation.Target;
6 import static java.lang.annotation.ElementType.FIELD;
7
8 /**
9 * 描述一个字段
10 * @author Jie.Yuan
11 *
12 */
13 @Target({FIELD})
14 @Retention(RetentionPolicy.RUNTIME) // 指定注解在运行时期有效
15 public @interface Column {
16
17 String columnName();
18 }
1 import static java.lang.annotation.ElementType.FIELD;
2
3 import java.lang.annotation.Retention;
4 import java.lang.annotation.RetentionPolicy;
5 import java.lang.annotation.Target;
6
7 /**
8 * 描述一个主键字段
9 * @author Jie.Yuan
10 *
11 */
12 @Target({FIELD})
13 @Retention(RetentionPolicy.RUNTIME) // 指定注解在运行时期有效
14 public @interface Id {
15
16 }
1 import static java.lang.annotation.ElementType.TYPE;
2
3 import java.lang.annotation.Retention;
4 import java.lang.annotation.RetentionPolicy;
5 import java.lang.annotation.Target;
6
7 /**
8 * 注解,描述表名称
9 * @author Jie.Yuan
10 *
11 */
12 @Target({TYPE})
13 @Retention(RetentionPolicy.RUNTIME) // 指定注解在运行时期有效
14 public @interface Table {
15
16 String tableName();
17 }
1 import java.lang.reflect.Field;
2 import java.lang.reflect.ParameterizedType;
3 import java.lang.reflect.Type;
4 import java.sql.ResultSet;
5 import java.sql.SQLException;
6 import java.util.ArrayList;
7 import java.util.List;
8
9 import org.apache.commons.beanutils.BeanUtils;
10 import org.apache.commons.dbutils.ResultSetHandler;
11
12 import cn.itcast.b_reflect.JdbcUtils;
13 import cn.itcast.utils.Column;
14 import cn.itcast.utils.Id;
15 import cn.itcast.utils.Table;
16
17 /**
18 * 解决优化的问题:
19 * 1. 当数据库表名与类名不一致、
20 * 2. 字段与属性不一样、
21 * 3. 主键不叫id
22 *
23 */
24 public class BaseDao<T> {
25
26 // 当前运行类的类型
27 private Class<T> clazz;
28 // 表名
29 private String tableName;
30 // 主键
31 private String id_primary;
32
33 // 拿到当前运行类的参数化类型中实际的类型 ( BaseDao<Admin> , Admin.class)
34 public BaseDao(){
35 Type type = this.getClass().getGenericSuperclass();
36 ParameterizedType pt = (ParameterizedType) type;
37 Type[] types = pt.getActualTypeArguments();
38 clazz = (Class<T>) types[0];
39
40 //已经拿到: Admin.class
41
42 /*******1. 获取表名*******/
43 Table table = clazz.getAnnotation(Table.class);
44 tableName = table.tableName();
45
46 /*******2. 获取主键字段*******/
47 //获取当前运行类的所有字段、遍历、获取每一个字段上的id注解
48 Field[] fs = clazz.getDeclaredFields();
49 for (Field f : fs) {
50
51 // 设置强制访问
52 f.setAccessible(true);
53
54 // 获取每一个字段上的id注解
55 Id anno_id = f.getAnnotation(Id.class);
56
57 // 判断
58 if (anno_id != null) {
59 // 如果字段上有id注解,当前字段(field)是主键; 再获取字段名称
60 Column column = f.getAnnotation(Column.class);
61 // 主键
62 id_primary = column.columnName();
63 // 跳出循环
64 break;
65 }
66 }
67
68 System.out.println("表:" + tableName);
69 System.out.println("主键:" + id_primary);
70 }
71
72
73 public T findById(int id){
74 try {
75 String sql = "select * from " + tableName + " where " + id_primary +"=?";
76 /*
77 * DbUtils的已经封装好的工具类:BeanHandler? 属性=字段
78 */
79 return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);
80 } catch (Exception e) {
81 throw new RuntimeException(e);
82 }
83 }
84
85
86 public List<T> getAll(){
87 try {
88 String sql = "select * from " + tableName;
89 return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));
90 } catch (Exception e) {
91 throw new RuntimeException(e);
92 }
93 }
94
95 }
96
97 /**
98 * 自定义结果集:封装单个Bean对象
99 */
100 class BeanHandler<T> implements ResultSetHandler<T>{
101 // 保存传入的要封装的类的字节码
102 private Class<T> clazz;
103 public BeanHandler(Class<T> clazz) {
104 this.clazz = clazz;
105 }
106
107 // 封装结果集的方法
108 @Override
109 public T handle(ResultSet rs) throws SQLException {
110 try {
111 // 创建要封装的对象 ‘1’
112 T t = clazz.newInstance();
113 // 向下读一行
114 if (rs.next()) {
115
116 // a. 获取类的所有的Field字段数组
117 Field[] fs = clazz.getDeclaredFields();
118
119 // b. 遍历, 得到每一个字段类型:Field
120 for (Field f : fs) {
121
122 // c. 获取”属性名称“
123 String fieldName = f.getName();
124
125 // e. 获取Field字段上注解 【@Column(columnName = "a_userName")】
126 Column column = f.getAnnotation(Column.class);
127
128 // f. ”字段名“
129 String columnName = column.columnName(); // 数据库中字段 a_userName
130
131 // g. 字段值
132 Object columnValue = rs.getObject(columnName);
133
134 // 设置(BeanUtils组件)
135 BeanUtils.copyProperty(t, fieldName, columnValue);
136 }
137 }
138 return t;
139 } catch (Exception e) {
140 throw new RuntimeException(e);
141 }
142 }
143 }
144
145
146 /**
147 * 自定义结果集:封装多个Bean对象到List集合
148 */
149 class BeanListHandler<T> implements ResultSetHandler<List<T>>{
150
151 // 要封装的单个对象
152 private Class<T> clazz;
153 public BeanListHandler(Class<T> clazz){
154 this.clazz = clazz;
155 }
156
157 // 把从数据库查询到的没一行记录,封装为一个对象,再提交到list集合, 返回List<T>
158 @Override
159 public List<T> handle(ResultSet rs) throws SQLException {
160 List<T> list = new ArrayList<T>();
161 try {
162 // 向下读一行
163 while (rs.next()) {
164
165 // 创建要封装的对象 ‘1’
166 T t = clazz.newInstance();
167
168 // a. 获取类的所有的Field字段数组
169 Field[] fs = clazz.getDeclaredFields();
170
171 // b. 遍历, 得到每一个字段类型:Field
172 for (Field f : fs) {
173
174 // c. 获取”属性名称“
175 String fieldName = f.getName();
176
177 // e. 获取Field字段上注解 【@Column(columnName = "a_userName")】
178 Column column = f.getAnnotation(Column.class);
179
180 // f. ”字段名“
181 String columnName = column.columnName(); // 数据库中字段 a_userName
182
183 // g. 字段值
184 Object columnValue = rs.getObject(columnName);
185
186 // 设置(BeanUtils组件)
187 BeanUtils.copyProperty(t, fieldName, columnValue);
188 }
189 // 对象添加到集合
190 list.add(t);
191 }
192 return list;
193 } catch (Exception e) {
194 throw new RuntimeException(e);
195 }
196 }
197
198 }