JDBC入门

前述:

  前面我们介绍了Mysql数据库以及SQL语言,我们可以通过命令行或者第三方客户端工具来操作Mysql数据库。

  然而,在实际的工作开发过程中,我们是需要整合、关联 java与数据库的,也就是通过 java来访问数据库

  那么,如何实现 java对数据库的访问呢?又是怎么做到 java可以对数据库访问的呢?

  -- 让我们先来认识下JDBC,问题便豁然开朗 ...

一、认识JDBC(Java DataBase Connectivity:java数据库连接

 1.1 概述

    JDBC是官方(sun公司)定义的一套操作所有关系型数据库的标准接口规范。

    我们只需要调用JDBC接口中的方法即可实现访问数据库,但真正操作数据库的是各大数据库厂商根据JDBC接口规范提供的具体实现类,也就是数据库驱动。

  •  综上,使用JDBC的好处:
    1. 程序员如果要开发访问数据库的程序,只需要会调用JDBC接口中的方法即可,不用关注类是如何实现的;
    2. 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库。

 1.2 使用JDBC开发使用到的包

会使用到的包 说明
java.sql   所有与JDBC访问数据库相关的接口和类
javax.sql       数据库扩展包,提供数据库额外的功能。如:连接池
数据库的驱动   由各大数据库厂商提供,是对JDBC接口实现的类,需要额外去根据需要下载

 1.3 JBDC的核心API

接口或类 作用
DriverManager类 1) 管理和注册数据库驱动
2) 得到数据库连接对象
Connection接口 一个连接对象,可用于创建Statement 和 PreparedStatement对象
Statement接口 一个SQL语句对象,用于将SQL语句发送给数据库服务器
reparedStatement接口 一个SQL语句对象,是Statement的子接口
ResultSet接口 用于封装数据库查询的结果集,返回给客户端Java程序

 1.4 java代码实现步骤

    1. 导入数据库驱动jar包。如:mysql-connector-java-5.1.37-bin.jar
      * 复制mysql-connector-java-5.1.37-bin.jar到项目的lib目录下
      * 右键-->Add As Library添加jar包成库
    2. 加载和注册数据库驱动。-- 告诉程序该使用哪一个数据库驱动jar包
      * Class.forName(数据库驱动实现类) 如:Mysql的数据库驱动实现类 com.mysql.jdbc.Driver 

/**
* com.mysql.jdbc.Driver源码
* java.sql.Driver接口,所有数据库厂商必须实现的接口,表示这是一个驱动
*/
public class Driver implements java.sql.Driver {
	public Driver() throws sQLException {
	}

	static {
		try {
			DriverManager.registerDriver(new Driver()); //注册数据库驱动
		}catch (SQLException var1){
			throw new RuntimeException ("can't register driver! ");
		}
	}
}  

  注意:从JDBC3开始(或mysql5之后驱动),目前已经普遍使用的版本,可以不用注册驱动而直接使用。Class.forName这句话可以省略。

    3. 获取数据库连接对象 Connection
      * Connection conn = DriverManager.getConnection("jdbc:mysql://ip地址(域名):端口号/数据库名称[?参数名=参数值]", "用户名", "密码"); 

/**
* DriverManager类中的静态方法
*	// 通过连接字符串,用户名,密码来得到数据库的连接对象
* 	Connection getConnection (String url,String user, String password)
*	// 通过连接字符串,属性对象来得到连接对象
* 	Connection getConnection (String url,Properties info)
*/
/**
Connection接口:数据库连接对象
	功能:
		1. 获取执行sql的对象
			* Statement createStatement()
			* PreparedStatement prepareStatement(String sql)  
		2. 管理事务:
			* 开启事务:setAutoCommit(boolean autoCommit) //调用该方法设置参数为false,即开启事务
			* 提交事务:commit() 
			* 回滚事务:rollback()
*/

  注意:

    • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称[?参数名=参数值]
    • 不同的数据库连接的URL地址是不同的(如conn获取的就说mysql的地址对象),通用地址格式:
        • 协议名:子协议:l服务器名或IP地址:端口号/数据库名[?参数=参数值]
        • [?参数=参数值]:比如设置编码格式?characterEncoding=utf8

    4. 定义sql语句
    5. 获取执行sql语句的对象 Statement
      * Statement stmt = conn.createStatement();

/**
* PreparedStatement:执行sql的对象
* 	1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题;
*	2. 解决SQL注入问题:使用PreparedStatement对象来解决;
*	3. 预编译的SQL:参数使用?作为占位符;
* 	4. 给占位符?赋值
*			获取执行SQL的对象:
*				PreparedStatement ps = Connection.prepareStatement(String sql)
*			方法: ps.setXxx(参数1,参数2)
*					* 参数1:?的位置编号 从1 开始
*					* 参数2:?的值
*
* Statement:用于发送SQL语句给服务器,获取执行SQL的对象
* Statement接口中的方法:
*	1. boolean execute(String sql):可以执行任意的sql(了解) 
*	//返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
*	2. int executeUpdate(String sql):执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
*	//返回值:查询的结果集。
*	3. ResultSet executeQuery(String sql):执行DQL(select)语句
*
* ResultSet:结果集对象,封装查询结果
* 	作用:用于遍历结果集,获取每一条数据记录
*	接口中的方法:
* 		boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
*		getXxx(参数):获取数据
*			1. Xxx:代表数据类型   				如:int getInt(), String getString()
*			2. 参数
*				int:代表列的编号,从1开始。	如: getString(1)
*				String:代表列名称。			如: getDouble("balance")
*/

    6. 执行sql,接受返回结果(stmt.方法)
    7. 处理结果
    8. 释放资源  //释放资源一般写在finally代码块中,并需要判断对象是否为null

 小贴士:PreparedStatement是Statement接口的子接口,继承于父接口中的所有方法,后期都会使用PreparedStatement来完成增删改查的所有操作

     原因:① 可以有效防止SQL注入的问题,效率更高;

        ② 因为有预先编译的功能,SQL的执行效率更高。

 1.5 常用数据类型转换表

SQL类型 JDBC对应方法 返回类型
BIT(1) bit(n) getBoolean() boolean
TINYINT getByte() byte
SMALLINT getShort() short
INT getlnt() int
BIGINT getLong() long
CHAR,VARCHAR getString() String
Text(Clob) Blob getClob getBlob() Clob Blob
DATE getDate() java.sql.Date 只代表日期
TIME getTime() java.sql.Timestamp同时有日期和时间
TIMESTAMP getTimestamp() java.sql.Timestamp同时有日期和时间
  • java.sql.Date、Time、Timestamp(时间戳),三个共同父类是:java.util.Date

二、抽取JDBC工具类: JDBCUtils

  如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。

  JDBC就符合这样的要求,我们可以把一些共用的代码抽取出来,并通过获取配置文件资源的方式来让代码更具可重用性、可读性、可操作性。

  • JDBCUtils工具类

    抽取目的:简化书写,让代码更具可重用性、可读性、可操作性。

    抽取分析:

      1.  抽取注册驱动;
      2.  抽取一个方法获取连接对象;

        * 需求:不想传递参数(麻烦),还得保证工具类的通用性。
        * 解决:配置文件
          jdbc.properties
            url=
            user=
            password=
            driver=

       3.  抽取一个方法释放资源。

     代码实现:

public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    /**
     * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块。
     */
    static{
        //读取资源文件,获取值。
        try {
            //1. 创建Properties集合类。
            Properties pro = new Properties();

            //获取src路径下的文件的方式--->ClassLoader 类加载器
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL res  = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            
            //2. 加载文件
            pro.load(new FileReader(path));

            //3. 获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
			
            //4. 注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


	/**
	* 获取连接
	* @return 连接对象
	*/
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url, user, password);
	}


	/**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void closeSC(Statement stmt, Connection conn){
        if( stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if( conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
	
	/**
	 * 释放资源
	 * @param stmt
	 * @param conn
	 */
	public static void closeRSC(ResultSet rs, Statement stmt, Connection conn){
		if( rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if( stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if( conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

  

 三、JDBC操作事务

    之前我们已经使用Mysql的命令来操作事务,那么现在认识了JDBC后,如何通过JDBC来操作事务呢?

 1.1 通过Connection对象来管理事务

    Connection接口中有与事务相关的方法,可以通过这些方法来操作管理事务。

相关方法 操作
void setAutoCommit(boolean autoCommit) 调用该方法设置参数为false,表示关闭自动提交,即开启事务
void commit() 提交事务
void rollback() 回滚事务

 1.2 开发步骤

    1. 获取连接:Connection conn = JDBCUtils.getConnection();
    2. 开启事务:conn.setAutoCommit(false);
    3. 获取执行sql对象:conn.prepareStatement(sql);
    4. 执行sql,返回结果;
    5. 提交事务/回滚事务;
    6. 关闭资源。

 1.3 代码实现

public class JDBCAutoCommit {
	public static void main(String[] args) {
	    Connection conn = null;
	    PreparedStatement pstmt1 = null;
	    PreparedStatement pstmt2 = null;
	
	    try {
			//1.获取连接
			conn = JDBCUtils.getConnection();
			
			//2.开启事务
			conn.setAutoCommit(false);

			//3.定义sql
			String sql1 = "... ...";
			String sql2 = "... ...";
			//4.获取执行sql对象
			pstmt1 = conn.prepareStatement(sql1);
			pstmt2 = conn.prepareStatement(sql2);
			//5.设置参数
			... ...
			
			//6.执行sql
			pstmt1.executeUpdate();
			// 手动制造异常
			int i = 3/0;
			pstmt2.executeUpdate();
			
			//7.提交事务
			conn.commit();
		} catch (Exception e) {
			try {
				if(conn != null) {
					//8.事务回滚
					conn.rollback();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally {
			//9.关闭资源
			JDBCUtils.closeSC(pstmt1,conn);
			JDBCUtils.closeSC(pstmt2,null);
		}
	}
}
原文地址:https://www.cnblogs.com/sun9/p/13587077.html