记录一次项目Java反射的应用

  1. 概念
    1. 在运行状态中,对于任意一个类,都能够知道类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法。这就是java的反射机制
  2. 用法
    1. 获取Class实例
    2. 使用Class实例可以获取泛型所指对象的方法、属性、注解等,还可以调用方法操作该类,具体哪些方法可以在java.lang.Class类中查看
  3. 实际应用
    1. 需求:从mdb文件中解析N多张表入库,可以通过反射拼写sql语句一次性执行。
    2. 实现:
      获取Class实例的几种方式
      //通过全限定类名获取
      Class<Father> aClass = Class.forName(classname);
      //通过Object中的getClass方法
      //object that represents the runtime class of this object这是Object中对于getClass方法的说明:为object获取运行时的class
      Class<Father> aClass = new Father().getClass()
      //类.class
      Class<Father> aClass = Father.class
      
      //一定要注意aClass到底是谁的实例,在继承或者传参的时候容易出错
      1.父类的引用指向子类的对象
      Father f = new Children();
      Class<Children> aClass = f.getClass;
      
      Class<Father> aClass = Father.class
      注意以上分别代表谁的Class实例
      
      2.当使用对象传参的时候,例如方法是使用Object接收的
      
      //假设有一个get方法需要传一个对象
      //我使用Father对象传参调用get方法  get(new Father());
      
      public void get(Object object){
         //当Father对象传递过来以后我们需要得到Class实例进行操作
         //此时的Class对象是Object的
         Class<?> aClass = object.getClass();
         //得到Father的全限定类名
         String classname = aClass.getName();
         //此时的Class对象才是Father的
         Class<?> myClass = Class.forName(classname);
          
      }
      
      //此处Object作为一个参数传递,因为我们并不知道传过来的是要入库的哪个实体
          public static void saveData(String ywh,Object obj) throws Exception {
              //解析mdb
              Connection conn = null;
              Statement stmt = null;
              String filePath = "C:\\Users\\xd\\Desktop\\成果包\\140000山西省空间规划数据库电子成果数据\\4表格数据\\140000山西省国土空间规划指标表.mdb";
              String conStr = "jdbc:ucanaccess:///" + filePath;
              DbUtils.loadDriver("net.ucanaccess.jdbc.UcanaccessDriver");
              conn = DriverManager.getConnection(conStr);
              stmt = conn.createStatement();
      
              //获取全限定类名
              String classname = obj.getClass().getName();
              //得到真正想要入库的对象 而不是Object的Class实例
              Class<?> aClass = Class.forName(classname);
              String[] split = classname.split("\\.");
              classname = split[split.length-1];
              String sql = "select * from "+classname;
              QueryRunner queryRunner = new QueryRunner();
              //注意aClass是真正要入库的对象,如果上面不做Class.forName处理,那么得到是Object,而达不到我们想要的结果
              List<Object> list = (List<Object>) queryRunner.query(conn,sql,new BeanListHandler(aClass));
              list.forEach(item -> {
                  try {
                      //获取对应的属性,这里使用的是暴力反射获取属性,因为属性在对象中定义的是private
                      Field f = item.getClass().getDeclaredField("ywh");
                      Field primary = item.getClass().getDeclaredField("ID");
                      try {
                          //private属性的操作需要设置setAccessible为true
                          primary.setAccessible(true);
                          f.setAccessible(true);
      
                          //赋值:将字符串ywh赋值给list中的对象的ywh属性,f即反射得到的ywh的属性对象
                          f.set(item,ywh);
                          //赋值:将字符串UUID赋值给list中的对象的ID属性,primary即反射得到的ID的属性对象
                          primary.set(item, IdGen.uuid());
                      } catch (IllegalAccessException e) {
                          e.printStackTrace();
                      }
                  } catch (NoSuchFieldException e) {
                      e.printStackTrace();
                  }
              });
              if(list.size()>0){
                  save(list,classname);
              }
      
          }
      
          public static void save(List<Object> list,String classname) {
              //获取目标对应的所有属性列表
              Field[] fields = list.get(0).getClass().getDeclaredFields();
              //将所有属性装到list中,并且拼接成字符串供后面使用
              List<String> nameList = new ArrayList<>();
              String insertstr = "";
              for(int i=0;i<fields.length;i++){
                  nameList.add(fields[i].getName());
                  insertstr+=fields[i].getName()+",";
              }
              insertstr = insertstr.substring(0,insertstr.length()-1);
              //类名 即 表名
              String tablename = "insert into xxhacheck."+classname.toLowerCase()+"("+insertstr+") values (" ;
              String allsql = "";
              //循环拼接sql语句
              for(Object obj: list){
                  String valuestr = "";
                  //为了获取list中每个对象的所有属性值
                  for(int i=0;i<fields.length;i++){
                      String fieldname = fields[i].getName();
                      try {
                          //反射获取属性对象Field,属性私有使用getDeclaredField
                          Field declaredField = obj.getClass().getDeclaredField(fieldname);
                          declaredField.setAccessible(true);
                          //利用属性对象获取属性值
                          Object value = declaredField.get(obj);
                          if(value==null){
                              valuestr+="无 "+",";
                          }else{
                              valuestr+=value.toString()+",";
                          }
                      } catch (IllegalAccessException e) {
                          e.printStackTrace();
                      } catch (NoSuchFieldException e) {
                          e.printStackTrace();
                      }
                  }
                  valuestr = valuestr.substring(0,valuestr.length()-1);
                  System.out.println("拼接以后的值:"+valuestr);
                  String finalstr = tablename+valuestr+");";
                  allsql+=finalstr;
              }
              System.out.println("最终的结果值:"+allsql);
          }

       

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dong__xue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值