一文搞懂反射泛型和反射注解以及通過(guò)注解方式寫一個(gè)BaseDao

反射泛型和反射注解概括起來(lái)就三步:

  • 自定義注解
  • 通過(guò)反射獲取注解值
  • 使用自定義注解

最終案例

通過(guò)自定義注解,將數(shù)據(jù)庫(kù)表與Java對(duì)象映射,在不需要配置文件的情況下,查詢出數(shù)據(jù)庫(kù)的記錄
分析:數(shù)據(jù)庫(kù)表有數(shù)據(jù)庫(kù)名,表名和字段,所以在定義注解時(shí)這些都是必須的,但是在查詢時(shí)有通過(guò)主鍵查詢的方式,那么如何知道哪個(gè)字段是主鍵呢,這就需要來(lái)聲明一下,所以,還需要定義一個(gè)id注解用于標(biāo)識(shí)某對(duì)象的某屬性對(duì)應(yīng)著數(shù)據(jù)庫(kù)的主鍵。此時(shí)就需要來(lái)說(shuō)明一下什么是注解。

注解

什么是注解

  • 語(yǔ)法:@注解名稱
  • 注解的作用:替代xml配置文件
  • Servlet3.0中就可以不在使用web.xml文件,而是所有配置文件都使用注解。
  • 注解是由框架來(lái)讀取的!

注解的使用!

  • 定義注解類(框架的工作)
  • 使用注解(我們的工作)
  • 讀取注解(反射讀取注解)(框架的工作)

注解其實(shí)也是一個(gè)類

如何定義注解類

class A{}定義類
interface A{}定義接口

@interface A{} 定義注解

  • 天下所有的注解都是Annotation的子類
    不用特意標(biāo)記默認(rèn)就是

如何使用注解

首先自定義一個(gè)注解:

//自定義注解類
package annotation;
@interface MyAnnotation {
//暫時(shí)不寫內(nèi)容,只是演示注解的使用
}

使用自定義MyAnnotation注解

package annotation;
@MyAnnotation//注解能放在類上
public class Demo1 {
    @MyAnnotation//注解能放在成員變量上
    private String name;
    
    @MyAnnotation//注解能放在構(gòu)造器上
    public void Demo1(){
        
    }
    
    @MyAnnotation//注解能放在方法上
    public void test1(){
        
    }
    
    public void test2(@MyAnnotation String name){//注解能放在參數(shù)上
        //注解能放在局部變量上
        @MyAnnotation
        String username = "hello";
    }
    //但是注解不能放在方法的調(diào)用上
}

注解的作用目標(biāo)

由上述使用注解的例子可以看出,注解的作用目標(biāo)有一下幾種:

  • 方法
  • 構(gòu)造器
  • 參數(shù)
  • 局部變量

注解的屬性(依賴文檔了解)

  • 定義屬性
    格式:類型 屬性名()
    例如:
//注解類
@interface MyAnno1{
    int age();//這是屬性不是方法
    String name();//括號(hào)后面不能跟{},也不能加參數(shù),因?yàn)檫@不是方法,而是注解的屬性
}
  • 使用注解時(shí)給屬性賦值
//使用屬性時(shí),屬性必須要求有值
@MyAnno1(age=100,name="zhangsan")
  • 注解屬性的默認(rèn)值
//注解類
@interface MyAnno2{
    int age() default 100;//這是屬性不是方法
    String name();
}
使用時(shí):@MyAnno2(name="zhangsan")
也可以在給一個(gè)age值如:
@MyAnno2(age="999",name="zhangsan")
此時(shí)值會(huì)覆蓋默認(rèn)值
  • 名為value的屬性的特權(quán)
在使用注解時(shí),如果只給名為value的屬性賦值,那么可以不給出屬性的名稱直接給出值
例如:
//注解的特權(quán)
@interface MyAnno3{
    int value();
    String name() default "hello world";
}
使用注解時(shí):
@MyAnno3(100)相當(dāng)于給value的屬性賦值不用指定value
  • 注解屬性的類型
注解屬性有8中基本類型:
- String
- Enum
- Class
- 注解類型(和循環(huán)體的內(nèi)容是循環(huán)體是一個(gè)道理)
- 以上類型的一維數(shù)組類型 int[],(二維數(shù)組不行)
注意:Integer包裝類型不能使用

如何使用:
@interface MyAnno4{
    int a();
    String b();
    MyEnum c();
    Class d();
    MyAnno2 e();
    String[] f();
}
enum MyEnum{
    A,B,C
}

@MyAnno4(
    a=100,
    b="hello",
    c=MyEnum.A,
    d=String.class,
    e=@MyAnno2(name = "zhangsan"),
    f={"hello","world"}
)
public class Demo3 {

}
當(dāng)給數(shù)組類型的屬性賦值時(shí),可以省略大括號(hào)
如f="hello"

注解的作用目標(biāo)限定以及保存策略限定

讓一個(gè)注解他的作用目標(biāo)只能在類上不能在方法上,這就叫做目標(biāo)的限定

  • 在定義注解時(shí)給注解添加注解叫做@Target
@Target(value={ElementType.TYPE,ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD})
@interface MyAnno1{
    
}

保留策略

  • 源代碼文件(SOURCE):注解只在源代碼中存在,在編譯時(shí)就別忽略了(無(wú)法反射)
  • 字節(jié)碼文件(CLASS):注解在源代碼中存在,編譯時(shí)會(huì)把注解信息放到class中存在,但JVM在類時(shí)會(huì)被忽略加載注解(無(wú)法反射)
  • JVM中(RUNTIME):注解在源代碼,字節(jié)碼文件中存在,并且在JVM加載類時(shí)會(huì)把注解加載到JVM內(nèi)存中(它是唯一可以反射的注解)

限定注解的而保留策略

@Retention(RetentionPolicy.RUNTIME)//保留策略
@interface MyAnno1{
    
}

讀取注解

反射泛型信息:

Class --> Type getGenericSuperclass()
Type --> ParameterizedType,把Type強(qiáng)轉(zhuǎn)為ParameterizedType類型
ParameterizedType --> 參數(shù)化類型 = A<String>
ParameterizedType :Type[]  getActualTypeArguments(),A<String>中的String
Type[]就是Class[],我們就得到了類型參數(shù)了!

通過(guò)上述描述的步驟既可以獲的類型參數(shù)

public class Demo1 {
    @Test
    public void fun1(){
        new B();//執(zhí)行得到j(luò)ava.lang.String
    }
}
class A<T> {
    public A() {
        /*
         * 在這里獲取子類傳遞的泛型信息,要得到一個(gè)Class
         */
//      Class clazz = this.getClass();//得到子類的類型
//      Type type = clazz.getGenericSuperclass();//獲取傳遞給父類參數(shù)化類型
//      ParameterizedType pType=(ParameterizedType)type;//它就是A<String>
//      Type[] types = pType.getActualTypeArguments();//它就是一個(gè)Class數(shù)組
//      Class c = (Class)types[0];
//      System.out.println(c.getName());//String或Integer
        
        //將上面注釋的內(nèi)容變成一句話
        Class c = (Class)((ParameterizedType)(this.getClass().
                getGenericSuperclass())).getActualTypeArguments()[0];
        System.out.println(c.getName());
    }
}
class B extends A<String> {
    
}
class C extends A<Integer> {
    
}

反射注解

上面講述了如何通過(guò)反射來(lái)得到類的類型,那么要通過(guò)反射得到注解,要求注解的保留策略必須是RUNTIME

反射注解需要從作用目標(biāo)開始反射

  • 類上的注解,需要使用Class來(lái)獲取
  • 方法上的注解需要Method來(lái)獲取
  • 構(gòu)造器上的注解需要Constructor來(lái)獲取
  • 成員山谷的需要使用Field來(lái)獲取

一下?lián)碛锌梢垣@取注解的方法:

  • Class:
  • Method、Constructor、Field有共同的父類:AccessibleObject
    它們都有一個(gè)方法:
  • Annotation getAnnotation(Class),返回目標(biāo)上指定類型的注解
  • Annotation[] getAnnoations(),返回目標(biāo)注解上所有的注解

定義一個(gè)注解MyAnno1 ,在定義一個(gè)類A來(lái)使用注解

@MyAnno1(name="A類",age=20,sex="男")
class A{
    @MyAnno1(name="test1方法",age=10,sex="女")
    public void test(){
        
    }
}
@Retention(RetentionPolicy.RUNTIME)//注意聲明保留策略,否則獲取不到
@interface MyAnno1 {
    String name();
    int age();
    String sex();
}

通過(guò)下面的代碼來(lái)演示如何獲得作用在A類上的注解

public class Demo2 {
       @Test
    public void test1(){
        /*
         * 1.得到作用目標(biāo)
         */
        Class<A> c = A.class;
        /*
         * 2.獲取指定類型的注解
         */
        MyAnno1 myAnno1 = c.getAnnotation(MyAnno1.class);
        System.out.println(myAnno1);//結(jié)果@demo2.MyAnno1(name=A類, age=20, sex=男)
    }

    @Test
    public void test2() throws NoSuchMethodException, SecurityException{
        /*
         * 1.得到作用目標(biāo)
         */
        Class<A> c = A.class;
        Method method = c.getMethod("test");
        
        /*
         * 2.獲取指定類型的注解(獲取方法上的注解)
         */
        MyAnno1 myAnno1 = method.getAnnotation(MyAnno1.class);
        System.out.println(myAnno1.name()+ ", " + myAnno1.age() + ", " +myAnno1.sex());
    }
}

通過(guò)上述內(nèi)容,我們了解了什么是如何通過(guò)反射獲取類型參數(shù),以及什么是注解,注解該如何通過(guò)反射獲取,那么作為練習(xí),下面就完成通過(guò)注解來(lái)寫一個(gè)BaseDao的實(shí)驗(yàn)

完成注解案例

首先我們根據(jù)實(shí)驗(yàn)的分析,創(chuàng)建注解類

/**  
* <p>Title: Table</p>  
* <p>Description: Table 注解類用于標(biāo)識(shí)哪個(gè)對(duì)象對(duì)應(yīng)數(shù)據(jù)庫(kù)的哪一張表,作用在類上</p>  
* @author guqin  
* @date 2018年9月23日  
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**  
* <p>Title: Column</p>  
* <p>Description: 該注解類用于將數(shù)據(jù)庫(kù)字段映射到j(luò)ava對(duì)象屬性上</p>  
* @author guqin  
* @date 2018年9月23日  
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}
/**  
* <p>Title: ID</p>  
* <p>Description: ID注解類用于在對(duì)象屬性上標(biāo)識(shí)哪一個(gè)字段是數(shù)據(jù)庫(kù)主鍵</p>  
* @author guqin  
* @date 2018年9月23日  
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ID {
    String value();
}

為什么沒(méi)有數(shù)據(jù)庫(kù)名的注解呢,眾所周知,連接數(shù)據(jù)庫(kù)需要指定庫(kù)名,用戶名和密碼才能訪問(wèn),這些信息都是配置在外部的配置文件中的,比如JDBC、Hibernate或者其他,于此同時(shí)還會(huì)使用數(shù)據(jù)庫(kù)連接池比如DBCP、C3P0連接池等,那么數(shù)據(jù)庫(kù)名及用戶名密碼就會(huì)配置在這些的配置文件當(dāng)中,比如可以寫一個(gè)jdbc.properties,所以是不需要指定庫(kù)名的注解的而且這中信息還是多個(gè)對(duì)象公用的。
下面以查詢user表為例來(lái)映射一個(gè)User對(duì)象:

import guqing.basedao.Column;
import guqing.basedao.ID;
import guqing.basedao.Table;

/**  
* <p>Title: User</p>  
* <p>Description: </p>  
* @author guqin  
* @date 2018年9月23日  
*/
@Table("user")//它的值表示當(dāng)前類對(duì)應(yīng)的表
public class User {
    @ID("u_id")//當(dāng)前屬性對(duì)應(yīng)的列明,而且說(shuō)明這個(gè)列是主鍵列
    private String uid;
    
    @Column("uname")
    private String username;
    
    @Column("password")
    private String password;
    
    @Column("state")
    private boolean state;
    
    @Column("price")
    private double price;
    
    //get set方法省略
}

完成了以上工作之后,現(xiàn)在就需要:

  • 獲取注解的信息
  • 拼接sql語(yǔ)句查詢數(shù)據(jù)庫(kù)
  • 映射結(jié)果集

獲取注解信息

package guqing.basedao;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**  
* <p>Title: MatchField</p>  
* <p>Description: 該類用于字段匹配,將數(shù)據(jù)庫(kù)字段與java對(duì)象屬性映射 </p>  
* @author guqin  
* @date 2018年9月26日  
*/
public class MatchField {
    private static String primary;//數(shù)據(jù)庫(kù)主鍵
    private static String primaryName;//標(biāo)有@ID注解的對(duì)象屬性名
    
    //通過(guò)單例設(shè)計(jì)模式,返回唯一實(shí)例
    private static MatchField matchField = new MatchField();
    //私有構(gòu)造方法,對(duì)外提供獲取該對(duì)象的方法來(lái)拿到唯一靜態(tài)實(shí)例
    private MatchField(){}
    
    /**
    * @Title: getMatchFieldInstance  
    * @Description: 獲取該對(duì)象的句柄  
    * @param @return
    * @return MatchField
    * @throws
     */
    public static MatchField getMatchFieldInstance() {
        return matchField;
    }
    
    /**
    * @Title: MappingField2Map  
    * @Description: 字段映射方法,返回一個(gè)Map,key=對(duì)象屬性名 ,value=數(shù)據(jù)庫(kù)字段名
    * @param @param beanClass
    * @param @return
    * @return Map<String,String>
    * @throws
     */
    public Map<String,String> MappingField2Map(Class<?> beanClass){
        Map<String,String> fieldMapping = new HashMap<String,String>();
        
        //反射獲取到主鍵的值
        Field[] fields = beanClass.getDeclaredFields();
        for(Field field : fields){//遍歷之
            ID id = field.getAnnotation(ID.class);
            Column column = field.getAnnotation(Column.class);
            if(id!=null) {
                //拿到至關(guān)重要的數(shù)據(jù)庫(kù)主鍵字段與@ID注解的對(duì)象屬性名,將其放到Map中形成映射鍵值對(duì)
                primary = id.value();
                primaryName = field.getName();
                fieldMapping.put(primaryName, primary);//對(duì)象的成員變量名-->表字段名
                
            } else if(column!=null) {
                //拿到其他普通數(shù)據(jù)庫(kù)字段與普通字段對(duì)應(yīng)的java對(duì)象屬性,同樣放到Map中形成映射關(guān)聯(lián)
                fieldMapping.put(field.getName(), column.value());
                
            } else {
                //如果都不是那么默認(rèn)就是字段名-->對(duì)應(yīng)數(shù)據(jù)庫(kù)字段名
                //也就是對(duì)象屬性可以不標(biāo)識(shí)注解表示與數(shù)據(jù)庫(kù)字段同名
                //也可以自己再改進(jìn)一下比如設(shè)置默認(rèn)值或者駝峰命名等
                //甚至還可以寫一個(gè)xml配置文件用于配置數(shù)據(jù)庫(kù)字段與對(duì)象屬性的映射
                //然后讀取配置文件的內(nèi)容,這就比較類似于hibernate,總之自由發(fā)揮吧
                fieldMapping.put(field.getName(), field.getName());
            }
        }
        
        //如果用戶忘記注解主鍵那么拋出異常
        if(primaryName==null||primary==null){
            throw new RuntimeException("syntax error:unknown primary key columns,"
                    + " try again after annotating the primary key in the Javabean with @ID(value)");
        }
        //返回?cái)?shù)據(jù)庫(kù)字段與對(duì)象屬性映射關(guān)系的Map
        return fieldMapping;
    }
    
    /**
    * @Title: precursorSelectSql  
    * @Description: 通過(guò)上面的MappingField2Map方法拼湊查詢語(yǔ)句的前半部分 
    * @param @param beanClass
    * @param @return
    * @return String
    * @throws
     */
    public String precursorSelectSql(Class<?> beanClass){
        //通過(guò)beanClass得到字段映射Map
        Map<String,String> mappingField = MappingField2Map(beanClass);
        
        //拿到j(luò)avaBean所有成員變量
        Field[] fields = beanClass.getDeclaredFields();
        
        //創(chuàng)建查詢語(yǔ)句前驅(qū)
        StringBuilder sb = new StringBuilder("select ");
        //拼湊sql語(yǔ)句
        for(int i=0;i<fields.length;i++){
            sb.append("`"+mappingField.get(fields[i].getName())+"`");//通過(guò)鍵獲得表的字段名稱
            sb.append(" as "+"`"+fields[i].getName()+"`");
            if(i<fields.length-1){
                sb.append(",");//最后一個(gè)不加逗號(hào)
            }
        }
        sb.append(" ");
        return sb.toString();
    }

    /**
    * @Title: getBeanPrimaryName  
    * @Description: 返回javabean中作為主鍵的成員變量名稱  
    * @param @return
    * @return String
    * @throws
     */
    public String getBeanPrimaryName(){
        return primaryName;
    }
}

其實(shí)有了數(shù)據(jù)庫(kù)字段與對(duì)象屬性的映射就可以比較方便的完成查詢更新刪除添加等操作了,都是寫平湊sql語(yǔ)句的活。缺點(diǎn)是只能進(jìn)行簡(jiǎn)單屬性的映射。
下面就是通過(guò)上面的映射方式寫的BaseDao可以參考下一:

package guqing.basedao;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import cn.itcast.jdbc.TxQueryRunner;

/**  
* <p>Title: BaseDao1</p>  
* <p>Description: </p>  
* @author guqin  
* @date 2018年9月23日  
*/
public class BaseDao<T> {
    private QueryRunner qr = new TxQueryRunner();
    private Class<T> beanClass;//通過(guò)父類獲取子類類型
    private String primaryName;//Dao主鍵字段名稱
    private String tablename;//表名稱
    private Map<String,String> mappingField;//存儲(chǔ)字段映射
    //獲取到MappingField對(duì)象
    private MatchField matchField = MatchField.getMatchFieldInstance();
    
    //構(gòu)造方法
    @SuppressWarnings("unchecked")
    public BaseDao(){
        //通過(guò)父類獲取子類類型
        beanClass = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        
        //先獲取字段映射Map
        mappingField = matchField.MappingField2Map(beanClass);
        //再獲取主鍵名稱
        primaryName = matchField.getBeanPrimaryName();
        
        //獲取到表名稱
        Table table = beanClass.getAnnotation(Table.class);
        if(table!=null){
            tablename = table.value();
            
        } else {
            String clazzSimpleName = beanClass.getSimpleName();
            tablename = clazzSimpleName.substring(0, 1).toLowerCase() + clazzSimpleName.substring(1);
        }
    }
    
    public void save(T bean) throws SQLException{
        //String sql ="insert into 表名 values(幾個(gè)?)";
        
        //通過(guò)反射將類中屬性的個(gè)數(shù)清楚就是問(wèn)號(hào)的個(gè)數(shù)
        Field[] fields = beanClass.getDeclaredFields();

        //獲取成員變量上的注解
        List<Object> params = new LinkedList<Object>();
        
        String sql ="insert into " + "`"+tablename +"`"+" values(";
        //拼湊sql字符串
        for(int i=0;i<fields.length;i++){
            sql += "?";
            //拼湊參數(shù)
            try {
                params.add(beanClass.getMethod(getGetMethodString(fields[i].getName())).invoke(bean));
            } catch (Exception e) {
                
                try {
                    Object param = beanClass.getMethod(getIsMethodString(fields[i].getName())).invoke(bean);
                    if(param=="false"){
                        params.add(0);
                    }else if(param=="true"){
                        params.add(1);
                    }else{
                        params.add(param);
                    }
                    
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
            if(i < fields.length-1){
                sql +=",";
            }
        }
        sql += ")";
        
        qr.update(sql,params.toArray());
    }
    
    
    /**
    * @Title: update  
    * @Description: 更新方法  
    * @param @param bean
    * @return void
    * @throws
     */
    public void update(T bean){
        try {
            Map<String,Object[]> updateSqlParam = bean2UpdateSql(bean);
            
            /*
             * update car_number_track set ...+where cid=cid子句
             */
            qr.update((String) updateSqlParam.get("sql")[0], updateSqlParam.get("params"));
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    
    /**
    * @Title: baseDelete  
    * @Description: 根據(jù)主鍵刪除  
    * @param @param id
    * @param @return
    * @return Boolean
    * @throws
     */
     public void deleteById(Object id){
         try{
            String sql = "delete from " + "`" + tablename +"`"+ " where " + mappingField.get(primaryName) +"=?";
            
            qr.update(sql,id);
         } catch (Exception e) {
             e.printStackTrace();
            throw new RuntimeException(e);
         }
     }     
        
     
     /**
     * @Title: get  
     * @Description: 通過(guò)主鍵查詢  
     * @param @param id
     * @param @return
     * @return T
     * @throws
      */
     public T get(Object id) {
         try {
            String preSelectSql =  matchField.precursorSelectSql(beanClass);
            preSelectSql = preSelectSql + "from " + "`" + tablename +"`" + " where " + mappingField.get(primaryName)+"=?";
            
            return qr.query(preSelectSql, new BeanHandler<T>(beanClass),id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
     }
     
     /**
     * @Title: list  
     * @Description: 查詢方法  
     * @param @return
     * @return List<T>
     * @throws
      */
     public List<T> list(){
        try {
            //查詢語(yǔ)句的前半部分 + 用戶自定義的后半部分查詢語(yǔ)句
            String querySql = matchField.precursorSelectSql(beanClass) + Query.getThatSql();
            
            if(querySql.contains(":")||querySql.contains("?")){
                throw new RuntimeException("Syntax error: the number of parameters is insufficient."
                        + " Please try again after checking[大哥參數(shù)個(gè)數(shù)沒(méi)給夠]");
            }
            
            return qr.query(querySql, new BeanListHandler<T>(beanClass));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
     }

    /**
    * @Title: getGetMethodString  
    * @Description: 通過(guò)成員變量屬性名稱獲取到set方法  
    * @param @param fieldName
    * @param @return
    * @return String
    * @throws
     */
    private String getGetMethodString(String fieldName) {
        String getMethodString = "get" + fieldName.substring(0, 1).toUpperCase() +
                fieldName.substring(1);
        return getMethodString;
    }
    
    private String getIsMethodString(String fieldName) {
        String getMethodString = "is" + fieldName.substring(0, 1).toUpperCase() +
                fieldName.substring(1);
        return getMethodString;
    }

    private Map<String,Object[]> bean2UpdateSql(T bean){
        List<Object> params = new ArrayList<Object>();
        Map<String,Object[]> updateSqlParams = new HashMap<String,Object[]>();
        
        //給出sql語(yǔ)句的前半部分
        StringBuilder firstHalfSql = new StringBuilder("update "+"`"+tablename+"`");//前綴
        StringBuilder setSql = new StringBuilder();//后綴
        
        Object primaryValue = null;
        //先在第一個(gè)占位符也就是cid出添加參數(shù)
        setSql.append(" set "+"`"+mappingField.get(primaryName)+"`"+"=?");
        try {
            primaryValue = beanClass.getMethod(getGetMethodString(primaryName)).invoke(bean); 
            params.add(primaryValue);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } 
        
        /*
         * 1.判斷條件,完成sql中追加where子句
         * 2.創(chuàng)建ArrayList,保存參數(shù)
         */
        Field[] fields = beanClass.getDeclaredFields();
        for(Field field : fields){
            if(field.getName().equals(primaryName)){
                continue;//略過(guò)主鍵
            }
            Column column = field.getAnnotation(Column.class);
            try {
                String returnType = beanClass.getMethod(getGetMethodString(field.getName())).getGenericReturnType().getTypeName();
                Object getMethod = beanClass.getMethod(getGetMethodString(field.getName())).invoke(bean);
            
                if(returnType.contains("String")||returnType.contains("Integer")){
                    String param = (String) getMethod;
                    if(param!=null && !param.trim().isEmpty() && param!="null" && column!=null){
                        setSql.append(","+"`"+column.value()+"`"+"=?");
                        params.add(param);
                        
                    } else if(param!=null && !param.trim().isEmpty() && param!="null" && column==null) {
                        setSql.append(","+"`"+ mappingField.get(field.getName()) +"`"+"=?");
                        params.add(param);
                    }
                }else if(returnType.contains("double")){
                    double param =  (double)getMethod;
                    if(param!=0.0 && column!=null){
                        setSql.append(","+"`"+column.value()+"`"+"=?");
                        params.add(param);
                        
                    } else if(column==null) {
                        setSql.append(","+"`"+ mappingField.get(field.getName()) +"`"+"=?");
                        params.add(param);
                    }
                }else if(returnType.contains("int")){
                    int param = (int) getMethod;
                    if(param!=0 && column!=null){
                        setSql.append(","+"`"+column.value()+"`"+"=?");
                        params.add(param);
                        
                    } else if(column==null) {
                        setSql.append(","+"`"+ mappingField.get(field.getName()) +"`"+"=?");
                        params.add(param);
                    }
                } else if(returnType.contains("boolean")){
                    Object param =  (Object)getMethod;
                    if(column!=null && param!=null && !param.equals("null")){
                        setSql.append(","+"`"+column.value()+"`"+"=?");
                        params.add((boolean)param);
                        
                    } else if(param==null){
                        continue;
                    }else{
                        setSql.append(","+"`"+ mappingField.get(field.getName()) +"`"+"=?");
                        params.add((boolean)param);
                    }
                }
            } catch (Exception e) {
                try {
                    String returnType = beanClass.getMethod(getIsMethodString(field.getName())).getGenericReturnType().getTypeName();
                    Object getMethod = beanClass.getMethod(getIsMethodString(field.getName())).invoke(bean);
                    
                    if(returnType.contains("boolean")){
                        Object param =  (Object)getMethod;
                        if(column!=null && param!=null && !param.equals("null")){
                            setSql.append(","+"`"+column.value()+"`"+"=?");
                            params.add((boolean)param);
                            
                        } else if(param==null){
                            continue;
                        }else{
                            setSql.append(","+"`"+ mappingField.get(field.getName()) +"`"+"=?");
                            params.add((boolean)param);
                        }
                    }
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
            
        }
        /*
         * 追加where語(yǔ)句的參數(shù)
         */
        String finalSql = firstHalfSql.append(setSql).append(" where "+
                        "`"+mappingField.get(primaryName)+"`"+"=?").toString();
        params.add(primaryValue);
        
        String[] sql = {finalSql};
        
        updateSqlParams.put("sql",sql);
        updateSqlParams.put("params", params.toArray());
        
        return updateSqlParams;
    }
    
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,248評(píng)論 0 4
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,985評(píng)論 0 9
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射...
    有_味閱讀 3,185評(píng)論 0 26
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,674評(píng)論 1 32
  • http://app.yiyiwawa.com/app_share_myreading.aspx?hbid=243...
    劉家洋洋閱讀 185評(píng)論 0 0

友情鏈接更多精彩內(nèi)容