基于 @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)