封装JDBC—非框架开发必备的封装类

栏目: 数据库 · 发布时间: 8年前

内容简介:封装JDBC—非框架开发必备的封装类

一些小型的项目,有时不想使用框架如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();
		}
	    }

	}

    }

}

以上,没有最方便的代码,只会有更方便的,欢迎大家指正,有什么好的建议欢迎留言,随时作出调整。


以上所述就是小编给大家介绍的《封装JDBC—非框架开发必备的封装类》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

How to Build a Billion Dollar App

How to Build a Billion Dollar App

George Berkowski / Little, Brown Book Group / 2015-4-1 / USD 24.95

Apps have changed the way we communicate, shop, play, interact and travel and their phenomenal popularity has presented possibly the biggest business opportunity in history. In How to Build a Billi......一起来看看 《How to Build a Billion Dollar App》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具