package cn.peng.dao;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.dbutils.QueryRunner;
import cn.itcast.jdbc.TxQueryRunner;
/**
* 根据反射泛型以及反射Class 实现BasicDao小工具
* 实现增删改查操作 继承此类,只用传递对应类名
* 且在该类中设置注解,注解的值就是数据库的列名以及表名
* 调用此类add/delete/modify/select方法即可完成对数据库操作
* @author peng'peng
* @param <T>
*/
public class BasicDao<T> {
private QueryRunner qr = new TxQueryRunner();
private Class<T> beanClass;
public BasicDao() {
//得到传递过来的泛型类的class名称
// Type c = this.getClass().getGenericSuperclass();
// ParameterizedType ptype = (ParameterizedType) c;
// Class beanClass = (ptype.getActualTypeArguments())[0].getClass();
// System.out.println("beanClass:"+beanClass.getName());
Class beanClass = (Class)((ParameterizedType)this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
this.beanClass = beanClass;
System.out.println(beanClass.getName());
}
public void add(T t) throws SQLException, IllegalArgumentException, IllegalAccessException {
/**
* 使用反射得到该T的表名,以及各个列名
*/
//使用反射得到类的注解名称的值 --》得到表名
//得到表名
//TableName tableNameAnno = (TableName)beanClass.getAnnotation(TableName.class);
//String table = tableNameAnno.value();
TableName table = t.getClass().getAnnotation(TableName.class);
String tableName = table.value();
System.out.println(t.getClass().getName());
System.out.println(tableName);
//使用map集合 存储每个列名对应的值
Map<String,String> map = new LinkedHashMap<String, String>();
//得到表名注解的成员变量的集合 //此处只能使用DeclaredFields方法 得到本类,Field是得到父类的共有字段
Field[] fields = t.getClass().getDeclaredFields();
fields[0].setAccessible(true);//设置禁用访问权限
ID id = (ID) fields[0].getAnnotation(ID.class);
//得到表主键名称以及对应值
map.put(id.value(), (String) fields[0].get(t));
//字符串拼接
StringBuilder sb = new StringBuilder();
for(int i=1;i<fields.length;i++) {
//将列名以及对应的值存到map中
fields[i].setAccessible(true);//先设置禁用每个属性的访问权限
String value = fields[i].getAnnotation(Column.class).value();
map.put(value, fields[i].get(t)+"");
if(i-1<fields.length-1) {
sb.append("?,");
}else {
sb.append("?");
}
}
sb.append("?");//补上最后一个参数?
String sql ="insert into "+tableName+" values("+sb.toString()+")";
Object[] params = map.values().toArray();
qr.update(sql, params);
}
}
上面是我封装的BasicDao 初版,在同一包下测试成功,当我在其他包下的时候,报异常,说是 TableName 那里的值为null
下面是我的包结构:
我觉得可能问题出在注解那里,我对注解也是今天才学了一点,只知道使用getAnnotation(Class) 得到指定注解名对象
如果此项目有能帮到我的地方,万分感谢!!!
这是测试类Book的注解:
数据库的表是对的,这个测试成功了,就是在其他包下使用就报错
报错提示如下:
如果还有需要补充的 欢迎评论
@SpringBootTest
class TravelServerApplicationTests {
private user u1=new user();
@Autowired
private user u2;
@Autowired
ApplicationContext applicationContext;
@Test
void contextLoads() throws IllegalAccessException, InstantiationException {
Arrays.stream(user.class.getAnnotations()).forEach(System.out::println);
System.out.println("-------------------");
Arrays.stream(u1.getClass().getAnnotations()).forEach(System.out::println);
System.out.println("-------------------");
Arrays.stream(u2.getClass().getAnnotations()).forEach(System.out::println);
user bean = applicationContext.getBean(user.class);
System.out.println("-------------------");
Arrays.stream(bean.getClass().getAnnotations()).forEach(System.out::println);
user u3 = user.class.newInstance();
System.out.println("-------------------");
Arrays.stream(u3.getClass().getAnnotations()).forEach(System.out::println);
}
}
spring管理的bean无法获取注解
因为这里的bean其实是一个代理类
AopUtils.getTargetClass(Obj)
可以使用这个方法获取
...看不懂,今天才开始学spring框架,我实现的时候,就是用原始的反射啥的实现的,没有使用框架,如果原始的方式能指点一下更好,不过也无伤大雅,毕竟以后都是使用框架了,还是先谢谢各位前辈哈