- 实体Admin,与数据库字段名不同,添加注释。
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 }
- Column.java 注释类
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 }
- Id.java
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 }
- Table.java
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 }
- BaseDao.java
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 }