实现原理:
* 获取结果集的元数据,得到各列的列名称
* 使用反射,创建参数clazz的对象,调用对象与列名称相对应的所有的set方法
* 【注意】请确保结果集的列名称和Javabean的属性名称、个数和类型完全相同
* 如果属性名称和数据库字段名称不同,可以在sql查询语句中使用 AS 关键字为列起别名
代码,附我的Mysql操作类:
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Mysql操作类,封装了连接断开数据库、使用预编译的SQl模板快速增删改查方法,时间紧迫,异常没有处理完善
* 封装了将查询记录集转成Javabean集合和遍历记录集的方法
*
* @author 王凯旋
*
*/
public class Mysql {
private static Mysql mysql;
private Connection conn;
private Statement stmt;
private Map<String,PreparedStatement> pstmt;
private Mysql() {
}
private Mysql(String url, String username, String password) {
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, username, password);
stmt = conn.createStatement();
pstmt = new HashMap<String, PreparedStatement>();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 使用单例模式懒汉式,调用构造方法,创建本类实例
*
* @param mysql
* 地址,例如jdbc:mysql://localhost/table_name,
* database_name为你想要连接的数据库名
* @param username
* mysql管理员用户名,如root
* @param password
* mysql管理员密码
* @return 返回本类实例
*/
public static synchronized Mysql getInstance(String url, String username,
String password) {
if (mysql == null) {
mysql = new Mysql(url, username, password);
}
return mysql;
}
/**
* 将sql语句预编译成sql模板,储存该模板到本类内置的map集合,键为key
*
* @param sql
* sql语句,可以带占位符
* @return sql模板
*/
public void setPstmt(String key,String sql) {
try {
PreparedStatement ps = conn.prepareStatement(sql);
pstmt.put(key, ps);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 快速查询,该方法先检查内置的map集合中是否有预编译的sql模板,如果有就使用模板进行查询,否则使用普通查询
* 使用setPstmt()方法可设置sql模板
*
* @param stmt
* 存储到map集合中的sql模板的key,或者要执行的sql语句
* @param arr
* 替换占位符的参数,可变参数,模板中有几个问号就需要几个参数。支持任意类型,当使用普通查询时忽略该参数
* @return 查询结果集
*/
public ResultSet Query(String stmt, Object... arr) {
try {
for (Entry<String, PreparedStatement> en : this.pstmt.entrySet()) {
if (en.getKey().equals(stmt)) {
PreparedStatement ps = en.getValue();
for (int i = 0; i < arr.length; i++) {
ps.setObject(i + 1, arr[i]);
}
return ps.executeQuery();
}
}
return this.stmt.executeQuery(stmt);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 快速更新,该方法先检查内置的map集合中是否有预编译的sql模板,如果有就使用模板进行更新,否则使用普通更新
* 使用setPstmt()方法可设置sql模板
*
* @param pstmt
* 可调用getPstmt()方法得到
* @param arr
* 替换占位符的参数,可变参数,模板中有几个问号就需要几个参数。Object,支持任意类型
* @return 查询结果集
*/
public int Update(String stmt, Object... arr) {
try {
for (Entry<String, PreparedStatement> en : this.pstmt.entrySet()) {
if (en.getKey().equals(stmt)) {
PreparedStatement ps = en.getValue();
for (int i = 0; i < arr.length; i++) {
ps.setObject(i + 1, arr[i]);
}
return ps.executeUpdate();
}
}
return this.stmt.executeUpdate(stmt);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
/**
* 断开mysql连接,释放资源
*/
public void close() {
if (stmt != null) {
try {
stmt.close();
stmt = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
conn = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
mysql = null;
}
/**
* 遍历输出记录集的所有记录,包括列名称
* 此方法和getList()方法都会调用rs的close()方法释放资源
* @param rs 要遍历的记录集
*/
public static void showResult(ResultSet rs) {
try {
//获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
//得到总列数
int lie=rsmd.getColumnCount();
//循环输出列名称
for (int i = 1; i <= lie; i++) {
System.out.print(rsmd.getColumnName(i)+"\t");
}
System.out.println();
//记录行数
int hang =0;
while (rs.next()) {
hang++;
//循环输出此行记录的每一列数据
for (int x = 1; x <= lie; x++) {
System.out.print(rs.getString(x)+"\t");
}
System.out.println();
}
//输出统计信息
System.out.println(lie+"列,"+hang+"条记录。");
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 一个神奇的方法!花了两个钟头才写出来,结合了Java的泛型和反射技术!
* 将mysql的查询结果集封装成Javabean储存到List集合中
*
* 实现原理:
* 获取结果集的元数据,得到各列的列名称
* 使用反射,创建参数clazz的对象,调用对象与列名称相对应的所有的set方法
* 【注意】请确保结果集的列名称和Javabean的属性名称、个数和类型完全相同
* 如果属性名称不同,可以在sql查询语句中使用 AS 关键字为列起别名
* 此方法和showResult()方法都会调用rs的close()方法释放资源
*
* @param rs 要封装到Javabean的结果集
* @param clazz Javabean的类对象,如:User.class,本方法使用泛型技术,
* 根据传入的class确定返回的集合类型
* @return 返回储存Javabean的List集合
*/
public static <T> List<T> getList(ResultSet rs,Class<T> clazz) {
List<T> al =null;
try {
ResultSetMetaData rsmd = rs.getMetaData();
int lie=rsmd.getColumnCount();
al = new ArrayList<T>();
while (rs.next()) {
T t = null;
try {
t = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
for (int j = 0; j < lie; j++) {
// System.out.println("set"+rsmd.getColumnName(j+1)+"::"+rs.getObject(j+1));
invokeX(t, "set"+rsmd.getColumnName(j+1), rs.getObject(j+1));
}
al.add(t);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return al;
}
/**
* 接收一个对象,根据传入的方法名称,调用方法(支持有参多参或无参)【反射实现】
* @param o 要处理的对象
* @param name 方法的名称,忽略大小写
* @param oo 参数,无参可使用null
* @return 如果有返回值就返回,没有返回null
*/
private static Object invokeX(Object o,String name,Object...oo) {
Class clazz =o.getClass();
Method[] mm=clazz.getDeclaredMethods();
for (Method method : mm) {
if (method.getName().equalsIgnoreCase(name)) {
try {
return method.invoke(o, oo);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
}
使用了这个Mysql操作类,再写Dao层真是太简单了~
package com.kxrjkf.user.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.ResourceBundle;
import com.kxrjkf.user.dao.UserDao;
import com.kxrjkf.user.domin.User;
import com.kxrjkf.user.utils.Mysql;
public class UserDaoImpl implements UserDao {
private static Mysql mysql = null;
static {
ResourceBundle rb = ResourceBundle.getBundle("config");
mysql = Mysql.getInstance(rb.getString("url"),
rb.getString("username"), rb.getString("password"));
String biao = rb.getString("biao");
// add方法的sql模板
mysql.setPstmt("addstmt", "insert into " + biao + " VALUES(null,?,?,?) ;");
// delete方法的sql模板
mysql.setPstmt("delstmt", "DELETE FROM " + biao + " where id=? ;");
// edit方法的sql模板
mysql.setPstmt("upstmt", "UPDATE " + biao
+ " SET name=?,phone=?,`like`=? where id=? ;");
// findId方法的sql模板
mysql.setPstmt("findIdstmt","select * from " + biao + " where id=? ;" );
// getList方法的sql模板
mysql.setPstmt("liststmt", "select * from " + biao + " ;");
// 分页getList方法的sql模板
mysql.setPstmt("fenyestmt","select * from " + biao + " limit ?,? ;" );
// getZong方法的sql模板
mysql.setPstmt("zongstmt", "select count(*) from " + biao + " ;");
}
/**
* 添加客户
* @param user 想要添加的客户
*/
public void add(User user) {
mysql.Update("addstmt", user.getName(), user.getPhone(),
user.getLike());
}
/**
* 删除客户
* @param id 客户的id
*/
public void delete(int id) {
mysql.Update("delstmt", id);
}
/**
* 修改客户资料
* @param id 客户id
* @param user 客户
*/
public void update(int id, User user) {
mysql.Update("upstmt", user.getName(), user.getPhone(),
user.getLike(), id);
}
/**
* 根据id查询客户
* @param id 客户id
* @return 找到返回客户信息,找不到返回null
*/
public User findId(int id) {
List<User> u = mysql.getList(mysql.Query("findIdstmt", id),
User.class);
User user = null;
if (u.size() != 0) {
user = u.get(0);
}
return user;
}
/**
* 获取所有客户
* @return List集合
*/
public List<User> getList() {
return mysql.getList(mysql.Query("liststmt"), User.class);
}
/**
* 分页获取客户集合
* @param qishi 开始的位置
* @param tiaoshu 要查询的条数
* @return 返回本页客户集合
*/
public List<User> getList(int qishi, int tiaoshu) {
return mysql.getList(mysql.Query("fenyestmt", qishi, tiaoshu),
User.class);
}
/**
* 获取客户总数
* @return 客户总数
*/
public int getZong() {
ResultSet rs = mysql.Query("zongstmt");
try {
rs.next();
return rs.getInt(1);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
//测试
// public static void main(String[] args) {
// new UserDaoImpl().add(new User("张三", "3333", "三三"));
// new UserDaoImpl().delete(5);
// new UserDaoImpl().update(1, new User("小白", "8888888", "睡觉"));
// System.out.println(new UserDaoImpl().findId(3));
// for (User u : new UserDaoImpl().getList(1,2)) {
// System.out.println(u);
// }
// UserDaoImpl udi = new UserDaoImpl();
// System.out.println(udi.getZong());
// }
}
这篇博客介绍了如何利用Java的泛型和反射技术将MySQL查询结果集转换为JavaBean集合。通过创建Mysql操作类,实现了连接数据库、预编译SQL模板以及将查询结果自动映射到JavaBean对象的功能。博主强调了结果集的列名必须与JavaBean的属性名、数量和类型完全一致,并提供了详细的代码示例和操作步骤。
682

被折叠的 条评论
为什么被折叠?



