花几分钟带你了解JDBC


大家好,我是EverdayForCode。今天你学习了吗?
花几分钟时间,EverDayForCode带你了解JDBC

JDBC介绍

JDBC是什么

JDBC:1Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成,是Java访问数据库的标准规范。
JDBC是接口,驱动是接口的实现类,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

JDBC可以用来干嘛

JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

JDBC API主要包括哪些

斜体代表接口,需驱动程序提供者来具体实现

API作用
DriverManager负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)
Driver驱动程序,会将自身加载到DriverManager中去,并处理相应的请求并返回相应的数据库连接(Connection)
Connection数据库连接,负责与进行数据库间通讯,SQL执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement。
Statement用以执行SQL查询和更新(针对静态SQL语句和单次执行)
PreparedStatement用以执行包含动态参数的SQL查询和更新(在服务器端编译,允许重复执行以提高效率)
CallableStatement用以调用数据库中的存储过程
SQLException代表在数据库连接的建立和关闭和SQL语句的执行过程中发生了例外情况(即错误)

JDBC与SQL数据映射

这种类型匹配不是强制性标准,特定的JDBC厂商可能会改变这种类型匹配。例如Oracle中的DATE类型是包含时分秒,而java.sql.Date仅仅支持年月日

SQL类型Java类型
CHARjava.lang.String
VARCHARjava.lang.String
LONGVARCHARjava.lang.String
NUMERICjava.math.BigDecimal
DECIMALjava.math.BigDecimal
BITboolean
TINYINTbyte
SMALLINTshort
INTEGERint
BIGINTlong
REALfloat
FLOATdouble
DOUBLEdouble
BINARYbyte[]
VARBINARYbyte[]
LONGVARBINARYbyte[]
DATEjava.sql.Date
TIMEjava.sql.Time
TIMESTAMPjava.sql.Timestamp
BLOBjava.sql.Blob
CLOBjava.sql.Clob
Arrayjava.sql.Array
REFjava.sql.Ref
Structjava.sql.Struct

JDBC 编程步骤

1. 导入相应数据库jar包

eclipse导包

右键project->property->java build path->libaries->add external jars
eclipse导包

IntelliJ idea导包

1. 普通导包

File->Project Structure->Libraries->+
idea导包idea导包

2. maven导包

pom.xml添加一下代码:

		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

2. 编写代码

2.1 加载驱动程序

/*
driver = “com.mysql.jdbc.Driver” or driver = “com.mysql.cj.jdbc.Driver”
*/
try {
        Class.forName(driver);		
        } catch (ClassNotFoundException e) { 				
            e.printStackTrace();
        }

Class.forName需要捕获ClassNotFoundException
不同版本的MySQL需要不同的驱动详细见下文:
那些MySQL5.x和MySQL6.x及以上踩过的坑

2.2 获取数据库连接

/*
url = "jdbc:mysql://127.0.0.1:3306/+数据库名称"
user = "root"
password = "你的数据库密码"
*/
try{
	Connection conn = DriverManager.getConnection(url, user, password);
}catch(SQLException e){
	e.printStackTrace();
}

需要捕获SQLException异常

2.3 封装成工具类便于调用

        /**
	 * 取得数据库的连接
	 * @return 一个数据库的连接
	 */
public static Connection getConnection(String driver,String url,String user,String password){
		Connection conn = null;
		 try {
			 	//初始化驱动类com.mysql.jdbc.Driver
	            Class.forName(driver);
	            conn = DriverManager.getConnection(url,user, password);
	            //该类就在 mysql-connector-java-5.0.8-bin.jar中,如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException
	        } catch (ClassNotFoundException e) { 				
	            e.printStackTrace();
	        }catch (SQLException e) {							
	            e.printStackTrace();
	        }
		 return conn;
	}

2.4 创建Statement或者PreparedStatement接口,执行SQL语句

2.4.1使用Statement接口

Statement接口创建之后,可以执行SQL语句,完成对数据库的增删改查。其中 ,增删改只需要改变SQL语句的内容就能完成,然而查询略显复杂。在Statement中使用字符串拼接的方式,该方式存在句法复杂,容易犯错等缺点,所以Statement在实际过程中使用的非常的少。

字符串拼接方式的SQL语句是非常繁琐的,中间有很多的单引号和双引号的混用,极易出错。

Statement s = conn.createStatement();
// 准备sql语句
// 注意: 字符串要用单引号'
String sql = "insert into t_courses values(null,"+"'数学')";
//在statement中使用字符串拼接的方式,这种方式存在诸多问题
s.execute(sql);
System.out.println("执行插入语句成功");
2.4.2 使用PreparedStatement接口

Statement一样,PreparedStatement也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement。除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。

给数据库中添加课程: (以下代码中最后关闭资源的两个方法 DbUtil.close(pstmt); DbUtil.close(conn); 和上面的建立连接的方法是一样的,是在工具类中定义了的关闭方法,下文会给出其代码)

        /**
	 * 添加课程
	 * @param courseName 课程名称
	 */
	public void addCourse(String courseName){
		String sql = "insert into t_course(course_name) values(?)";  
 //该语句为每个 IN 参数保留一个问号(“?”)作为占位符
		Connection conn = null;				//和数据库取得连接
		PreparedStatement pres = null;		//创建statement
		try{
			conn = DbUtil.getConnection(driver,url,user,passsword);
			pres = conn.prepareStatement(sql);
			pres.setString(1, courseName); //给占位符赋值
			pres.executeUpdate();			//执行
		}catch(SQLException e){
			e.printStackTrace();
		}
		finally{
			DbUtil.close(pres);
			DbUtil.close(conn);		//必须关闭
		}
	}

注意:

  1. 使用PreparedStatement时,他的SQL语句不再采用字符串拼接的方式,而是采用占位符的方式。“”在这里就起到占位符的作用。这种方式除了避免了statement拼接字符串的繁琐之外,还能够提高性能。每次SQL语句都是一样的,java类就不会再次编译,这样能够显著提高性能。
  2. 后面需要用到PreparedStatement接口创建的pstmtset方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
  3. 增删改都使用pstmt.executeUpdate();语句进行SQL语句的提交 ,下文的查询会有所不同,请注意。
  4. 在添加的过程的,如果添加的数据量比较大的话,可以用批量添加。 PreparedStatement接口提供了相应的批量操作的方法。
for(int i=1;i<100;i++){
    pstmt.setInt(1,8000+i);
    pstmt.setString(2,"赵_"+i);
    pstmt.addBatch();
//批量更新
    if(i%10==0){
    pstmt.executeBatch();
   }
}

下面我们来看稍显麻烦一点的查询操作:

        /**
	 * 查询课程
	 * @return
	 */
	public List<Course> findCourseList(){
		String sql = "select * from t_course order by course_id";
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		//创建一个集合对象用来存放查询到的数据
		List<Course> courseList = new ArrayList<>();
		try {
			conn = DbUtil.getConnection();
			pstmt = (PreparedStatement) conn.prepareStatement(sql);
			rs = (ResultSet) pstmt.executeQuery();
			while (rs.next()){
				int courseId = rs.getInt("course_id");
				String courseName = rs.getString("course_name");
				//每个记录对应一个对象
				Course course = new Course();
				course.setCourseId(courseId);
				course.setCourseName(courseName);
				//将对象放到集合中
				courseList.add(course);
			}
		} catch (SQLException e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally{
			DbUtil.close(pstmt);
			DbUtil.close(conn);		//必须关闭
		}
		return courseList;
	}

查询操作使用executeQuery()进行更新。其他相关的问题放在第2.5(处理和显示结果)中解释。

2.4.3 StatementPreparedStatement的异同及优缺点

同:两者都是用来执SQL语句的

异:PreparedStatement需要根据SQL语句来创建,它能够通过设置参数,指定相应的值,不是像Statement那样使用字符串拼接的方式。

PreparedStatement的优点:

1、其使用参数设置,可读性好,不易记错。在statement中使用字符串拼接,可读性和维护性比较差。

2、其具有预编译机制,性能比statement更快。

3、其能够有效防止SQL注入攻击。

2.4.4 executeexecuteUpdate的区别

相同点:二者都能够执行增加、删除、修改等操作。

不同点:

1、execute可以执行查询语句,然后通过getResult把结果取出来。executeUpdate不能执行查询语句。

2、execute返回Boolean类型,true表示执行的是查询语句,false表示执行的insertdeleteupdate等。executeUpdate的返回值是int,表示有多少条数据受到了影响。

2.5处理和显示结果

执行查询语句,并把结果集返回给集合ResultSet

ResultSet rs = s.executeQuery(sql);

利用While(ResultSet.next()){…}循环将集合ResultSet中的结果遍历出来。

ResultSet.getXX(); 这里的get方法的括号里面可以填属性值,如下图代码中的course_id,还可以填该属性在数据表中的列号,从1开始编码,例如:course_id在我的t-courses数据表中位于第一列,所以执行get方法的时候,我除了代码段中写法外,还可以这样写int courseId = rs.getInt(1);但是不推荐使用列号的这种方式,因为一段数据表中个属性值得顺序发生变化,就会导致这里出错,而使用属性名则不会出现这样的问题。

		while (rs.next()){
		int courseId = rs.getInt("course_id");
		String courseName = rs.getString("course_name");
		//每个记录对应一个对象
		Course course = new Course();
//在我的项目中创建了course类,其中定义了set方法,所以这里将查询到的值传给了course,也可以直接打印到控制台
		course.setCourseId(courseId);
		course.setCourseName(courseName);
		//将对象放到集合中
		courseList.add(course);
		}

rs.next()用法值得注意,具体详见以下博客:

2.6释放资源

在JDBC编码的过程中我们创建了ConnectionResultSet等资源,这些资源在使用完毕之后是一定要进行关闭的。关闭的过程中遵循从里到外的原则。因为在增删改查的操作中都要用到这样的关闭操作,为了使代码简单,增加其复用性,这里我将这些关闭的操作写成一个方法和建立连接的方法一起放到一份工具类中。

/**
	 * 封装三个关闭方法
	 * @param pstmt
	 */
	public static void close(PreparedStatement pstmt){
		if(pstmt != null){						//避免出现空指针异常
			try{
				pstmt.close();
			}catch(SQLException e){
				e.printStackTrace();
			}
			
		}
	}
	
	public static void close(Connection conn){
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}
	
	public static void close(ResultSet rs){
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}

参考博客:
JDBC详细介绍


  1. 摘自百度百科 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值