JDBC_Day1
文章目录
一、JDBC的引言
1. 概念
JDBC(Java DataBase Connection)
利用java程序连接数据库的技术,通过ava程序连接广泛的数据库,并对数据库中的数据进行增加、删除、查询、修改的操作的技术。
通过navicat或者cmd工具将sql语句发送给数据库进而达到操作数据库的目的。本质上,JDBC的作用和前者的作用是相同的,都是发送sql语句到数据库中执行并将结果返回。差别在于,图形化界面是傻瓜的,而jdbc则需要通过编码的方式完成图形化操作的效果。
总结:jdbc本质上是一种发送sql语句操作数据库的技术,只不过需要通过java编码完成。
2. 为什么学习jdbc技术
java是可编程的(可定制的)可以将普通用户输入的数据拼接成各种各样的可以运行的sql语句,从而降低了普通用户使用数据库服务的难度。
3. JDBC访问数据的方式
JDBC访问数据库涉及到的API
Driver:驱动接口 定义了java如何和数据库获取连接等 #### DriverManager:工具类 提供了获取数据库的连接
Connection:连接的接口 代表java和数据库之间的联系
PreparedStatement:发送sql的工具接口
ResultSet:结果集接口,表示一个sql语句返回的结果。
4. JDBC涉及的类型是接口类型
JDBC是一种数据库访问技术,允许访问各种数据库,sun公司提供标准,各大数据库厂商提供相应的实现类,方便JDBC的代码在不同数据库间轻松迁移。
二、JDBC编程
1. 编码步骤
#### 加载驱动
#### 获取连接
#### 写sql语句
#### 执行sql语句(发送sql语句)
#### 如果是查询,针对查询的结果处理
#### 释放资源
Connection、PreparedStatement、ResultSet都是资源,就占用内存,必须要释放。
2. 第一个JDBC程序
向t_account表中添加一行数据
2.1 准备工作(搭建开发环境)
创建一个项目,需要在项目中引入数据库的驱动jar包(jar包:针对class文件的压缩格式,包含了多个带包的class文件,类似于普通文件打包的zip,rar)
#### eclipse
- 在项目根目录下创建一个文件夹(folder),文件夹名为lib,将数据库驱动jar包复制到 lib 文件下。
- 选中jar包右键选择Build Path --- > add to build path
#### idea
- 在项目根目录下创建一个文件夹(directory),文件夹名为lib,将数据库的驱动jar包复制到lib文件下。
- 选中lib文件夹右键选择Add as Library
2.2 编码
#### 增加的操作
package jdbc_day1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TestJDBCInsert {
public static void main(String[] args)throws Exception {
//加载驱动 (启动navicat) 将各种对象引入到内存中
Class.forName("com.mysql.cj.jdbc.Driver");//主动类加载 参数:权限定名
/*
getConnect()参数
参数1:url
参数2:username
参数3:password
url:
jdbc:遵守jdbc的协议 访问数据库
mysql:mysql数据库
localhost:ip 唯一定义一台计算机 localhost:代表本机
3306:端口号 port 定位一台计算机的某个软件 3306:mysql端口号
2106:database 数据库名 根据自己的数据库名进行更改
oracle:jdbc:oracle:thin:@localhost:1521:orcl
*/
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
//获取连接 Connection
Connection conn = DriverManager.getConnection(url, username, password);
//提供sql语句
String sql = "insert into t_account values(3,'cpx',2000.0)";
//执行sql PreparedStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
int count = pstmt.executeUpdate();
//如果是查询 则针对查询的结果处理 ResultSet
System.out.println("添加了 " + count +" 行数据");
//释放资源
pstmt.close();
conn.close();
}
}
3 更新的操作
public class TestJDBCUpdate {
public static void main(String[] args) throws Exception {
//1. 加载驱动 将Driver驱动加载到内存中 会抛出已检查异常 必须要处理的异常
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 创建PreparedStatement
String sql = "update t_account set name = 'zhangsan' where id = 1";
PreparedStatement pstmt = conn.prepareStatement(sql);
//4. 执行sql语句
int count = pstmt.executeUpdate();
//5. 针对查询的结果处理
System.out.println("更新了 " + count + " 行数据");
//6. 释放资源
pstmt.close();
conn.close();
}
}
4 JDBC的查询操作
需求:查询t_account表中的数据
select * from t_account;
编码
public class TestJDBCSelect {
public static void main(String[] args) throws Exception {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 创建PreparedStatement
String sql = "select * from t_account";
PreparedStatement pstmt = conn.prepareStatement(sql);
//4. 执行sql语句
ResultSet rs = pstmt.executeQuery();
//5. 针对查询的结果集处理
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
double balance = rs.getDouble("balance");
System.out.println(id+"\t"+name+"\t"+balance);
}
//6. 释放资源
rs.close();
pstmt.close();
conn.close();
}
}
三、数据绑定
将用户输入的数据绑定到要执行的sql语句中。
绑定的方式有两种
- 字符串拼接
- ?占位符绑定
1. 字符串拼接
本质上就是通过java字符串拼接的语法手动构造出正确的可以执行的sql语句。步骤如下:
- 在需要数据的地方,使用变量名替换
- 在变量名前添加 “+ , 在变量名后添加 +”
把数据去掉,然后加双引号,再加上双加号,加号中间加变量名。
public class TestJDBCInsert {
public static void main(String[] args) throws Exception {
//1. 加载驱动 将Driver驱动加载到内存中 会抛出已检查异常 必须要处理的异常
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
String name = "chenpx";
int id = 1;
//3. 创建PreparedStatement
String sql = "update t_account set name = '"+name+"' where id = "+id+"";
PreparedStatement pstmt = conn.prepareStatement(sql);
//4. 执行sql语句
int count = pstmt.executeUpdate();
//5. 针对查询的结果处理
System.out.println("更新了 " + count + " 行数据");
//6. 释放资源
pstmt.close();
conn.close();
}
}
2. ?占位符
是JDBC中的一种特定语法,专用于参数绑定。使用步骤如下:
- 在需要使用数据的地方,使用?占位
- 执行sql语句之前,通过pstmt.setXxx()方法给?赋值
setXXX( 第几个?,值 ) Xxx:代表数据类型
整数:setInt();
小数:setDouble();
字符串:setString();
日期:setDate()
public class TestJDBCInsert {
public static void main(String[] args) throws Exception {
//1. 加载驱动 将Driver驱动加载到内存中 会抛出已检查异常 必须要处理的异常
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 创建PreparedStatement
String sql = "update t_account set name = ? where id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
//为?赋值
pstmt.setString(1,"zhangsan");
pstmt.setInt(2,1);
//4. 执行sql语句
int count = pstmt.executeUpdate();
//5. 针对查询的结果处理
System.out.println("更新了 " + count + " 行数据");
//6. 释放资源
pstmt.close();
conn.close();
}
}
3. 字符串拼接和?占位符的区别
方式 | 特点 | 使用场景 | 最佳实践 |
---|---|---|---|
字符串拼接 | 可能会被sql注入攻击 | 可以拼接表名、列名、sql关键字 | 动态的查询给bu’to的表以及根据用户的选择设升序或降序查询数据 |
?占位符 | 可以防止sql注入的攻击 | 绑定纯数据 | 通常情况下使用占位符 |
四、JDBC中的异常
1 解决问题的步骤
#### 定位问题(哪一行出错了)
- 添加打印语句
- 根据异常信息的日志定位(控制台中出现的关于自己代码的部分的报错信息)
#### 为什么出错
根据异常信息和自己所学的知识分析问题的原因
#### 解决错误
根据问题的原因,解决异常且一定要将异常记录下来(方便下次调错)
2 根据异常日志分析错误
分析异常最高效的办法就是阅读异常日志,根据异常日志提供的信息,可以快速定位到问题的位置,进而解决问题。
-
查看异常类型
ClassNotFoundException: com.mysql.cj.jdbc.Drvier:驱动类文件没有找到
-
报错位置
自上而下查看报错代码的位置,找到自己写的代码进入到指定位置,检查错误。 -
解决问题
错误原因- 驱动类类名写错 (本案例中出错原因)
- 驱动jar包没有导入。
3 添加打印语句
可以在代码的关键位置添加打印语句,通过观察语句的输出与否判断异常产生的原因。注意:打印的语句尽量有意义,如代码存在返回值可以打印返回值等。
public class TestJDBCSelect {
public static void main(String[] args) throws Exception {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Drvier");
System.out.println("驱动类加载成功");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
System.out.println("连接创建成功 con = " + conn);
//3. 创建PreparedStatement
String sql = "select * from t_account";
PreparedStatement pstmt = conn.prepareStatement(sql);
System.out.println("创建Prepared Statement成功 pstmt = " + pstmt);
//4. 执行sql语句
ResultSet rs = pstmt.executeQuery();
System.out.println("sql语句执行成功 rs = " + rs);
//5. 针对查询的结果集处理
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
double balance = rs.getDouble("balance");
System.out.println(id+"\t"+name+"\t"+balance);
}
//6. 释放资源
rs.close();
pstmt.close();
conn.close();
}
}
4 掌握JDBC中常见的异常
url中如果localhost写错,报Caused by: java.net.UnknownHostException: localhosst
url中port写错,报错不能连接到数据库
用户名或者密码错误
#### url中database写错
sqlException
JDBC_Day2
一、Junit单元测试
1. 传统的主函数作为测试类存在的问题
- 系统测试类数量过多,代码冗余,不便于项目
- 回测性差
2. Junit单元测试工具
2.1 作用:代替主函数进行java代码的测试
2.2 使用
#### 引入junit相关的jar包
将junit的jar引入到lib,然后选择lib文件夹右键选择add as library
#### 创建测试类
/*
1. 添加@Test注解 注解写在方法上
2. 写测试方法 方法名随意 遵守标识符规范即可
访问修饰符 返回值类型 方法名 ( 参数表 ) 抛出异常{}
访问修饰符:public
返回值类型: void
参数表:无参
抛出异常根据需要决定
*/
//测试类
public class TestJDBC {
@Test
public void test1(){
String name = "cpx";
System.out.println(name);
}
}
如果将来还有其他测试方法,则还需要添加@Test注解
2.3 常见的错误
- 类名不能与注解名相同,即不能叫Test。
- 测试方法没有加@Test注解:测试方法不能运行
- 如果第一个测试方法添加了@Test注解,但是第二个方法没加@Test注解,当前的测试方法没法运行,运行结果是原来的测试方法
2.4 补充
Junit4中的注解有 @Before、@After、@Test、@Ignore、@BeforeClass、@AfterClass。
二、日期的处理
数据库中的类型 | Java中的类型 |
---|---|
int、Integer | Integer |
double、decimal | Double |
varchar(m) | String |
datetime | java.sql.Date |
在程序中会使用到哪些类型的日期
String、java.util.Date(在java中使用最频繁的日期)、java.sql.Date(JDBC操作中使用的类型)
1. java.util.Date和java.sql.Date关系
java.sql.Date 是 java.util.Date的子类,可以使用多态。
查询功能时,可能会从数据库中查询一些日期类型的数据,可以直接保存在java.util.Date中。
java.util.Date utilDate = rs.getDate("birthday");
java.util.Date utilDate = rs.getDate("hiredate");
2. strDate转换成sqlDate
需求:将“1996-12-13” 转换成 java.sql.Date 进而存储到数据库中
注意:strDate不能直接转换成sqlDate,中间需要借助于java.util.Date
@Test
public void testDate() throws ParseException {
String strDate = "1996-12-13";
//strDate --- > utilDate
//SimpleDateFormat:工具类 参数:日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date utilDate = sdf.parse(strDate);
System.out.println(utilDate);
//将utilDate转换成sqlDate
//java.sql.Date构造方法 没有无参构造方法 需要参数 long time
long time = utilDate.getTime();//时间的毫秒整数 10分钟 10*60*1000 = 600000ms
java.sql.Date sqlDate = new java.sql.Date(time);
System.out.println(sqlDate);
}
3. sqlDate在jdbc中的使用
@Test
public void testInsert() throws Exception{
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 创建PreparedStatement
String sql = "insert into t_person values(null,?,?,?,?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
//4. 为?赋值
pstmt.setString(1,"cpx");
pstmt.setInt(2,20);
pstmt.setString(3,"男");
pstmt.setDouble(4,3000.0);
pstmt.setString(5,"15139785182");
pstmt.setString(6,"河南省郑州市惠济区刘寨社区");
String date = "1995-12-13";
//jdbc中日期使用java.sql.Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date utilDate = sdf.parse(date);
java.sql.Date birthday = new java.sql.Date(utilDate.getTime());
pstmt.setDate(7,birthday);
//5. 执行sql语句
pstmt.executeUpdate();
//6. 释放资源
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
}
jdbc中使用try-catch-finally处理异常
@Test
public void testQuery(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 可能出现异常的代码
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
conn = DriverManager.getConnection(url, username, password);
String sql = "select * from t_person where pid = ?";
pstmt = conn.prepareStatement(sql);
//为?赋值
pstmt.setInt(1,1);
//执行sql语句
rs = pstmt.executeQuery();
//针对查询的结果处理
while(rs.next()){
int pid = rs.getInt("pid");
String pname = rs.getString("pname");
int age = rs.getInt("age");
String sex = rs.getString("sex");
double salary = rs.getDouble("salary");
String mobile = rs.getString("mobile");
String address = rs.getString("address");
java.util.Date birthday = rs.getDate("birthday");
System.out.println(pid+"\t"+pname+"\t"+age+"\t"+sex+"\t"+salary+"\t"+mobile+
"\t"+address+"\t"+birthday);
}
}catch (Exception e){
// 出现异常后执行的代码
e.printStackTrace();
}finally {
// 最终执行的代码(不管是否存在异常 释放资源的代码)
if(rs!=null)try{rs.close();}catch (Exception e){e.printStackTrace();}
if(pstmt!=null)try{pstmt.close();}catch (Exception e){e.printStackTrace();}
if(conn!=null) try{conn.close();}catch (Exception e){e.printStackTrace();}
}
}
三、IO和Properties集合的简单回顾
1. IO流(基本的操作)
@Test
public void testIO() throws Exception{
FileInputStream fis = new FileInputStream("a.txt");
while(true){
int read = fis.read();
if(read == -1)break;
System.out.print((char)read);
}
System.out.println();
}
2. Properties
Hashtable的子类(Map集合的实现类)。
特点:
#### key:String;value:String
- 如果配置文件是以key=value的方式,一旦通过io流将配置文件中的内容加载到内存的Properties中,会自动的将配置文件的key当作集合的key;将配置文件的值当作集合的值
@Test
public void testProperties(){
/*
Map: key-value
HashMap:
Hashtable jdk1.0 --- > Properties (key:String value:String) 经常用于文件的读取
jdk5.0以后泛型
*/
Properties p = new Properties();
//在Properties集合中存储一个key-value
p.setProperty("driver","com.mysql.cj.jdbc.Driver");
p.setProperty("url","jdbc:mysql://localhost:3306/2106");
p.setProperty("username","root");
p.setProperty("password","root");
//通过key获取value
System.out.println(p.getProperty("driver"));
System.out.println(p.getProperty("url"));
System.out.println(p.getProperty("username"));
System.out.println(p.getProperty("password"));
}
@Test
public void testProperties2() throws Exception{
//通过io将文件中的内容读入到内存中
InputStream is = new FileInputStream("a.txt");
//将流中的内容加载到Properties集合中
Properties p = new Properties();
p.load(is);
//直接从集合中通过key获取value
System.out.println(p.getProperty("driver"));
System.out.println(p.getProperty("url"));
System.out.println(p.getProperty("username"));
System.out.println(p.getProperty("password"));
}
四、JDBCUtils工具类的封装
1. 现有jdbc代码中存在的问题
冗余代码过多(第1,2,6步)
2. 代码重构思想
将冗余代码提取出来,封装成函数,以便于复用。(函数不能单独存在必须依附于类—工具类)
一般将工具类放置在com.baizhi.util包下
3. 第一版本JDBCUtils工具类的封装
基于功能复用的原则
public class JDBCUtils {
//获取连接的方法
public static Connection getConn(){
Connection conn = null;
try{
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 创建连接
String url = "jdbc:mysql://localhost:3306/2106";
String username = "root";
String password = "root";
conn = DriverManager.getConnection(url, username, password);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return conn;
}
//释放资源的方法
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs){
if(rs!=null){try{rs.close();}catch (Exception e){e.printStackTrace();}}
if(pstmt!=null){try{pstmt.close();}catch (Exception e){e.printStackTrace();}}
if(conn!=null){try{conn.close();}catch (Exception e){e.printStackTrace();}}
}
}
使用
@Test
public void testQuery(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
//通过工具类获取连接
conn = JDBCUtils.getConn();
String sql = "select * from t_person where pid = ?";
//3. 创建PreparedStatement
pstmt = conn.prepareStatement(sql);
//为?赋值
pstmt.setInt(1,1);
//4. 执行sql语句
rs = pstmt.executeQuery();
//5. 针对查询的结果处理
while(rs.next()){
int pid = rs.getInt("pid");
String pname = rs.getString("pname");
int age = rs.getInt("age");
String sex = rs.getString("sex");
double salary = rs.getDouble("salary");
String mobile = rs.getString("mobile");
String address = rs.getString("address");
java.util.Date birthday = rs.getDate("birthday");
System.out.println(pid+"\t"+pname+"\t"+age+"\t"+sex+"\t"+salary+"\t"+
mobile+"\t"+address+"\t"+birthday);
}
}catch (Exception e){
// 出现异常后执行的代码
e.printStackTrace();
}finally {
// 最终执行的代码(不管是否存在异常 释放资源的代码)
//6 通过释工具类放资源释放资源
JDBCUtils.close(conn,pstmt,rs);
}
}
问题:jdbc连接参数硬编码在了程序中,不利于后期代码的维护和修改
解决思路:将程序中经常需要修改的字符串提取到配置文件中,通过io流读取到内存中
4. 第二版本的JDBCUtils工具类的封装
配置文件:
- 格式以key=value
- 文件名以properties结尾
4.1 创建jdbc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/2106
username=root
password=root
4.2 在JDBCUtils中通过io流的方式读取
public class JDBCUtils {
//获取连接的方法
public static Connection getConn(){
Connection conn = null;
try{
//将配置文件中的内容读取到流中
InputStream is = new FileInputStream("file/jdbc.properties");
//将流中的内容加载到Properties集合
Properties p = new Properties();
p.load(is);
//1. 加载驱动
Class.forName(p.getProperty("driver"));
//2. 创建连接
String url = p.getProperty("url");
String username = p.getProperty("username");
String password = p.getProperty("password");
conn = DriverManager.getConnection(url, username, password);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return conn;
}
//释放资源的方法
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs){
if(rs!=null){try{rs.close();}catch (Exception e){e.printStackTrace();}}
if(pstmt!=null){try{pstmt.close();}catch (Exception e){e.printStackTrace();}}
if(conn!=null){try{conn.close();}catch (Exception e){e.printStackTrace();}}
}
}
问题:性能问题,每次调用getConn()都会获取流读取配置文件的内容。
解决:将读取配置文件的操作放到静态代码块中,保证读取文件的操作有且只执行1次。
4.3 第三个版本的JDBCUtils的封装
public class JDBCUtils {
//将流中的内容加载到Properties集合
private static Properties p = new Properties();
//保证在类加载时只读取一次配置你文件
static{
InputStream is = null;
try {
//将配置文件中的内容读取到流中
is = new FileInputStream("file/jdbc.properties");
p.load(is);
}catch (Exception e){
e.printStackTrace();
}finally {
if(is!=null) {
try {is.close();} catch (IOException e) {e.printStackTrace();}
}
}
}
//获取连接的方法
public static Connection getConn(){
Connection conn = null;
try{
//1. 加载驱动
Class.forName(p.getProperty("driver"));
//2. 创建连接
String url = p.getProperty("url");
String username = p.getProperty("username");
String password = p.getProperty("password");
conn = DriverManager.getConnection(url, username, password);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return conn;
}
//释放资源的方法
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs){
if(rs!=null){try{rs.close();}catch (Exception e){e.printStackTrace();}}
if(pstmt!=null){try{pstmt.close();}catch (Exception e){e.printStackTrace();}}
if(conn!=null){try{conn.close();}catch (Exception e){e.printStackTrace();}}
}
}
对于配置文件读取的方式采用如下方式
public class JDBCUtils {
//将流中的内容加载到Properties集合
private static Properties p = new Properties();
//保证在类加载时只读取一次配置你文件
static{
InputStream is = null;
try {
//将配置文件中的内容读取到流中
//is = new FileInputStream("file/jdbc.properties");
//任何一个类都要做类加载,类加载的过程需要使用输入流 路径:/代表根目录(src)
// /com/baizhi/conf/jdbc.properties 代表src/com/baizhi/conf/jdbc.properties 路径
is = JDBCUtils.class.getResourceAsStream("/com/baizhi/conf/jdbc.properties");
p.load(is);
}catch (Exception e){
e.printStackTrace();
}finally {
if(is!=null) {
try {is.close();} catch (IOException e) {e.printStackTrace();}
}
}
}
//获取连接的方法
public static Connection getConn(){
Connection conn = null;
try{
//1. 加载驱动
Class.forName(p.getProperty("driver"));
//2. 创建连接
String url = p.getProperty("url");
String username = p.getProperty("username");
String password = p.getProperty("password");
conn = DriverManager.getConnection(url, username, password);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return conn;
}
//释放资源的方法
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs){
if(rs!=null){try{rs.close();}catch (Exception e){e.printStackTrace();}}
if(pstmt!=null){try{pstmt.close();}catch (Exception e){e.printStackTrace();}}
if(conn!=null){try{conn.close();}catch (Exception e){e.printStackTrace();}}
}
}
总结
- 解决代码冗余的典型方案:将冗余代码提出到一个工具类中(JDBCUtils)。
- 代码中如果有经常需要修改的字符串时,可以将字符串提取到配置文件(数据库的连接参数提取到properties集合中)
- 保证配置文件中的内容有且只读取一次,将配置文件的读取放置在静态代码块中。