博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
封装JDBC—非框架开发必备的封装类
阅读量:6094 次
发布时间:2019-06-20

本文共 13040 字,大约阅读时间需要 43 分钟。

一些小型的项目,有时不想使用框架如MyBatis,Hibernate等开发时,往往在数据持久化时操作比较繁琐,以下提供了对JDBC的封装类,简化JDBC操作。
为了更客观展示MyJDBC,我们通过一般的JDBC连接数据库的增删改查来对比。
JDBC连接数据库操作通常的做法都是先建立一个公共类,来配置数据库信息,加载驱动等,这里不展示公共类(网上到处都是)。
以下对比增删改查:

增(通常的代码):

private static int insert(Student student) {        Connection conn = getConn();        int i = 0;        String sql = "insert into students (Name,Sex,Age) values(?,?,?)";        PreparedStatement pstmt;        try {            pstmt = (PreparedStatement) conn.prepareStatement(sql);            pstmt.setString(1, student.getName());            pstmt.setString(2, student.getSex());            pstmt.setString(3, student.getAge());            i = pstmt.executeUpdate();            pstmt.close();            conn.close();        } catch (SQLException e) {            e.printStackTrace();        }        return i;    }
使用MyJDBC:
public void insert() throws Exception{       String SQL = "insert into user_info(username,password) value (?,?)";       MyJDBC.insert(SQL, true, "阿木侠","12345");   }
对于单条数据的新增:
不需要使用类似pstmt.setString(1, student.getName());这样的语句一条一条对应占位符,MyJDBC提供了封装:MyJDBC.insert(SQL, autoGeneratedKeys, params)
SQL:需要执行的 INSERT 语句
autoGeneratedKeys:指示是否需要返回由数据库产生的键,当autoGeneratedKeys为true时,返回由数据库产生的主键的值,false时返回记录改变的条数。
params:使用了可变参数,无论多少位占位符,依次写入即可。

删:

private static int delete(String name) {    Connection conn = getConn();    int i = 0;    String sql = "delete from students where Name='" + name + "'";    PreparedStatement pstmt;    try {        pstmt = (PreparedStatement) conn.prepareStatement(sql);        i = pstmt.executeUpdate();        System.out.println("resutl: " + i);        pstmt.close();        conn.close();    } catch (SQLException e) {        e.printStackTrace();    }    return i;}
使用MyJDBC:
public void delete() throws Exception{	String username = "阿木";        String SQL = "delete from user_info where username like '%"+username+"%'";        MyJDBC.execute(SQL);    }

改:

private static int update(Student student) {    Connection conn = getConn();    int i = 0;    String sql = "update students set Age='" + student.getAge() + "' where Name='" + student.getName() + "'";    PreparedStatement pstmt;    try {        pstmt = (PreparedStatement) conn.prepareStatement(sql);        i = pstmt.executeUpdate();        System.out.println("resutl: " + i);        pstmt.close();        conn.close();    } catch (SQLException e) {        e.printStackTrace();    }    return i;}
使用MyJDBC:
public void update() throws Exception{        String SQL = "update user_info set password=? where id=2";        MyJDBC.execute(SQL, "123321");    }

查:

private static Integer getAll() {    Connection conn = getConn();    String SQL = "select id,password from user_info where username= ?";    PreparedStatement pstmt;    try {        pstmt = (PreparedStatement)conn.prepareStatement(SQL);        ResultSet rs = pstmt.executeQuery();        while (rs.next()) {            User user = new User();	        user.setId(rs.getInt(1));	        user.setUsername(rs.getString(2));	        user.setPassword(rs.getString(3));	        System.out.println("用户信息"+user);            System.out.println("");        }    } catch (SQLException e) {        e.printStackTrace();    }    return null;}
使用MyJDBC:
public void query() throws Exception{	String name = "阿木侠";	String SQL = "select id,password from user_info where username= ?";	ResultSet rs = MyJDBC.query(SQL,name);	    if(rs.next()){	        User user = new User();	        user.setId(rs.getInt(1));	        user.setUsername(name);	        user.setPassword(rs.getString(2));	        System.out.println("用户信息"+user);	  }    }
我们可以看到,代码确实简化了好多,Statement,Connection,ResultSet都不需要去手动操作,关闭,全部由MyJDBC代理。
不仅如此,还提供了execute()方法对SQL进行基本的操作。
下面贴出MyJDBC封装类:
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;/** * @author */public final class MyJDBC {    private static String connect;    private static String driverClassName;    private static String URL;    private static String username;    private static String password;    private static boolean autoCommit;    /** 声明一个 Connection类型的静态属性,用来缓存一个已经存在的连接对象 */    private static Connection conn;    static {	config();    }    /**     * 开头配置自己的数据库信息     */    private static void config() {	/*	 * 获取驱动	 */	driverClassName = "com.mysql.jdbc.Driver";	/*	 * 获取URL	 */	URL = "jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf8";	/*	 * 获取用户名	 */	username = "root";	/*	 * 获取密码	 */	password = "1234";	/*	 * 设置是否自动提交,一般为false不用改	 */	autoCommit = false;    }    /**     * 载入数据库驱动类     */    private static boolean load() {	try {	    Class.forName(driverClassName);	    return true;	} catch (ClassNotFoundException e) {	    System.out.println("驱动类 " + driverClassName + " 加载失败");	}	return false;    }    /**     * 专门检查缓存的连接是否不可以被使用 ,不可以被使用的话,就返回 true     */    private static boolean invalid() {	if (conn != null) {	    try {		if (conn.isClosed() || !conn.isValid(3)) {		    return true;		    /*		     * isValid方法是判断Connection是否有效,如果连接尚未关闭并且仍然有效,则返回 true		     */		}	    } catch (SQLException e) {		e.printStackTrace();	    }	    /*	     * conn 既不是 null 且也没有关闭 ,且 isValid 返回 true,说明是可以使用的 ( 返回 false )	     */	    return false;	} else {	    return true;	}    }    /**     * 建立数据库连接     */    public static Connection connect() {	if (invalid()) { /* invalid为true时,说明连接是失败的 */	    /* 加载驱动 */	    load();	    try {		/* 建立连接 */		conn = DriverManager.getConnection(URL, username, password);	    } catch (SQLException e) {		System.out.println("建立 " + connect + " 数据库连接失败 , " + e.getMessage());	    }	}	return conn;    }    /**     * 设置是否自动提交事务     **/    public static void transaction() {	try {	    conn.setAutoCommit(autoCommit);	} catch (SQLException e) {	    System.out.println("设置事务的提交方式为 : " + (autoCommit ? "自动提交" : "手动提交") + " 时失败: " + e.getMessage());	}    }    /**     * 创建 Statement 对象     */    public static Statement statement() {	Statement st = null;	connect();	/* 如果连接是无效的就重新连接 */	transaction();	/* 设置事务的提交方式 */	try {	    st = conn.createStatement();	} catch (SQLException e) {	    System.out.println("创建 Statement 对象失败: " + e.getMessage());	}	return st;    }    /**     * 根据给定的带参数占位符的SQL语句,创建 PreparedStatement 对象     *      * @param SQL     *            带参数占位符的SQL语句     * @return 返回相应的 PreparedStatement 对象     */    private static PreparedStatement prepare(String SQL, boolean autoGeneratedKeys) {	PreparedStatement ps = null;	connect();	/* 如果连接是无效的就重新连接 */	transaction();	/* 设置事务的提交方式 */	try {	    if (autoGeneratedKeys) {		ps = conn.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS);	    } else {		ps = conn.prepareStatement(SQL);	    }	} catch (SQLException e) {	    System.out.println("创建 PreparedStatement 对象失败: " + e.getMessage());	}	return ps;    }    public static ResultSet query(String SQL, Object... params) {	if (SQL == null || SQL.trim().isEmpty() || !SQL.trim().toLowerCase().startsWith("select")) {	    throw new RuntimeException("你的SQL语句为空或不是查询语句");	}	ResultSet rs = null;	if (params.length > 0) {	    /* 说明 有参数 传入,就需要处理参数 */	    PreparedStatement ps = prepare(SQL, false);	    try {		for (int i = 0; i < params.length; i++) {		    ps.setObject(i + 1, params[i]);		}		rs = ps.executeQuery();	    } catch (SQLException e) {		System.out.println("执行SQL失败: " + e.getMessage());	    }	} else {	    /* 说明没有传入任何参数 */	    Statement st = statement();	    try {		rs = st.executeQuery(SQL); // 直接执行不带参数的 SQL 语句	    } catch (SQLException e) {		System.out.println("执行SQL失败: " + e.getMessage());	    }	}	return rs;    }    private static Object typeof(Object o) {	Object r = o;	if (o instanceof java.sql.Timestamp) {	    return r;	}	// 将 java.util.Date 转成 java.sql.Date	if (o instanceof java.util.Date) {	    java.util.Date d = (java.util.Date) o;	    r = new java.sql.Date(d.getTime());	    return r;	}	// 将 Character 或 char 变成 String	if (o instanceof Character || o.getClass() == char.class) {	    r = String.valueOf(o);	    return r;	}	return r;    }    public static boolean execute(String SQL, Object... params) {	if (SQL == null || SQL.trim().isEmpty() || SQL.trim().toLowerCase().startsWith("select")) {	    throw new RuntimeException("你的SQL语句为空或有错");	}	boolean r = false;	/* 表示 执行 DDL 或 DML 操作是否成功的一个标识变量 */	/* 获得 被执行的 SQL 语句的 前缀 */	SQL = SQL.trim();	SQL = SQL.toLowerCase();	String prefix = SQL.substring(0, SQL.indexOf(" "));	String operation = ""; // 用来保存操作类型的 变量	// 根据前缀 确定操作	switch (prefix) {	case "create":	    operation = "create table";	    break;	case "alter":	    operation = "update table";	    break;	case "drop":	    operation = "drop table";	    break;	case "truncate":	    operation = "truncate table";	    break;	case "insert":	    operation = "insert :";	    break;	case "update":	    operation = "update :";	    break;	case "delete":	    operation = "delete :";	    break;	}	if (params.length > 0) { // 说明有参数	    PreparedStatement ps = prepare(SQL, false);	    Connection c = null;	    try {		c = ps.getConnection();	    } catch (SQLException e) {		e.printStackTrace();	    }	    try {		for (int i = 0; i < params.length; i++) {		    Object p = params[i];		    p = typeof(p);		    ps.setObject(i + 1, p);		}		ps.executeUpdate();		commit(c);		r = true;	    } catch (SQLException e) {		System.out.println(operation + " 失败: " + e.getMessage());		rollback(c);	    }	} else { // 说明没有参数	    Statement st = statement();	    Connection c = null;	    try {		c = st.getConnection();	    } catch (SQLException e) {		e.printStackTrace();	    }	    // 执行 DDL 或 DML 语句,并返回执行结果	    try {		st.executeUpdate(SQL);		commit(c); // 提交事务		r = true;	    } catch (SQLException e) {		System.out.println(operation + " 失败: " + e.getMessage());		rollback(c); // 回滚事务	    }	}	return r;    }    /*     *      * @param SQL     *            需要执行的 INSERT 语句     * @param autoGeneratedKeys     *            指示是否需要返回由数据库产生的键     * @param params     *            将要执行的SQL语句中包含的参数占位符的 参数值     * @return 如果指定 autoGeneratedKeys 为 true 则返回由数据库产生的键; 如果指定 autoGeneratedKeys     *         为 false 则返回受当前SQL影响的记录数目     */    public static int insert(String SQL, boolean autoGeneratedKeys, Object... params) {	int var = -1;	if (SQL == null || SQL.trim().isEmpty()) {	    throw new RuntimeException("你没有指定SQL语句,请检查是否指定了需要执行的SQL语句");	}	// 如果不是 insert 开头开头的语句	if (!SQL.trim().toLowerCase().startsWith("insert")) {	    System.out.println(SQL.toLowerCase());	    throw new RuntimeException("你指定的SQL语句不是插入语句,请检查你的SQL语句");	}	// 获得 被执行的 SQL 语句的 前缀 ( 第一个单词 )	SQL = SQL.trim();	SQL = SQL.toLowerCase();	if (params.length > 0) { // 说明有参数	    PreparedStatement ps = prepare(SQL, autoGeneratedKeys);	    Connection c = null;	    try {		c = ps.getConnection(); // 从 PreparedStatement 对象中获得 它对应的连接对象	    } catch (SQLException e) {		e.printStackTrace();	    }	    try {		for (int i = 0; i < params.length; i++) {		    Object p = params[i];		    p = typeof(p);		    ps.setObject(i + 1, p);		}		int count = ps.executeUpdate();		if (autoGeneratedKeys) { // 如果希望获得数据库产生的键		    ResultSet rs = ps.getGeneratedKeys(); // 获得数据库产生的键集		    if (rs.next()) { // 因为是保存的是单条记录,因此至多返回一个键			var = rs.getInt(1); // 获得值并赋值给 var 变量		    }		} else {		    var = count; // 如果不需要获得,则将受SQL影像的记录数赋值给 var 变量		}		commit(c);	    } catch (SQLException e) {		System.out.println("数据保存失败: " + e.getMessage());		rollback(c);	    }	} else { // 说明没有参数	    Statement st = statement();	    Connection c = null;	    try {		c = st.getConnection(); // 从 Statement 对象中获得 它对应的连接对象	    } catch (SQLException e) {		e.printStackTrace();	    }	    // 执行 DDL 或 DML 语句,并返回执行结果	    try {		int count = st.executeUpdate(SQL);		if (autoGeneratedKeys) { // 如果企望获得数据库产生的键		    ResultSet rs = st.getGeneratedKeys(); // 获得数据库产生的键集		    if (rs.next()) { // 因为是保存的是单条记录,因此至多返回一个键			var = rs.getInt(1); // 获得值并赋值给 var 变量		    }		} else {		    var = count; // 如果不需要获得,则将受SQL影像的记录数赋值给 var 变量		}		commit(c); // 提交事务	    } catch (SQLException e) {		System.out.println("数据保存失败: " + e.getMessage());		rollback(c); // 回滚事务	    }	}	return var;    }    /** 提交事务 */    private static void commit(Connection c) {	if (c != null && !autoCommit) {	    try {		c.commit();	    } catch (SQLException e) {		e.printStackTrace();	    }	}    }    /** 回滚事务 */    private static void rollback(Connection c) {	if (c != null && !autoCommit) {	    try {		c.rollback();	    } catch (SQLException e) {		e.printStackTrace();	    }	}    }    /**     *  释放资源     *   **/    public static void release(Object cloaseable) {	if (cloaseable != null) {	    if (cloaseable instanceof ResultSet) {		ResultSet rs = (ResultSet) cloaseable;		try {		    rs.close();		} catch (SQLException e) {		    e.printStackTrace();		}	    }	    if (cloaseable instanceof Statement) {		Statement st = (Statement) cloaseable;		try {		    st.close();		} catch (SQLException e) {		    e.printStackTrace();		}	    }	    if (cloaseable instanceof Connection) {		Connection c = (Connection) cloaseable;		try {		    c.close();		} catch (SQLException e) {		    e.printStackTrace();		}	    }	}    }}
以上,没有最方便的代码,只会有更方便的,欢迎大家指正,有什么好的建议欢迎留言,随时作出调整。

转载地址:http://luzza.baihongyu.com/

你可能感兴趣的文章
HDU 4377 Sub Sequence[串构造]
查看>>
云时代架构阅读笔记之四
查看>>
WEB请求处理一:浏览器请求发起处理
查看>>
Lua学习笔记(8): 元表
查看>>
PHP经典算法题
查看>>
LeetCode 404 Sum of Left Leaves
查看>>
醋泡大蒜有什么功效
查看>>
hdu 5115(2014北京—dp)
查看>>
数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)...
查看>>
PHP读取日志里数据方法理解
查看>>
第五十七篇、AVAssetReader和AVAssetWrite 对视频进行编码
查看>>
Vivado增量式编译
查看>>
一个很好的幻灯片效果的jquery插件--kinMaxShow
查看>>
微信支付签名配置正确,但返回-1,调不出支付界面(有的手机能调起,有的不能)...
查看>>
第二周例行报告
查看>>
Spring学习(16)--- 基于Java类的配置Bean 之 基于泛型的自动装配(spring4新增)...
查看>>
实验八 sqlite数据库操作
查看>>
四种简单的排序算法(转)
查看>>
Quartz2D之着色器使用初步
查看>>
多线程条件
查看>>