基于 @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)
上一篇:windows安装和使用latex


下一篇:Java基础-反射机制