【java】对jdbc操作结果简单的映射封装
1. 对jdbc做一个简单的封装,select可以返回一个javabean对象,而不是resultset。主要用了反射。这是我之前写的代码,做了简单的修改。
实现功能:a.对数据库的基本操作 增删改查
b.对查询的单条记录返回一个指定类型的javabean对象,利用java反射,jdbc ResultSet类和ResultSetMetaData类
c. 对查到的结果集返回一个List, 泛型
数据源:用到的 数据库连接池是我自己简单实现的一个连接池:【java】简单实现数据库连接池,主要为了后续实现事务的简单实现
用到的java知识 : 反射,泛型,jdbc
import com.yeyeck.noob.ConnectionPollImpl; import com.yeyeck.noob.IConnectionPool; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.*; import java.util.ArrayList; import java.util.List; public class DBUtil { public static int excuteUpdate(String sql, Object... objects) { IConnectionPool connectionPool = ConnectionPollImpl.getInstance(); Connection connection = connectionPool.getConnection(); PreparedStatement preparedStatement = null; try { preparedStatement = getStateMent(connection, sql, objects); return preparedStatement.executeUpdate(); //执行sql并返回结果 } catch (SQLException e) { e.printStackTrace(); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } } return 0; } /** * 查询单条记录 * * @param sql 查询语句 * @param clazz 返回对象的class * @param objects 需要的参数,必须跟sql占位符的位置一一对应 * @param <T> 泛型返回 * @return 返回单个对象 */ public static <T> T queryForObject(String sql, Class<T> clazz, Object... objects) { IConnectionPool connectionPool = ConnectionPollImpl.getInstance(); Connection connection = connectionPool.getConnection(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; T object = null; try { preparedStatement = getStateMent(connection, sql, objects); resultSet = getResultSet(preparedStatement); if (resultSet.next()) { object = invokeObject(resultSet, clazz); } } catch (SQLException | IllegalAccessException | InstantiationException | NoSuchFieldException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } finally { close(preparedStatement, resultSet); //记得关闭 } return object; } /** *查询多条记录 * * @param sql 查询语句 * @param clazz 返回对象的class * @param objects 需要的参数,必须跟sql占位符的位置一一对应 * @param <T> 泛型返回 * * @return list */ public static <T> List<T> queryForList(String sql, Class<T> clazz, Object... objects) { IConnectionPool connectionPool = ConnectionPollImpl.getInstance(); Connection connection = connectionPool.getConnection(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; List<T> list = new ArrayList<>(); try { preparedStatement = getStateMent(connection, sql, objects); resultSet = getResultSet(preparedStatement); while (resultSet.next()) { //调用 invokeObject方法,把一条记录封装成一个对象,添加到list中 list.add(invokeObject(resultSet, clazz)); } } catch (SQLException | IllegalAccessException | InstantiationException | NoSuchFieldException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } finally { close(preparedStatement, resultSet); } return list.size() > 0 ? list : null; } private static void close(PreparedStatement preparedStatement, ResultSet resultSet) { try { if(resultSet != null) { resultSet.close(); } if (preparedStatement != null) { preparedStatement.close(); } } catch (SQLException e) { e.printStackTrace(); } } /** * 把数据库中的一条记录通过反射包装成相应的Bean * @param resultSet * @param clazz * @param <T> * @return * @throws IllegalAccessException * @throws InstantiationException * @throws SQLException * @throws NoSuchFieldException * @throws NoSuchMethodException * @throws InvocationTargetException */ private static <T> T invokeObject(ResultSet resultSet, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException { T object = clazz.getDeclaredConstructor().newInstance(); ResultSetMetaData metaData = resultSet.getMetaData(); for (int i = 0, count = metaData.getColumnCount(); i < count; i++) { String columnName = metaData.getColumnName(i + 1); //数据库返回结果的列名 String fieldName = StringUtil.camelName(columnName); //去掉列名中的下划线“_”并转为驼峰命名 Field field = clazz.getDeclaredField(fieldName); //根据字段名获取field String methName = setMethodName(fieldName); //拼set方法名 Class type = field.getType(); //获取字段类型 Method setMethod = clazz.getDeclaredMethod(methName, field.getType()); Object value = resultSet.getObject(i + 1); //获取字段值 setMethod.invoke(object, type.cast(value)); //强转并且赋值 } return object; } private static PreparedStatement getStateMent(Connection connection, String sql, Object... objects) throws SQLException { PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0, len = objects.length; i < len; i++) { preparedStatement.setObject(i + 1, objects[i]); //给sql每个?占位符填上数据 } return preparedStatement; } private static ResultSet getResultSet(PreparedStatement statement) throws SQLException { if (statement == null) { return null; } else { return statement.executeQuery(); } } private static String setMethodName(String str) { return "set" + StringUtil.firstUpperCase(str); } }
其中用到的StringUtil的几个方法
public class StringUtil { /** * 转为驼峰命名 * @param str * @return string */ public static String camelName(String str) { if (!isEmpty(str)) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0, len = str.length(); i < len; i++) { if (str.charAt(i) == '_') { while (str.charAt(i + 1) == '_') { i++; } stringBuilder.append(("" + str.charAt(++i)).toUpperCase()); } else { stringBuilder.append(str.charAt(i)); } } return stringBuilder.toString(); } return str; } /** * 判断是否为空串 * * @param str * @return */ public static boolean isBlank(String str) { if (str != null && str.length() > 0) { for (int i = 0, len = str.length(); i < len; i++) { if (!Character.isSpaceChar(str.charAt(i))) { return false; } } } return true; } /** * 判断是否为空串 ?!!! 我怎么又写了个一样的方法?!!! * @param str * @return */ public static boolean isEmpty(String str) { return str == null || str.length() == 0; } /** * 将第一个字母替换为大写 * @param str * @return */ public static String firstUpperCase(String str) { return str.substring(0, 1).toUpperCase() + str.substring(1, str.length()); } }
测试
1.测试用到的表
CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `age` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
初始数据
测试代码
import java.util.List; public class DBUtilTest { public static void main(String[] args) { List<User> users1 = DBUtil.queryForList("select * from t_user", User.class); System.out.println(users1); User user = new User(); user.setUsername("刘能"); user.setAge(12); String sql1 = "insert into `t_user`(username, age) values (?, ?)"; System.out.println("insert 语句测试返回结果:" + DBUtil.excuteUpdate(sql1, user.getUsername(), user.getAge())); List<User> users2 = DBUtil.queryForList("select * from t_user", User.class); System.out.println(users2); String sql2 = "delete from t_user where id = ?"; System.out.println("delete 语句测试返回结果:" + DBUtil.excuteUpdate(sql2, 3)); String sql3 = "update t_user set age = ? where id = ?"; System.out.println("update 语句测试返回结果:" + DBUtil.excuteUpdate(sql3, 100, 1)); String sql4 = "select * from t_user where id = ?"; User user2 = DBUtil.queryForObject(sql4, User.class, 2); System.out.println("select 语句测试返回结果: " + user2 ); List<User> users3 = DBUtil.queryForList("select * from t_user", User.class); System.out.println(users3); } }
测试结果
[User{id=1, username='小明', age=100}, User{id=2, username='小红', age=15}, User{id=4, username='小二', age=12}, User{id=5, username='刘能', age=12}] insert 语句测试返回结果:1 [User{id=1, username='小明', age=100}, User{id=2, username='小红', age=15}, User{id=4, username='小二', age=12}, User{id=5, username='刘能', age=12}, User{id=6, username='二蛋', age=99}] delete 语句测试返回结果:1 update 语句测试返回结果:1 select 语句测试返回结果: User{id=2, username='小红', age=15} [User{id=1, username='小明', age=20}, User{id=2, username='小红', age=15}, User{id=4, username='小二', age=12}, User{id=6, username='二蛋', age=99}]
数据库数据
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【java】简单实现数据库连接池
一直在想java事务是怎么实现的,在原声jdbc的时候级别下,我们可以通过关掉autocommit 然后再手动commit。但是项目开发中基本上是看不见conection的。所以自己决定简单实现框架的一点皮毛功能。首先就是数据库连接池了 1. 先定义一个接口 import java.sql.Connection; public interface IConnectionPool { /** * 获取一个连接 * @return */ Connection getConnection(); /** * 用完后调用,把连接放回池中,实现复用 */ void freeLocalConnection(); /** * 销毁连接池 */ void destroy(); //测试用 void status(); } 2. 实现数据库连接池的代码, 为了线程安全,简单粗暴地用synchronized关键字 实现事务的关键是,我们执行一个事务的Connection是同一个,我们可以在事务控制的时候用AOP,在事务开始的时候 调用setAutoCommit(false) 然后在事务代码之后调用commi...
- 下一篇
Linux/Windows配置stm32免费开发环境详细流程
Linux/Windows配置stm32免费开发环境详细流程 系统:linux mint 18.3 xfce,windows10 stm32开发板:正点原子mini板(stm32f103rc) 烧写器:stlink v2 如果是JLINK的可以参考这篇 需要软件: 链接:https://pan.baidu.com/s/1nxgh1VF密码:rvzu 2018/4/1更新 系统:manjaro xfce 64bit stm32型号:f407vet6 烧写器:stlink v2 基于arch Linux的manjaro安装软件更加简单方便,步骤和下列初版教程一样,为了运行stm32cubemx和sw4stm32,需要安装jdk或者jre环境,我自己把两个都安装上了,在manjaro的软件包管理器搜索安装,如下图 下载安装stm32cubemx和sw4stm32下面有介绍,这里就介绍一下manjaro下安装stlink和openocd的教程,非常简单,终端执行 $ yaourt stlink 1 和 $ yaourt openocd 1 前提是已经安装了AUR软件包管理器yaourt,其实在...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- MySQL8.0.19开启GTID主从同步CentOS8
- Hadoop3单机部署,实现最简伪集群
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,CentOS8安装Elasticsearch6.8.6