博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据库面试技巧,通过JDBC展示自己专业性,摘自java web轻量级开发面试教程
阅读量:7095 次
发布时间:2019-06-28

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

       这篇文章是我之前写的博文  和 

是一个系列的,通过面试官的视角和大家分享在数据库方面的面试经验,这些内容都来摘自  。

       之前的两篇文章点击量都还行,也感谢管理员放入首页,这鼓舞到了我,也让我更有信心和大家分享我的经验。

        我们知道,最终我们是要通过jdbc来连接并访问数据库的,也就是说,最近面试官一定会通过JDBC方面的技能来考核候选人的能力,这篇文章就是和大家展示这方面的说辞。

 

 

1  用try…catch…finally从句

       根据这个从句的特性,不论是否发生异常,不论发生何种异常,finally从句一定会执行(除非用System.exit退出)。

        根据这个特性,需要把关闭JDBC对象部分的代码写到finally从句里。

        同时,在try…catch里应该注意如下三点:

        第一,不能直接用Exception来接收所有异常,应当先用专业的异常处理类,比如SQLException来接收,最后再用Exception来做最后的防守。

      第二,在catch从句里,别什么都不做,也别直接抛出异常了事,应该返回一些有可操作性的语句,提示用户在遇到异常时该怎么办,比如给出联系人的电话。

     第三,因为监听和检测异常是需要代价的,所以应当尽量缩小try…catch的范围,只包括必要的代码即可,而不是把整个函数都包含在try…catch从句里。

      大家别小看上述非常通俗易懂的原则。作者在某个大公司工作时,曾加过一个项目的评审团队,该公司所有的项目在上线前都要经过这个团队评审打分,如果分数达不到标准,就需要整改代码。

      刚提到的这些原则都是具体的打分项,这个大公司是著名外企,其中的员工都很优秀,但在异常处理点上失分是普遍现象。换句话说,如果大家在面试中说出上述的说辞,一定会让面试官对大家刮目相看。

      下面通过一个简单的查询例子ResultDemo.java来观察下标准写法。有个Student表,其中有两个字段,均为字符类型的学号ID和姓名Name。

1 import java.sql.Connection; 2 import java.sql.DriverManager; 3 import java.sql.ResultSet; 4 import java.sql.SQLException; 5 import java.sql.Statement; 6 public class ResultDemo { 7     public static void main(String[] args) { 8         try { 9                //需要确保支持MySQL的jar能被读到10               Class.forName("com.mysql.jdbc.Driver");11             } catch (ClassNotFoundException e) {12                 System.out.println("Where is your MySQL JDBC Driver?");13                 e.printStackTrace();14                 return;15             }16             Connection connection = null;17             Statement stmt = null;18             try {19             //这里是连接字符串20                 connection = DriverManager.getConnection(21                     "jdbc:mysql://localhost:3306/class3", "root", "123456");22                 if (connection != null) {23                     stmt = connection.createStatement();24                     String query = "select ID,Name from student";25                     ResultSet rs=stmt.executeQuery(query);26                     while(rs.next())27                     {28                         System.out.println(rs.getString(“ID”));29                         System.out.println(rs.getString("Name"));30                     }31                 } else {32                     System.out.println("Failed to make connection!");33                 }34             } catch (SQLException e) {35     System.out.println("Check the JDBC Driver or Connection!");36                 e.printStackTrace();37             } finally {38             //close the connection 39                 try {40                         stmt.close();41                 connection.close();42                 } catch (SQLException e) {43                     e.printStackTrace();44                 }45             }46         }47     }

    

      上述代码的业务非常简单,连接数据库后依次打印Student表里的ID和Name信息。但请大家关注一下这段代码带给我们的启示。

        第一,在短短的业务逻辑里,我们分别在第8到第15行,第18到第44行,用了两块try…catch,而没有图省事用一块try…catch代码包含所有的业务方法,这遵循了“尽量缩小检测范围”的原则。

        第二,在第35和36行的catch从句里,没有简单地抛出异常了事,而是输出了一些信息,根据这些信息,调试程序的开发人员能很快从中得到提示,从而很快地找到原因。

        此外,在catch从句里,也可以输出一些面向使用者的提示信息,比如让使用者重启程序,总之一句话,需要把面向Java的异常翻译成让程序员或使用者能理解的提示信息。

       第三,在第37到第44行的finally从句里,关闭了连接,因为不论发生了什么异常,或者是否发生异常,finally从句一定会被执行到,所以可以把关闭连接的代码放入其中。如果不关闭连接,这个数据库连接对象是无法被回收的(Java的垃圾回收机制也无法回收)。

 

2  预处理和批处理

         这里对应的问题有:你有没有用过PreparedStatement对象?PreparedStatement和Statement有什么差别?

         请大家说清楚两点,1 提升效率,2 避免SQL注入,从而保证系统的安全。

         什么叫SQL注入?例如有下图所示的登录界面。

         

       我们一般用如下SQL来验证身份:

Select userName from users where username = ‘输入的用户名’ and pwd = ‘输入的密码’

       一般来说,如果用户名和密码不匹配,是无法通过验证的,但有人可以在User Name里输入1,在User Password部分输入:1’ and pwd = ‘1’ or ‘1’=’1

        那么整个SQL语句就会变成:

         Select userName from users where username = ‘1’ and pwd = ‘1’ or ‘1’=’1’

         这样就能绕过验证。

          而处理对象PrepareStatement能有效防止这个现象的发生,因为一个“?”就是一个占位符,无法扩展。下面来看一个预处理和批处理结合的例子,同样用到刚才提到的Student表,这次来批量插入数据。         

import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;import java.sql.Statement;public class JDBCBatch {	public static void main(String[] args) {		try {			Class.forName("com.mysql.jdbc.Driver");		} catch (ClassNotFoundException e) {			System.out.println("Where is your MySQL JDBC Driver?");			e.printStackTrace();			return;		}		Connection connection = null;	        PrepareStatement pstmt;			try {	        //这里是连接字符串				connection = DriverManager.getConnection(						"jdbc:mysql://localhost:3306/class3", "root", "123456");				if (connection != null) {					String query = "insert into student values (?,?)";					pstmt = connection.preparedStatement(query);//开始设置参数					pstmt.setString(1,"1");					pstmt.setString(2,"Peter");					pstmt.addBatch();					//设置第二个参数					pstmt.setString(1,"2");					pstmt.setString(2,"Mike");					pstmt.addBatch();					//执行批处理					pstmt.executeBatch();								} else {					System.out.println("Failed to make connection!");				}			} catch (SQLException e) {				System.out.println("Some of Students were not inserted correctly, please check the student table and insert manually.");				e.printStackTrace();			} finally {				try {					connection.close();				} catch (SQLException e) {					e.printStackTrace();				}			}		}	}

  这部分的逻辑也比较简单,用insert语句批量插入数据。但请大家注意如下两点:

① 在PrepareStatement里,占位符的编号是从1开始,而不是从0开始。

② 批量操作能提升效率,但一次性操作多少,才能让效率提升到最高?这在不同的数据库里是不同的,一般是每批操作500到1000条语句。但切记,别一次性把所有的insert语句都用addBatch放入,因为如果SQL语句过多,会撑爆缓存,从而出错。

       PrepareStatement是个比较重要的JDBC对象。再重复一下,我们在面试的时候,有时会问这个问题:Statement和PrepareStatement有什么差别?答案要点是PrepareStatement能预处理,如果能展开一下,说明能防止SQL注入就更好了。

       总结一下,这里大家可以通过叙述代码里的要点来阐释自己在JDBC方面的能力。

       1 阐述try...catch...finally的用法。

       2 详细阐述PreparedStatement的用法,包括预处理批处理和SQL注入两点。

 

转载于:https://www.cnblogs.com/JavaArchitect/p/7482769.html

你可能感兴趣的文章
Spark log4j 日志配置详解
查看>>
Java学习:JVM是什么?
查看>>
深度解析国内首个云原生数据库POLARDB的“王者荣耀”
查看>>
常见乱码问题分析和总结
查看>>
Spring MVC 源码解析(二)— 容器初始化
查看>>
Android NDK开发之旅8 C语言基础 预编译
查看>>
iOS的 gRPC 之路
查看>>
【译】Swift算法俱乐部-二分搜索
查看>>
Android面试题(三)
查看>>
Android 重识MVP 你应该知道的写法
查看>>
ionic2 中使用iconfont
查看>>
Redis命令详解:String
查看>>
使用css的伪类给html代码块添加代码种类
查看>>
小程序实战踩坑之B2B商城项目总结
查看>>
阿里如何做到百万量级硬件故障自愈?
查看>>
猫晚流量再创记录,阿里云直播方案护航优酷2500万用户体验
查看>>
Java架构-(十二) 整合spring cloud云架构 - SSO单点登录之OAuth2.0 登出流程(3)
查看>>
ReactNative干货分享——视频播放器App
查看>>
详解 PHP 数组的底层实现:HashTable
查看>>
函数式点滴--partial&curry
查看>>