java 反射 封装_Java使用反射封装一个方便操作数据库的类

刚开始学JavaWeb时,我是调用N个setter方法将从数据库中查询出的数据封装成JavaBean的,极其繁琐。

后来了解SpringJDBC后,发现它提供的接口非常简单,然后就想自己封装一个简单的用。

原理很简单,就是使用反射代替手动调用 setter 方法,JavaBean中的属性名要和数据库查询语句中的字段名相同,一一对应。

数据库配置文件(config.properities)格式为:

db.url = xxx

db.dbname = xxx

db.user = xxx

db.password = xxx

代码:

package Utils;

import java.io.IOException;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.sql.*;

import java.util.ArrayList;

import java.util.List;

import java.util.Properties;

/**

* 使用示例:

* (三个方法都有可能返回null,返回null则表示数据库操作异常)

* 1. 查询符号指定条件的记录数

* // 必须写成 as count

* int count = DBUtils.queryForCount("select count(1) as count from users where age = ?", age);

*

* 2. 查询出封装好的对象

* 查询出的字段要和欲封装成的对象的属性名一一对应,且需要包含setter方法,不需要加构造函数

* class User {

* private String name;

* private int age;

* public void setName(String name) { this.name = name; }

* public String getName() { return this.name; }

* public void setAge(int age) { this.age = age; }

* public int getAge() { return this.age; }

* }

* // 查询出一条记录并封装成对象,传入User.class,如果要查询出Product对象,则传入Product.class

* User user = DBUtils.queryForObject("select name, age from users where id = ?", User.class, id);

* // 查询出多条记录并封装成对象

* List users = DBUtils.queryForList("select name, age from users where id < ?", User.class, id);

*

* 3. 增删改

* // 删除

* int changedCount = DBUtils.update("delete from users where id = ?", id);

* // 插入

* int changedCount = DBUtils.update("insert into users(name, age) values(?, ?)", name, age);

* // 修改

* int changedCount = DBUtils.update("update user set age = ? where id = ?", newAge, id);

*

* 4. 事务

* (多个update操作共同协同工作时使用事务)

* DBUtils.startTransaction(); // 开启事务

* if (DBUtils.update(xxx) == null) {

* DBUtils.rollback();

* return false; // 失败,返回

* }

* if (DBUtils.update(xxx) == null) {

* DBUtils.rollback();

* return false; // 失败,返回

* }

* DBUtils.commit(); // 成功,提交事务

* return true;

*/

public class DBUtils {

/**

* 线程作用域内,并发安全,可复用

*/

private final static ThreadLocal threadLocal = new ThreadLocal<>();

/**

* 获取数据库链接对象

* @return 数据库连接对象

*/

private static Connection getConnection() {

if (threadLocal.get() == null) {

Properties properties = new Properties();

try {

properties.load(DBUtils.class.getResourceAsStream("config.properties"));

Connection conn = DriverManager.getConnection(

properties.getProperty("db.url") + "/" + properties.getProperty("db.dbname"),

properties.getProperty("db.user"),

properties.getProperty("db.password")

);

threadLocal.set(conn);

} catch (SQLException e) {

System.out.println("【连接数据库时出现异常:" + e.getMessage() + "】");

} catch (IOException e) {

System.out.println("【打开配置文件 config.properties 时出现异常:" + e.getMessage() + "】");

}

}

return threadLocal.get();

}

/**

* 关闭数据库连接

*/

public static void closeConnection() {

if (threadLocal.get() != null) {

try {

threadLocal.get().close();

} catch (SQLException e) {

e.printStackTrace();

}

}

threadLocal.remove();

}

/**

* 查询多条数据并封装成对应的实例

* @param sql 返回多条记录数的查询语句

* @param requireType 要封装成的类的Class对象

* @param params 要绑定到SQL语句上的参数

* @param 要封装成的类的类型

* @return 返回封装好的对象列表

*/

public static List queryForList(String sql, Class requireType, Object... params) {

List ret = new ArrayList<>();

Connection conn = getConnection();

PreparedStatement ps = null;

if (conn == null)

return null;

try {

ps = conn.prepareStatement(sql);

for (int i = 0; i < params.length; i++) { // 绑定参数

ps.setObject(i + 1, params[i]);

}

ResultSet result = ps.executeQuery();

while (result.next()) {

ret.add(requireType.getConstructor().newInstance()); // 创建一个实例

Field[] fields = requireType.getDeclaredFields(); // 获取所有属性

for (Field field : fields) {

// 构造 setter 方法名

String setterName = "set" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);

// 调用对应实例的 setter 方法给它设置属性

Method setter = requireType.getMethod(setterName, field.getType());

setter.invoke(ret.get(ret.size() - 1), result.getObject(field.getName()));

}

}

} catch (Exception e) {

e.printStackTrace();

} finally {

// 仅需关闭 PreparedStatement,关闭它时 ResultSet 会自动关闭

try {

if (ps != null)

ps.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

return ret;

}

/**

* 查询出一条数据并封装成对象

* @param sql 返回一条记录数的查询语句

* @param requireType 要封装成的类的Class对象

* @param params 要绑定到SQL语句上的参数

* @param 要封装成的类的类型

* @return 返回封装好的对象

*/

public static T queryForObject(String sql, Class requireType, Object... params) {

List list = queryForList(sql, requireType, params);

return list == null ? null : list.get(0);

}

/**

* 查询符合指定条件的记录数

* @param sql 查询记录数的SQL语句

* @param params 要绑定到SQL语句上的参数

* @return 返回符合条件的记录数

*/

public static Long queryForCount(String sql, Object... params) {

class Count {

private Long count;

public Count() {}

public void setCount(Long count) {

this.count = count;

}

public Long getCount() {

return this.count;

}

}

Count count = queryForObject(sql, Count.class, params);

return count.getCount();

}

/**

* 执行增删除操作

* @param sql DML SQL语句

* @param params 要绑定到SQL语句上的参数

* @return 影响的数据库记录数目

*/

public static Integer update(String sql, Object... params) {

Connection conn = getConnection();

PreparedStatement ps = null;

Integer rowChanged = null;

try {

ps = conn.prepareStatement(sql);

for (int i = 0; i < params.length; i++) { // 绑定参数

ps.setObject(i + 1, params[i]);

}

rowChanged = ps.executeUpdate();

} catch (SQLException e) {

e.printStackTrace();

return null;

} finally {

try {

if (ps != null)

ps.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

return rowChanged;

}

/**

* 开启事务

*/

public static void startTransaction() {

try {

getConnection().setAutoCommit(false);

} catch (SQLException e) {

e.printStackTrace();

}

}

/**

* 回滚事务

*/

public static void rollback() {

try {

getConnection().rollback();

} catch (SQLException e) {

e.printStackTrace();

} finally {

try {

getConnection().setAutoCommit(true);

} catch (SQLException e) {

e.printStackTrace();

}

}

}

/**

* 提交事务

*/

public static void commit() {

try {

getConnection().commit();

} catch (SQLException e) {

e.printStackTrace();

} finally {

try {

getConnection().setAutoCommit(true);

} catch (SQLException e) {

e.printStackTrace();

}

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值