Java 模拟mybatis映射实体类
使用mybatis也有很长时间了,它的强大也是众所周知的,包括性能和灵活性等方面。说起它的强大,但是对象赋值也是一大亮点了,所以我做了一个模拟
在我的理解中,我觉得可以通过Java的反射机制,来模拟一次mybatis实体类的赋值,将实体类的set方法调用出来,今晚字段赋值,就可以实现,接下来演示一下代码。
1. 准备工作
1.1 Java:版本1.8
1.2 mysql包:5.1.44
其实可以不用跟着我的版本,根据自己的版本来
还需要一个JDBC工具类,因为是通过JDBC连接数据库,采用最原生的方式,实现模拟
JDBC工具类传送门:JDBC工具类
2. 模拟代码
private static<T> T mappingObj(ResultSet resultSet, Class<T> clazz) {
T obj = null;
try {
//实例化映射对象
obj = clazz.newInstance();
//获取映射对象的方法
Method[] methods = clazz.getMethods();
//获取结果集中元数据信息
ResultSetMetaData meta = resultSet.getMetaData();
// 按字段数目循环结果集中记录,进行对象映射
for (int i = 1; i <= meta.getColumnCount(); i++) {
// 构造当前列的set方法名称
String columnName = meta.getColumnName(i);
String methodName = "set" + columnName.replaceAll("[\\.|\\-|\\_]", "");
// 循环查找同名方法,并通过反射调用该方法,设置属性
for (Method method : methods) {
if (method.getName().equalsIgnoreCase(methodName)) {
method.invoke(obj, resultSet.getObject(i));
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
以上就是模拟赋值的核心代码,主要的思路就是靠传进来一个class,实例化获取对象,再利用JDBC的结果集对象,获取到当前连接数据库的表字段,通过Java反射机制,再两者合二为一
运用在实例当中
/**
* 获取数据库下的所有表字段名称
*
* @param dbConfig 数据库配置对象
* @return List集合
*/
public static List<String> getColumnNames(DbConfig dbConfig) {
List<String> columnNames = new ArrayList<>();
Connection connection = getConnection(dbConfig);
PreparedStatement statement = null;
String sql = "SELECT * FROM " + dbConfig.getTableName();
try {
statement = connection.prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println(mappingObj(resultSet, Test.class));
}
//结果集元数据
ResultSetMetaData metaData = statement.getMetaData();
//表列数
int size = metaData.getColumnCount();
for (int i = 0; i < size; i++) {
columnNames.add(metaData.getColumnName(i + 1));
}
logger.info("查询成功" + columnNames);
} catch (SQLException e) {
throw new SqlErrorException("获取数据库表字段失败:" + e.getMessage());
} finally {
closeConnection(connection, null, statement);
}
return columnNames;
}
public static void main(String[] args) {
DbConfig config = new DbConfig();
config.setUrl("127.0.0.1");
config.setPort("3306");
config.setDataBase("coon");
config.setUser("root");
config.setPassWord("root");
config.setDriverClass("com.mysql.jdbc.Driver");
config.setTableName("user");
System.out.println(getColumnNames(config));
}
运用在了一个简单获取表字段的方法中,在一个while循环中可以看到被调用到了,其中Test
是我建立的一个测试类,里面的属性很简单,就是用户名和密码以及手机号码三个,看一下打印台的运行结果
Test{userName='测试用户', passWord='123456', userPhone='13000000000'}
Test{userName='测试用户', passWord='123456', userPhone='13000000000'}
Test{userName='测试用户', passWord='123456', userPhone='13000000000'}
Test{userName='测试用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
Test{userName='默认用户', passWord='123456', userPhone='13000000000'}
21:17:31.952 [main] INFO com.example.web.codegenerator.util.DataBaseUtil - 查询成功[user_id, user_name, password, user_level, user_phone, user_email, user_balance, user_integral, user_card]
21:17:31.952 [main] INFO com.example.web.codegenerator.util.DataBaseUtil - 数据库关闭连接
[user_id, user_name, password, user_level, user_phone, user_email, user_balance, user_integral, user_card]
大功告成,数据库中的几条数据都被打印了出来。这个只是一个思路模型,大致按照我的理解做了一次模拟,粗糙了一点,供大家参考一起学习,可以自行优化封装,说不定会派上用处呢,哈哈。