1. 程式人生 > 實用技巧 >基於 @SelectProvider 註解實現的無侵入的通用Dao

基於 @SelectProvider 註解實現的無侵入的通用Dao

基於 @SelectProvider 註解實現的無侵入的通用Dao

程式碼設計

//實體
@Data //lombok
public class User {
    private Integer id;
    /**
    * 是否可以,0/1
    */
    private Boolean available;
    /**
    * 使用者名稱
    */
    private String username;
    /**
    * 密碼
    */
    private String password;
    /**
    * 記錄生成時間,預設當前時間
    */
    private Date gmtCreate;
    /**
    * 記錄修改時間,預設當前時間
    */
    private Date gmtModified;
}

//通用dao
public interface BaseDao<E,I> {

    @SelectProvider(type = BaseDaoProvider.class,method = "getById")
    E getById(I id);

}

//具體dao
public interface UserDao extends BaseDao<User,Integer> {
}

//通用Provider,通過泛型反射獲取實體型別
public class BaseDaoProvider {

    public String getById(ProviderContext context) {
        return new SQL() {{
            SELECT(getTableColumns(context));
            FROM(getTableName(context));
            WHERE("id = #{id}");
        }}.toString();
    }

    private String getTableName(ProviderContext context){
        Class clazz = getEntityType(context);
        return SQLUtil.getTableName(clazz);
    }

    private String getTableColumns(ProviderContext context){
        Class clazz = getEntityType(context);
        return SQLUtil.getTableColumns(clazz);
    }

    private Class getEntityType(ProviderContext context) {
        return (Class) ((ParameterizedType) (context.getMapperType().getGenericInterfaces()[0])).getActualTypeArguments()[0];
    }
}

//sql工具類,通過實體獲取表名和列名,但資料庫和實體必須遵循下劃線轉駝峰規則
//即表列名必須全小寫,多單詞以下劃線分割,實體屬性必須為駝峰規則
public class SQLUtil {

    private static String toLowerCase(String camelStr) {
        String lowerCase = camelStr.replaceAll("[A-Z]", "_$0").toLowerCase();
        if (lowerCase.startsWith("_")){
            lowerCase = lowerCase.substring(1);
        }
        return lowerCase;
    }

    public static String getTableName(Class clazz){
        String className = clazz.getSimpleName();
        String tableName = toLowerCase(className);
        return tableName;
    }

    public static String getTableColumns(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        List<String> fieldNames = new ArrayList<>();
        for (Field field : fields) {
            String fieldName = field.getName();
            String columnName = toLowerCase(fieldName);
            fieldNames.add(columnName);
        }
        String columns = String.join(",",fieldNames);
        return columns;
    }

}

測試

@SpringBootTest
class ApplicationTests {
    @Resource
    private UserDao2 userDao2;

    @Test
    void test1(){
        User user = userDao2.getById(1);
        System.out.println(user);
    }
}

測試結果

  • ==> Preparing: SELECT id,available,username,password,gmt_create,gmt_modified FROM user WHERE (id = ?)
  • ==> Parameters: 1(Integer)
  • <== Total: 1
  • User(id=1, available=true, username=123, password=123, gmtCreate=Tue Dec 15 21:05:57 CST 2020, gmtModified=Tue Dec 15 21:05:57 CST 2020)