JDBC之运用反射模拟ORM
2009-10-23 16:47 BlueDream 阅读(2076) 评论(0) 编辑 收藏 举报上一篇我们使用了结果集元数据实现了将结果集封装到List<Map<K,V>>中返回.
ORM:对象-关系数据库映射(Object/Relation Mapping).以简单的方式提供了领域对象模型与数据库间的映射.典型的Hibernate,iBatis
这里仅是练习.功能还很弱.
程序目的:传入sql语句返回字段如果和传入对象模型的setXX方法对应则自动赋值.并返回该对象.
首先构建User模型.应该和数据库字段相对应.数据库结构如下:
User模型:
package com.test.reflection;
public class User {
private Integer id;
private String firstname;
private String lastname;
private Integer age;
// 约定的默认构造器(必须)
public User() {
}
@Override
public String toString() {
return "id: " + this.id + " firstname: " + this.firstname
+ " lastname: " + this.lastname + " age: " + this.age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public class User {
private Integer id;
private String firstname;
private String lastname;
private Integer age;
// 约定的默认构造器(必须)
public User() {
}
@Override
public String toString() {
return "id: " + this.id + " firstname: " + this.firstname
+ " lastname: " + this.lastname + " age: " + this.age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
然后是上次提供的DBUtils:
package com.test.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public final class DBUtils {
private static String url = "jdbc:mysql://localhost:3306/mytest";
private static String user = "root";
private static String password = "root";
// 获得连接
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
// 释放连接
public static void free(ResultSet rs, PreparedStatement ps, Connection conn) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
// 加载驱动
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("驱动加载出错");
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public final class DBUtils {
private static String url = "jdbc:mysql://localhost:3306/mytest";
private static String user = "root";
private static String password = "root";
// 获得连接
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
// 释放连接
public static void free(ResultSet rs, PreparedStatement ps, Connection conn) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
// 加载驱动
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("驱动加载出错");
}
}
}
最后最主要的ORMExample:
package com.test.reflection;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import com.test.jdbc.DBUtils;
public class ORMExample {
public static void main(String[] args) {
User user = (User) getObject(
"select id, firstname, lastname, age from users where id = 1",
User.class);
System.out.println(user);
}
public static <T>T getObject(String sql, Class<T> clazz) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtils.getConn();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
// 必须有无参的构造函数
T obj = null;
// 获得共有方法
Method[] ms = clazz.getMethods();
// 通过结果集元数据获得列数
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
obj = clazz.newInstance();
for (int i = 1; i <= columnCount; i++) {
String colName = rsmd.getColumnLabel(i);
String methodName = "set"
+ colName.substring(0, 1).toUpperCase()
+ colName.substring(1);
// 循环读取所有方法
for (Method m : ms) {
// 列名和set方法名如果相同则调用该方法
if (methodName.equals(m.getName())) {
m.invoke(obj, rs.getObject(colName));
}
}
}
}
return obj;
} catch (Exception e) {
throw new RuntimeException();
} finally {
DBUtils.free(rs, ps, conn);
}
}
}
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import com.test.jdbc.DBUtils;
public class ORMExample {
public static void main(String[] args) {
User user = (User) getObject(
"select id, firstname, lastname, age from users where id = 1",
User.class);
System.out.println(user);
}
public static <T>T getObject(String sql, Class<T> clazz) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtils.getConn();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
// 必须有无参的构造函数
T obj = null;
// 获得共有方法
Method[] ms = clazz.getMethods();
// 通过结果集元数据获得列数
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
obj = clazz.newInstance();
for (int i = 1; i <= columnCount; i++) {
String colName = rsmd.getColumnLabel(i);
String methodName = "set"
+ colName.substring(0, 1).toUpperCase()
+ colName.substring(1);
// 循环读取所有方法
for (Method m : ms) {
// 列名和set方法名如果相同则调用该方法
if (methodName.equals(m.getName())) {
m.invoke(obj, rs.getObject(colName));
}
}
}
}
return obj;
} catch (Exception e) {
throw new RuntimeException();
} finally {
DBUtils.free(rs, ps, conn);
}
}
}
数据库值如下:
代码运行结果为:
id: 1 firstname: 咖 lastname: 咖 age: 23
具体的方法可见代码注释.通过反射获取方法和元数据的列比较相同的便动态执行.
下篇将要介绍自己写连接池.待续.