优化JDBC封装
可重用性较强的JDBC封装
以下为代码,注释中写了主要思想
主类
com.util.JDBCUtil.java
package com.util; import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class JDBCUtil {
private final static String driver="com.mysql.jdbc.Driver";
private final static String url="jdbc:mysql://192.168.137.11:3306/db_test?useUnicode=true&characterEncoding=utf8";
private final static String user="root";
private final static String password="123456";
//获取JDBC连接
public static Connection getConnection(){
Connection conn=null;
try {
Class.forName(driver);
conn=DriverManager.getConnection(url,user,password); } catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return conn;
}
//关闭连接
public static void close(Connection conn,PreparedStatement pstmt,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(pstmt!=null){
try {
pstmt.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
//增、删、改
/*
* sql语句参数部分应改为?替代,代码中使用PreparedStatement类来注入参数,防止sql注入
* 因不确定sql语句参数个数,类型,所以使用动态参数Object... objects
* 将objects使用PreparedStatement中setObject方法注入
* 调用时可以这样调用
* update("insert into user values(?,?)","ads","asdsa");
* 这样封装使得此方法可重用性强
*/
public static int update(String sql,Object... objects ){
Connection conn=getConnection();
PreparedStatement pstmt=null;
int result =0; try {
pstmt=conn.prepareStatement(sql);
if(objects!=null){
for(int i=0;i<objects.length;i++){
pstmt.setObject(i+1, objects[i]);
}
}
result=pstmt.executeUpdate();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
close(conn, pstmt, null);
} return result;
} //添加对象
/*
* 不确定未来编程时向数据库中添加对象是什么,固使用泛型T
* 可以使用自定义注解的方式实现javabean与相应数据表的映射
* 此方法封装时代码晦涩难懂,使用时不用自己去写sql语句较为方便且复用性强
* 类似于hibernate
*/
public static <T> int insert(T t){
//列名数组,即javabean的属性,用于拼接sql语句
List<String> columns=new ArrayList<>();
//用于拼接sql语句,存放‘?’,若javabean有4个属性,则此数组为[?,?,?,?]
List<String> values=new ArrayList<>();
//存放javabean各个属性的值,最后使用PreparedStatement注入
List<Object> params=new ArrayList<>(); Class clz=t.getClass();
//TableUtil自定义注解,用于javabean与表名的映射
TableUtil ann=(TableUtil)clz.getAnnotation(TableUtil.class);
//获取该javabean的属性
Field[] fields=clz.getDeclaredFields();
//for循环对columns values数组赋值
/*
* ColumnUtil自定义注解,用于javabean属性与表的列名映射
* IDUtil自定义注解,用于表的自增长主键与相应javabean属性映射
*/
for (Field field : fields) {
//若数据表中设置了自增长主键,使用insert语句时须跳过相应的主属性,所以应执行此if语句判断
if(!field.isAnnotationPresent(IDUtil.class)){
//判断是使用ColumnUtil将此属性映射
if(field.isAnnotationPresent(ColumnUtil.class)){
//获取列名
ColumnUtil column= field.getAnnotation(ColumnUtil.class);
//columns数组添加相应列名
columns.add(column.value());
//获取一列,便向values数组中添加一个‘?’,即有多少列就有多少个‘?’
values.add("?");
//一般javabean属性为private,使用此方法可访问private属性
field.setAccessible(true);
try {
//列相应的值,存放入params数组
params.add(field.get(t));
} catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*
* 拼接sql语句
* ann.value()即注解的表名
* list数组转化为String,结果为[...],为拼接sql语句需将"[]"变"()"
*/
String sql="insert into "+ann.value()+Arrays.toString(columns.toArray()).replaceAll("\\[", "(").replaceAll("\\]", ")")+" values"+Arrays.toString(values.toArray()).replaceAll("\\[", "(").replaceAll("\\]", ")");
//System.out.println(Arrays.toString(params.toArray()) );
//System.out.println(sql); //以下为执行sql语句过程
//思想同上面的update方法
Connection connection=getConnection();
PreparedStatement preparedStatement=null;
int result=0;
try {
preparedStatement=connection.prepareStatement(sql);
for (int i=0;i<params.size();i++) {
preparedStatement.setObject(i+1,params.get(i));
}
result=preparedStatement.executeUpdate(); } catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
close(connection, preparedStatement, null);
} return result; } //查询,获取对象列表
/*
* 此方法调用时,使用匿名内部类,程序员可以自己写ResultSet结果集,具有好的复用性
* sql语句中参数部分使用?替代,并使用动态参数,思想同上
*/
public static <T> List<T> executeQuery(String sql,RowMap<T> rowMap,Object...objects ){
List<T> list=new ArrayList<>();
Connection connection=getConnection();
PreparedStatement preparedStatement=null;
ResultSet rSet=null;
try {
preparedStatement=connection.prepareStatement(sql);
if(objects!=null) {
for (int i=0;i<objects.length;i++) {
preparedStatement.setObject(i+1, objects[i]); }
}
rSet=preparedStatement.executeQuery();
while (rSet.next()) {
T t=rowMap.rowMapping(rSet);
list.add(t);
}
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
close(connection, preparedStatement, rSet);
} return list;
} }
以下为相关工具类
com.util.ColumnUtil.java
package com.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnUtil {
//相应列名
String value();
}
com.util.IDUtil.java
package com.util; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
//自增主键注解
public @interface IDUtil { }
com.util.TableUtil.java
package com.util; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableUtil {
//映射相应表名
String value();
}
com.util.RowMap.java
package com.util;
import java.sql.ResultSet;
public interface RowMap<T> {
//自定义result结果集
//使用了匿名内部类的思想
public T rowMapping(ResultSet rs);
}
以下为测试类:
com.model.User.java
package com.model; import com.util.ColumnUtil;
import com.util.TableUtil; @TableUtil("t_user")
//此javabean映射表名为"t_user"
public class User {
@ColumnUtil("c_username")
//属性username对应表中的c_username列
private String username;
//属性password对应表中的c_password列
@ColumnUtil("c_password")
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
} }
tests.JDBCUtilTest.java
package tests; import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID; import com.model.User;
import com.util.JDBCUtil;
import com.util.RowMap; public class JDBCUtilTest { public static void main(String[] args) {
User newUser=new User();
newUser.setUsername(UUID.randomUUID().toString());
newUser.setPassword("asd");
JDBCUtil.insert(newUser);
List<User> users=JDBCUtil.executeQuery("select * from t_user where c_username!=?",new RowMap<User>() {
@Override
//匿名内部类 定义resultset结果集
public User rowMapping(ResultSet rs) {
User user=new User();
try {
user.setUsername(rs.getString("c_username"));
user.setPassword(rs.getString("c_password"));
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
}, "JDBCUtil");//查找用户名不为JDBCUtil的用户
for (User user : users) {
System.out.println(user.getUsername()+"&&"+user.getPassword());
} } }
测试结果:

相应数据库:

优化JDBC封装的更多相关文章
- 优化JDBC开发
一.元数据 元数据:数据库.表.列的定义信息 1.DataBaseMetaData对象 getURL():返回一个String类对象,代表数据库的URL. getUserName():返回连接当前数据 ...
- 优化JDBC编程-多提提意见
优化JDBC编程这是我根据MS SQL SERVER 2000 JDBC DRIVER HELP,并参考其它资料整理而成.ms的这个帮助文件实在有失大家风范,示例代码很.....有兴趣者可以去下载ht ...
- jdbc封装代码
jdbc封装代码 package jdbcUtil; import java.sql.Connection; import java.sql.DriverManager; import java.sq ...
- JDBC封装的工具类
1. JDBC封装的工具类 public class JDBCUtil { private static Properties p = new Properties(); private static ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(九)数据层优化-jdbc连接池简述、druid简介
日常啰嗦 终于回到既定轨道上了,这一篇讲讲数据库连接池的相关知识,线程池以后有机会再结合项目单独写篇文章(自己给自己挖坑,不知道什么时候能填上),从这一篇文章开始到本阶段结束的文章都会围绕数据库和da ...
- 数据层优化-jdbc连接池简述、druid简介
终于回到既定轨道上了,这一篇讲讲数据库连接池的相关知识,线程池以后有机会再结合项目单独写篇文章(自己给自己挖坑,不知道什么时候能填上),从这一篇文章开始到本阶段结束的文章都会围绕数据库和dao层的优化 ...
- IOS实现自动循环滚动广告--ScrollView的优化和封装
一.问题分析 在许多App中,我们都会见到循环滚动的视图,比如广告,其实想实现这个功能并不难,用ScrollView就可以轻松完成,但是在制作的过程中还存在几个小问题,如果能够正确的处理好这些小问题, ...
- 高性能jdbc封装工具 Apache Commons DbUtils 1.6(转载)
转载自原文地址:http://gao-xianglong.iteye.com/blog/2166444 前言 关于Apache的DbUtils中间件或许了解的人并不多,大部分开发人员在生成环境中更多的 ...
- Mysql,JDBC封装
1.完成对数据库的表的增删改的操作 2.查询返回单条记录 3.查询返回多行记录 4.可以使用反射机制来封装,查询单条记录 5.反射机制,查询多条记录 package myjdbc; import ja ...
随机推荐
- Bar Mitzvah Attack分析
结合RC4算法实现,简单分析一下Bar Mitzvah Attack攻击的原理,并以WEP破解过程来举例说明通用的破解方式.(个人觉得RC4早已经过时,要想避免该攻击,应该采用更好的加密算法,如:cc ...
- 理解js的DOM操作
1.DOM结构——两个节点之间可能存在哪些关系以及如何在节点之间任意移动.document.documentElement 返回文档的根节点<html> document.body ...
- PHP中的错误信息
PHP中的错误信息 php.ini中配置错误消息 在PHP4中,没有异常 Exception这个概念,只有 错误Error.我们可以通过修改php.ini 文件来配置用户端输出的错误信息. 在ph ...
- 前端学习笔记之BOM和DOM
前言 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我们需要继续学习BOM和DO ...
- GIT使用—分支与合并
一.分支名 分支名不能以斜线结尾 分支名不能以减号开头 以斜杠分割的组件不能以点开头(feature/.new) 分支名的任何地方都不能包含连个连续的点 分支名不能包含空格或空白符 分支名不能包含波浪 ...
- 20145312 《Java程序设计》第五周学习总结
20145312 <Java程序设计>第五周学习总结 学习笔记 Chapter8 异常处理 8.1语法与继承架构 1.Java中的错误以对象方式呈现,只要捕捉包装错误的对象,就可以针对该错 ...
- Centos7 ActiveMQ 安装并配置为开机启动
第一步, 环境准备 更新CentOS7 ,安装epel-release,安装JDK,关闭防火墙 # yum clean all && yum update# yum install - ...
- POJ-2418 Hardwood Species(二叉搜索树)
思路就是先将每个单词存进二叉树中,没出现一次,修改该单词所在结点的cnt++: 最后通过递归中序遍历输出结果. 思路很清晰,主要注意一下指针的使用,想一想为什么要这么用? 简单的解释就是,insert ...
- IPTABLES拒绝某个IP某项服务,并记录到日志(rhel7实例)
#iptables -I INPUT -p icmp -s 192.168.0.1 -j DROP \\在INPUT链中插入:如果检测到从192.168.0.1发过来的 ...
- jar包中使用log4j2不起作用
某程序中有使用到log4j2,将该程序打包成jar,使用以下命令执行时,发现log4j不输出 java -cp Tool.jar com.zhen.nameOnce.Log4jTest 且报以下错误 ...