一、自制DbUtils
一成不变的生活,太让人难受了,于是我便动手编写了个属于自己的Dbutils 。尽管是有"重复造轮子"一说,可是这让我成长了,让我认识到我和大牛之间的差距。
为了区别其它DbUtils.jar,我用DbUtils的全称DatabaseUtilities来命名文件,即"DatabaseUtilities.jar"
二、运行展示
1.使用SqlRunner对象进行查询操作
1.1 代码
package com.ytt.test;
import com.liurui.growth.*;
import com.ytt.domain.User;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class SqlRunnerTest {
@Test
public void testQuery() throws ClassNotFoundException, IOException, SQLException {
Properties properties = new Properties();
properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);
//------------------------------------------------------------------------------------
SqlRunner sqlRunner = new SqlRunner(connection);
List<User> userList = sqlRunner.query("select * from user where name like ?",
new BeanListHandler<User>(User.class), "%a%");
User user = sqlRunner.query("select * from user where id=?",
new BeanHandler<User>(User.class), 2);
Map<String, Object> map = sqlRunner.query("select * from user where id=?",
new MapHandler<User>(User.class), 30);
List<Map<String, Object>> mapList = sqlRunner.query("select * from user where birthdate in(?,?)",
new MapListHandler<User>(User.class), "1993-10-03","2000-10-10");
//------------------------------------------------------------------------------------
System.out.println("userList\r\n"+userList);
System.out.println("user\r\n"+user);
System.out.println("map\r\n"+map);
System.out.println("mapList");
for (Map<String, Object> stringObjectMap : mapList) {
System.out.println(stringObjectMap);
}
}
}
1.2 运行结果
2. 使用SqlRunner对象进行删除操作
2.1 操作代码
package com.ytt.test;
import com.liurui.growth.*;
import com.ytt.domain.User;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class SqlRunnerTest {
@Test
public void testQuery() throws ClassNotFoundException, IOException, SQLException {
Properties properties = new Properties();
properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);
connection.setAutoCommit(false);//不自动提交事务,不作真正的删除操作
//为了明显地看出删除的效果,这里查询两次
//------------------------------------------------------------------------------------
SqlRunner sqlRunner = new SqlRunner(connection);
List<User> userList = sqlRunner.query("select * from user", new BeanListHandler<User>(User.class));
System.out.println("userList\r\n" + userList);
Integer row = sqlRunner.delete("delete from user where id in(?,?,?)", 25,26,27);
System.out.println("删除id为25,26,27的记录");
System.out.println("rows affected:\t" + row);
userList = sqlRunner.query("select * from user", new BeanListHandler<User>(User.class));
System.out.println("userList\r\n" + userList);
//------------------------------------------------------------------------------------
}
}
2.2 运行结果
3. 使用SqlRunner对象进行插入,批量插入操作
3.1 操作代码
package com.ytt.test;
import com.liurui.growth.*;
import com.ytt.domain.User;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class SqlRunnerTest {
@Test
public void testQuery() throws ClassNotFoundException, IOException, SQLException {
Properties properties = new Properties();
properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);
connection.setAutoCommit(false);//不自动提交事务
//为了明显地看出插入记录的效果,
// 先删除所有记录,
// 再插入一条记录,查询一次,
// 最后一次性插入三条记录,查询一次
//------------------------------------------------------------------------------------
SqlRunner sqlRunner = new SqlRunner(connection);
Integer rows = sqlRunner.delete("delete from user");//删除所有记录
System.out.println("删除所有记录");
System.out.println("rows affected:\t"+rows);
rows = sqlRunner.insert("insert into user(name) values(?)", "盖亚奥特曼");
System.out.println("插入一条记录");
System.out.println("rows affected:\t"+rows);
List<User> userList = sqlRunner.query("select * from user", new BeanListHandler<User>(User.class));
System.out.println("userList\r\n"+userList);
Object[][] arguments=new Object[][]{
{"梦比优斯奥特曼"},{"雷欧奥特曼"},{"迪加奥特曼"}
};
rows = sqlRunner.insertBatch("insert into user(name) values(?)", arguments);
System.out.println("插入三条记录");
System.out.println("rows affected:\t"+rows);
userList = sqlRunner.query("select * from user", new BeanListHandler<User>(User.class));
System.out.println("userList\r\n"+userList);
//------------------------------------------------------------------------------------
}
}
3.2 运行结果
4. 使用SqlRunner对象进行修改操作
4.1 操作代码
package com.ytt.test;
import com.liurui.growth.*;
import com.ytt.domain.User;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class SqlRunnerTest {
@Test
public void testQuery() throws ClassNotFoundException, IOException, SQLException {
Properties properties = new Properties();
properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);
connection.setAutoCommit(false);//不自动提交事务
//------------------------------------------------------------------------------------
SqlRunner sqlRunner = new SqlRunner(connection);
Integer rows = sqlRunner.delete("delete from user");//删除所有记录
System.out.println("删除所有记录");
System.out.println("rows affected:\t"+rows);
Object[][] arguments=new Object[][]{
{"梦比优斯奥特曼"},{"雷欧奥特曼"},{"迪加奥特曼"}
};
rows = sqlRunner.insertBatch("insert into user(name) values(?)", arguments);
System.out.println("插入三条记录");
System.out.println("rows affected:\t"+rows);
List<User> userList = sqlRunner.query("select * from user", new BeanListHandler<User>(User.class));
System.out.println("userList\r\n"+userList);
rows = sqlRunner.update("update user set name=?", "欧布奥特曼");
System.out.println("修改所有记录,将name的值修改为'欧布奥特曼'");
System.out.println("rows affected:\t"+rows);
userList = sqlRunner.query("select * from user", new BeanListHandler<User>(User.class));
System.out.println("userList\r\n"+userList);
//------------------------------------------------------------------------------------
}
}
4.2 运行结果
5. 使用SqlRunner对象操作聚合函数及查看系统变量
5.1 操作代码
package com.ytt.test;
import com.liurui.growth.*;
import com.ytt.domain.User;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class SqlRunnerTest {
@Test
public void testQuery() throws ClassNotFoundException, IOException, SQLException {
Properties properties = new Properties();
properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);
connection.setAutoCommit(false);//不自动提交事务
//------------------------------------------------------------------------------------
SqlRunner sqlRunner = new SqlRunner(connection);
List<Map<String, Object>> mapList = sqlRunner.query("select * from user", new MapListHandler<>(User.class));
System.out.println("查询所有记录");
System.out.println("mapList");
for (Map<String, Object> stringObjectMap : mapList) {
System.out.println(stringObjectMap);
}
System.out.println("---------------------------------------------");
Integer count = sqlRunner.query("select count(*) from user", new ScalarHandler<>(Integer.class));
System.out.println("count(*)\t"+count);
Date date = sqlRunner.query("select max(birthdate) from user", new ScalarHandler<Date>(Date.class));
System.out.println("max(birthdate)\t"+date);
Double maxBalance = sqlRunner.query("select max(balance) from user", new ScalarHandler<Double>(Double.class));
System.out.println("max(balance)\t"+maxBalance);
String transactionIsolation = sqlRunner.query("select @@transaction_isolation", new ScalarHandler<String>(String.class));
System.out.println("transactionIsolation\t"+transactionIsolation);
//------------------------------------------------------------------------------------
}
}
5.2 运行结果
三、 结构和代码展示
1. 整体结构
2. 代码
2.1 两个接口
2.1.1 ResultSetHandler接口,用来处理ResultSet
package com.liurui.origin;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface ResultSetHandler <T>{
T handle(ResultSet resultSet) throws SQLException;
}
2.1.2 Runner 接口,用来处理SQL语句
package com.liurui.origin;
import java.sql.Connection;
import java.sql.SQLException;
public interface Runner {
<T> T query(String sql, ResultSetHandler<T> resultSetHandler) throws SQLException;
<T> T query(String sql, ResultSetHandler<T> resultSetHandler, Object... arguments) throws SQLException;
<T> T query(Connection connection, String sql, ResultSetHandler<T> resultSetHandler) throws SQLException;
<T> T query(Connection connection, String sql, ResultSetHandler<T> resultSetHandler, Object... arguments) throws SQLException;
Integer delete(String sql, Object... arguments);
Integer delete(String sql);
Integer delete(Connection connection, String sql, Object... arguments);
Integer delete(Connection connection, String sql);
Integer insert(String sql, Object... arguments);
Integer insert(String sql);
Integer insert(Connection connection, String sql, Object... arguments);
Integer insert(Connection connection, String sql);
Integer insertBatch(String sql, Object arguments[][]);
Integer insertBatch(String sql);
Integer insertBatch(Connection connection, String sql, Object arguments[][]);
Integer insertBatch(Connection connection, String sql);
Integer update(String sql, Object... arguments);
Integer update(Connection connection, String sql, Object... arguments);
Integer update(String sql);
Integer update(Connection connection, String sql);
void close();
}
2.2 六个实现接口类
2.2.1 BeanHandler类
实现ResultSetHandler接口,将ResultSet中的数据封装在一个JavaBean类中,并返回JavaBean对象。
使用场景:当ResultSet只有一条数据库表记录时。
package com.liurui.growth;
import com.liurui.origin.ResultSetHandler;
import com.liurui.utilities.ResultSetProcessor;
import java.sql.ResultSet;
public class BeanHandler<T> implements ResultSetHandler<T> {
private Class<T> beanClass;
private ResultSetProcessor<T> resultSetProcessor;
public BeanHandler(Class<T> beanClass)
{
this(beanClass,new ResultSetProcessor<T>());
}
public BeanHandler(Class<T> beanClass,ResultSetProcessor<T> resultSetProcessor)
{
this.beanClass=beanClass;
this.resultSetProcessor=resultSetProcessor;
}
@Override
public T handle(ResultSet resultSet) {
if (resultSet == null)
return null;
return resultSetProcessor.getBean(resultSet,beanClass);
}
}
2.2.2 BeanListHandler类
实现ResultSetHandler接口,将ResultSet中的数据封装在一个List集合中,并返回List对象。
使用场景:当ResultSet有多条数据库表记录时。
package com.liurui.growth;
import com.liurui.origin.ResultSetHandler;
import com.liurui.utilities.ResultSetProcessor;
import java.sql.ResultSet;
import java.util.List;
public class BeanListHandler<T> implements ResultSetHandler<List<T>> {
private Class<T> beanClass;
private ResultSetProcessor<T> resultSetProcessor;
public BeanListHandler(Class<T> beanClass)
{
this(beanClass, new ResultSetProcessor<>());
}
public BeanListHandler(Class<T> beanClass, ResultSetProcessor<T> resultSetProcessor)
{
this.beanClass=beanClass;
this.resultSetProcessor=resultSetProcessor;
}
@Override
public List<T> handle(ResultSet resultSet){
if(resultSet==null)
return null;
return resultSetProcessor.getBeanList(resultSet,beanClass);
}
}
2.2.3 MapHandler类
实现ResultSetHandler接口,将ResultSet中的数据封装在一个Map<String, Object>集合中,并返回Map对象。
使用场景:当ResultSet有一条数据库表记录时。
package com.liurui.growth;
import com.liurui.origin.ResultSetHandler;
import com.liurui.utilities.ResultSetProcessor;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
public class MapHandler<T> implements ResultSetHandler<Map<String,Object>> {
private Class<T> beanClass;
private ResultSetProcessor resultSetProcessor;
public MapHandler(Class<T> beanClass)
{
this(beanClass,new ResultSetProcessor<>());
}
public MapHandler(Class<T> beanClass,ResultSetProcessor<T> resultSetProcessor) {
this.beanClass=beanClass;
this.resultSetProcessor=resultSetProcessor;
}
@Override
public Map<String, Object> handle(ResultSet resultSet) throws SQLException {
return resultSetProcessor.getMap(resultSet,beanClass);
}
}
2.2.4 MapListHandler类
实现ResultSetHandler接口,将ResultSet中的数据封装在一个List<Map<String, Object>>集合中,并返回List对象。
使用场景:当ResultSet有多条数据库表记录时。
package com.liurui.growth;
import com.liurui.origin.ResultSetHandler;
import com.liurui.utilities.ResultSetProcessor;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class MapListHandler<T> implements ResultSetHandler<List<Map<String,Object>>> {
private Class<T> beanClass;
private ResultSetProcessor<T> resultSetProcessor;
public MapListHandler(Class<T> beanClass)
{
this(beanClass,new ResultSetProcessor<T>());
}
public MapListHandler(Class<T> beanClass,ResultSetProcessor<T> resultSetProcessor)
{
this.beanClass=beanClass;
this.resultSetProcessor=resultSetProcessor;
}
@Override
public List<Map<String, Object>> handle(ResultSet resultSet) throws SQLException
{
return resultSetProcessor.getMapList(resultSet,beanClass);
}
}
2.2.5 ScalarHandler类
实现ResultSetHandler接口,将ResultSet中的数据封装在一个指定的数据类型(主要有:java.sql.Date,String,Integer,Long,Double,Float)中,并返回指定数据类型的对象。
使用场景:执行SQL聚合函数后得到的ResultSet
package com.liurui.growth;
import com.liurui.origin.ResultSetHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ScalarHandler<T> implements ResultSetHandler<T> {
private final String columnName;//表中字段名
private final Integer columnIndex;//表中字段索引,从1开始
private Class<T> outcomeClass;//将查询出来的结果封装到指定类的Class
public ScalarHandler(Class<T> outcomeClass, Integer columnIndex) {
this(outcomeClass, null, columnIndex);
}
public ScalarHandler(Class<T> outcomeClass) {
this(outcomeClass, null, 1);//为字段索引指定默认值1,即第一列
}
public ScalarHandler(Class<T> outcomeClass, String columnName) {
this(outcomeClass, columnName, 1);//为字段索引指定默认值1
}
private ScalarHandler(Class<T> outcomeClass, String columnName, Integer columnIndex) {
this.outcomeClass = outcomeClass;
this.columnName = columnName;
this.columnIndex = columnIndex;
}
@Override
public T handle(ResultSet resultSet) throws SQLException {
//不管有没有通过构造函数传入的参数为this.columnIndex赋值,this.columnIndex都会赋默认值1
//而this.columnName必须由构造函数传入的参数为其赋值,否则this.columnName为null
String outcomeString=null;
try{
if (resultSet.next()) {
outcomeString = columnName == null ?
resultSet.getObject(columnIndex).toString() :
resultSet.getObject(columnName).toString();
T entityObject = transform(outcomeClass, outcomeString);
return entityObject;
}
}catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e)
{
e.printStackTrace();
}
return null;
}
private T transform(Class<T> toClass, String fromString) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
if(fromString.getClass()==toClass)
{
return (T)fromString;
}
Method valueOfMethod = toClass.getMethod("valueOf",String.class);//取出静态方法valueOf
T entityObject =(T)valueOfMethod.invoke(null, fromString);
return entityObject;
}
}
2.2.6 SqlRunner类
实现Runner接口,执行SQL语句
使用场景:通过Connection对象,Sql语句, ,Sql语句的参数,指定的ResultSetHandler实现类,执行Sql语句,并根据指定的ResultSetHandler实现类,生成对应的返回值
package com.liurui.growth;
import com.liurui.origin.ResultSetHandler;
import com.liurui.origin.Runner;
import java.sql.*;
/*
主操作类
通过SqlRunner对象来执行SQL语句
*/
public class SqlRunner implements Runner {
private Connection connection;
private PreparedStatement preparedStatement;
private ResultSet resultSet;
public SqlRunner() {
}
public SqlRunner(Connection connection) {
this.connection = connection;
}
private void fillArguments(PreparedStatement preparedStatement, Object... arguments)//给PreparedStatement填充参数
{
if (preparedStatement == null)
return;
if (arguments == null)
return;
ParameterMetaData parameterMetaData;
try {
parameterMetaData = preparedStatement.getParameterMetaData();
int parameterCount = parameterMetaData.getParameterCount();
if (parameterCount != arguments.length)
return;
for (int i = 0; i < parameterCount; i++) {
preparedStatement.setObject(i + 1, arguments[i]);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private <T> T executeDQL(Connection connection, String sql, ResultSetHandler<T> resultSetHandler, Object... arguments)
{
T outcome = null;
try {
if ((this.connection == null || this.connection.isClosed()) && connection != null) {
this.connection = connection;
}
if ((this.connection == null || this.connection.isClosed()) && connection == null) {
throw new SQLException("There is no Database Connectivity");
}
if (sql == null || sql.trim() == "" || resultSetHandler == null)
return null;
this.preparedStatement = this.connection.prepareStatement(sql);
fillArguments(this.preparedStatement,arguments);
this.resultSet = this.preparedStatement.executeQuery();
outcome = resultSetHandler.handle(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return outcome;
}
@Override
public <T> T query(String sql, ResultSetHandler<T> resultSetHandler) {
return executeDQL(null, sql, resultSetHandler, null);
}
@Override
public <T> T query(String sql, ResultSetHandler<T> resultSetHandler, Object... arguments) {
return executeDQL(null, sql, resultSetHandler, arguments);
}
@Override
public <T> T query(Connection connection, String sql, ResultSetHandler<T> resultSetHandler) throws SQLException {
return executeDQL(connection, sql, resultSetHandler, null);
}
@Override
public <T> T query(Connection connection, String sql, ResultSetHandler<T> resultSetHandler, Object... arguments) throws SQLException {
return executeDQL(connection, sql, resultSetHandler, arguments);
}
private int executeDML(Connection connection, String sql, Object... arguments)
{
int affectedRow = 0;
try {
if ((this.connection == null || this.connection.isClosed()) && connection != null) {
this.connection = connection;
}
if ((this.connection == null || this.connection.isClosed()) && connection == null) {
throw new SQLException("There is no Database Connectivity");
}
if (sql == null || sql.trim() == "")
return -1;
this.preparedStatement = this.connection.prepareStatement(sql);
fillArguments(this.preparedStatement, arguments);
affectedRow = preparedStatement.executeUpdate();
return affectedRow;
} catch (SQLException e) {
e.printStackTrace();
}
return affectedRow;
}
@Override
public Integer delete(String sql, Object... arguments) {
return executeDML(null, sql, arguments);
}
@Override
public Integer delete(String sql) {
return executeDML(null, sql, null);
}
@Override
public Integer delete(Connection connection, String sql, Object... arguments) {
return executeDML(connection, sql, arguments);
}
@Override
public Integer delete(Connection connection, String sql) {
return executeDML(connection, sql, null);
}
@Override
public Integer insert(String sql, Object... arguments) {
return executeDML(null, sql, arguments);
}
@Override
public Integer insert(String sql) {
return executeDML(null, sql, null);
}
@Override
public Integer insert(Connection connection, String sql, Object... arguments) {
return executeDML(connection, sql, arguments);
}
@Override
public Integer insert(Connection connection, String sql) {
return executeDML(connection, sql, null);
}
private int executeBatchDML(Connection connection, String sql, Object[][] arguments)
{
int affectedRow = 0;
try {
if ((this.connection == null || this.connection.isClosed()) && connection != null) {
this.connection = connection;
}
if ((this.connection == null || this.connection.isClosed()) && connection == null) {
throw new SQLException("There is no Database Connectivity");
}
if (sql == null || sql.trim() == "")
return -1;
this.preparedStatement = this.connection.prepareStatement(sql);
if(arguments!=null)
{
for (int i = 0; i < arguments.length; i++) {
fillArguments(this.preparedStatement, arguments[i]);
this.preparedStatement.addBatch();
}
}
affectedRow = preparedStatement.executeBatch().length;
return affectedRow;
} catch (SQLException e) {
e.printStackTrace();
}
return affectedRow;
}
@Override
public Integer insertBatch(String sql,Object arguments[][])
{
return executeBatchDML(null, sql, arguments);
}
@Override
public Integer insertBatch(String sql) {
return executeBatchDML(null,sql,null);
}
@Override
public Integer insertBatch(Connection connection, String sql, Object arguments[][])
{
return executeBatchDML(connection,sql,arguments);
}
@Override
public Integer insertBatch(Connection connection, String sql) {
return executeBatchDML(connection,sql,null);
}
@Override
public Integer update(String sql, Object... arguments) {
return executeDML(null, sql, arguments);
}
@Override
public Integer update(String sql) {
return executeDML(null, sql, null);
}
@Override
public Integer update(Connection connection, String sql) {
return executeDML(connection, sql, null);
}
@Override
public Integer update(Connection connection, String sql, Object... arguments) {
return executeDML(connection, sql, arguments);
}
public void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
try {
if (connection != null && !connection.isClosed())
connection.close();
if (preparedStatement != null && !preparedStatement.isClosed())
preparedStatement.close();
if (resultSet != null && !resultSet.isClosed())
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close(Connection connection) {
close(connection, this.preparedStatement, this.resultSet);
}
@Override
public void close() {
close(this.connection, this.preparedStatement, this.resultSet);
}
}
2.3 两个工具类
2.3.1 BeanUtilities
该类中都是静态方法,用作bean和map之间的转换
package com.liurui.utilities;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class BeanUtilities {
/*
该Map用作缓冲,Key存储JavaBean的全限定类名,Value存储JavaBeanClass中Field对象的List集合
*/
private final static Map<String, List<Field>> bufferMap=new TreeMap<>();
/*
使用内省获取JavaBeanClass中所有的Field对象
传入参数:JavaBean的Class对象
返回参数:装载JavaBeanClass中所有Field对象的List集合
*/
public static <T> List<Field> getBeanFieldList(Class<T> beanClass)
{
if(bufferMap.containsKey(beanClass.getName()))//若Map的Key中已存储JavaBean的全限定类名
{
return bufferMap.get(beanClass.getName());//则直接返回已装载JavaBeanClass中所有Field对象的List集合
}
BeanInfo beanInfo;
String property;
Method writeMethod;
Method readMethod;
Field field;
List<Field> fieldList = null;
try {
beanInfo = Introspector.getBeanInfo(beanClass);//运用内省
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
fieldList = new ArrayList<>();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) //遍历Field描述器或属性描述器
{
property = propertyDescriptor.getName();//获取Field的名字
writeMethod = propertyDescriptor.getWriteMethod();//Field对应的写方法
readMethod = propertyDescriptor.getReadMethod();//Field对应的读方法
if (writeMethod != null && readMethod != null) //排除getClass()方法
{
field = beanClass.getDeclaredField(property);//由Field的名字取出Field对象
field.setAccessible(true);//暴力反射
fieldList.add(field);
}
}
} catch (IntrospectionException | NoSuchFieldException ex) {
ex.printStackTrace();
}
bufferMap.put(beanClass.getName(),fieldList);
return fieldList;
}
public static <T> Map<String, Object> beanToMap(T beanObject, Class<T> beanClass)
{
if (beanObject == null || beanClass == null)
return null;
List<Field> beanFieldList = getBeanFieldList(beanClass);//通过JavaBeanClass获取其所有的Field对象的List集合
Map<String, Object> beanMap = null;
try
{
beanMap = new TreeMap<>();
for (Field field : beanFieldList)//遍历List
{
beanMap.put(field.getName(), field.get(beanObject));//取出Field对象的名字和Field在JavaBean对象中对应的值
}
}catch (IllegalAccessException e)
{
e.printStackTrace();
}
return beanMap;
}
public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
if (map == null || beanClass == null)
return null;
if (map.size() == 0)
return null;
T beanObject = null;
try {
beanObject = beanClass.getConstructor().newInstance();//通过反射,创建JavaBean对象
List<Field> beanFieldList = getBeanFieldList(beanClass);通过JavaBeanClass获取其所有的Field对象的List集合
for (Field field : beanFieldList) //遍历List
{
field.set(beanObject,map.get(field.getName()));//为JavaBean对象的每一个Field赋值
}
} catch (InstantiationException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return beanObject;
}
}
2.3.2 ResultSetProcessor
该类中主要用来处理ResultSet,供ResultSetHandler的实现类使用
package com.liurui.utilities;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ResultSetProcessor<T> {
public List<T> getBeanList(ResultSet resultSet, Class<T> beanClass)
{
ResultSetMetaData resultSetMetaData;
List<T> beanList = null;
String fieldName;
Object value;
T beanObject;
Field declaredField;
try {
resultSetMetaData = resultSet.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
beanList = new ArrayList<>();
while (resultSet.next()) //不论ResultSet对象中有一个还是多个记录,都遍历它,
{
beanObject = beanClass.getConstructor().newInstance();//创建存储数据库表记录的JavaBean对象
for (int i = 0; i < columnCount; i++)
{
fieldName = resultSetMetaData.getColumnLabel(i + 1);
value = resultSet.getObject(i + 1);
declaredField = beanClass.getDeclaredField(fieldName);
declaredField.setAccessible(true);
declaredField.set(beanObject, value);//将表中记录的每一列的值存储于JavaBean的属性中
}
beanList.add(beanObject);//将JavaBean对象装入List集合中
}
} catch (Exception e) {
e.printStackTrace();
}
//若ResultSet对象有一条记录,那么List对象的size为1,若ResultSet对象有10条记录,那么List对象的size为10
//若ResultSet对象没有记录,那么List对象的size为0
return beanList;
}
public T getBean(ResultSet resultSet, Class<T> beanClass)
{
return BeanUtilities.mapToBean(getMap(resultSet,beanClass),beanClass);
}
public Map<String,Object> getMap(ResultSet resultSet, Class<T> beanClass)
{
List<T> beanList = getBeanList(resultSet, beanClass);
if(beanList==null || beanList.size()==0)
return null;
T beanObject= beanList.get(0);
return BeanUtilities.beanToMap(beanObject,beanClass);
}
public List<Map<String,Object>> getMapList(ResultSet resultSet, Class<T> beanClass)
{
List<T> beanList = getBeanList(resultSet, beanClass);
if(beanList==null || beanList.size()==0)
return null;
List<Map<String,Object>> mapList=new ArrayList<>();
Map<String,Object> map;
for (T t : beanList) {
map = BeanUtilities.beanToMap(t, beanClass);
mapList.add(map);
}
return mapList;
}
}
四、总结
纸上得来终觉浅,绝知此事要躬行!只有理性的认识,不足以把握事物,我们还得亲身去接触事物,感受事物,反复认识事物,才能越来越接近事物的本质。