如今框架横行,很多人用的得心应手,可是很多人都没有了解过底层的东西,导致往后去学习别的框架的时候就不会那么顺利。就比如我们平时在写代码时,都会用MyBatis或者JPA,但是你了解过他们是怎么匹配字段的吗?如果突然不让使用框架,你还能那么轻松的写出来吗。
在原生JDBC的场景下,我们如何将查询的字段自动封装到对象中呢?就是通过Java的反射实现,这是一个很实用的技术。我们看一下下面的代码
这是一个数据库表对应的类,其中使用有驼峰命名
@Data
@TableName("t_admin")
public class Admin implements Serializable {
@TableId("username")
private String username;//用户名
private String nickName;//用户昵称
private String password;//用户密码
private String email;//用户邮箱
private String avatar;//用户头像
private String qq;
private String weChat;
private String weChatQrCode;//微信收款码
private String authorImage;//管理员主页图
private String alipayQrCode;//管理员主页图
private String weChatCode;//微信二维码
private Integer type;//用户类型
}
对于这样一个类或者数据库,我们当然没有感觉它有多繁琐,可是当不同的类和数据表,或者表很多表或者类时,那将会怎么样呢?是不是觉得不好写,而且不容易维护,一旦程序出现变动,整个映射都需要重新更改。那么我们来看一下如何通过反射实现字段映射封装。
//可以封装起来,传入class或者对象
Admin admin;
try {
//这里可以通过反射创建
admin = new Admin();
String regex = "[A-Z]";//匹配驼峰规则
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, root, passwd);
PreparedStatement ps = conn.prepareStatement("select * from t_admin where username = ? and password = ?");
ps.setString(1, username);
ps.setString(2, MyConfig.md5Code(password));
ResultSet rs = ps.executeQuery();
Class<? extends Admin> aClass = admin.getClass();
Field[] fields = aClass.getDeclaredFields();//获得class中的属性
StringBuilder sb = new StringBuilder();
while (rs.next()) {
//替换驼峰字符
for (int i = 0; i < fields.length; i++) {
for (int j = 0; j < fields[i].getName().length(); j++) {
char ch = fields[i].getName().charAt(j);
if ((ch + "").matches(regex)) {
sb.append("_" + (ch + "").toLowerCase());
} else {
sb.append(ch);
}
}
//破坏私有属性
fields[i].setAccessible(true);
//这里可以根据字段进行判断,因为数据库字段是string和integer,所以只判断两个类
//这句代码的意思是判断两个类型是否是一个类型,可以根据自己的数据库进行编写(注意原始数据类型即可)
boolean b = String.class.isAssignableFrom(fields[i].getType());
if (b) {
fields[i].set(admin, rs.getString(sb.toString()));
} else {
fields[i].set(admin, rs.getInt(sb.toString()));
}
//重置sb(StringBuilder线程不安全,如果在多线程下请使用StringBuffer)
sb.setLength(0);
}
}
rs.close();
ps.close();
conn.close();
System.out.println(admin);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
注意需要导入mysql
驱动
是不是觉得很简单