在上篇文章中,已经开始对原始代码进行一定的优化,同时站在客户的角度我们也发现了新的问题:
1、在许多公司的内部,为了保证数据的安全性,定期会修改公司的内部账号,数据库账号密码也不例外。那么,我们在给客户设计程序的时候,如果像之前这样将用户名密码直接写在代码中,是十分不利于客户使用的。并且将代码交给客户也是存在很大风险的一件事。因此,我们需要找到一个方法来解决这个问题。
2、客户对于操作后,executeUpdate()
返回影响了几行数据的这种结果可能并不买账。我们需要一个更直观的操作结果。
针对问题一,我们可以想到用什么办法解决呢?以下是笔者的思考路程
1.用户操作之前,弹出提示让用户输入用户名和密码。
嗯这也是常见的办法, 相似的有软件的登录、网页的登录都是同样的套路。那么这个登录肯定不是每次操作都需要重新输入。而是只需要登录一次即可。根据之前的代码,每次JDBC操作都是需要创建连接的,那么
2.将登录后的信息保存起来,之后每次进行JDBC操作时都获取一次登录信息
那么用什么方式保存呢?变量?文件?如果我们想把这个功能进行扩充,输入的不仅是用户名和密码,也包括连接url、sid和其他信息怎么办?似乎可以书写一个文件。
3.读取登录信息即加载文件信息
提到加载文件信息怎么做?I/O流?…io操作又得一大堆代码,一提到这个就心累。Java中有没有更加便捷的方法呢?
有!>>>>>>ResourceBundle类
Java提供了这样一个工具类,可以用于书写和导入配置文件,下边仅给出简单示例:
1.书写一个简单配置文件test.properties。注意文件的后缀名,并将其放在src/目录下
test.properties
NAME=apple
AGE=18
HAIR=yellow
嗯…这是一个有着黄色头发的18岁apple同学。
2.书写配置器测试文件
package test;
import java.util.ResourceBundle;
public class ResourceBundleTest
{
public static void main(String[] args)
{
//1.定义字符串变量
String name = null;
String age = null;
String hair = null;
//2.创建资源适配器,并匹配配置文件
ResourceBundle bundle = ResourceBundle.getBundle("test");
//3.填充变量
name = bundle.getString("NAME");
age = bundle.getString("AGE");
hair = bundle.getString("HAIR");
//4.输出测试结果
System.out.println(name);
System.out.println(age);
System.out.println(hair);
}
}
可以得到输出结果
apple
18
yellow
既然有了ResourceBundle这种好玩意,那么就修改我们的连接方式吧!
1.书写DBUtils.java的配置文件DBOptions.properties,并将其放入src/目录下
DBOptions.properties
URL=jdbc:oracle:thin:@localhost:1521:orcl
USERNAME=admin
PASSWORD=admin1234
2.修改连接方式
思考:
1.既然每一次操作都需要加载相同的用户名和密码,那么我们可以定义全局变量,这样之后每次调用都不需要再重新开辟内存可以节约空间
2.获取用户名密码的连接操作肯定是所有操作中第一件要做的事,而每个操作都需要调用连接方法。那么它不应该放在连接方法内,而应该独立出来,在这里我采用了静态块的方法
DBUtils.java内部
/*********************************************************
* 以下为连接方法
*********************************************************/
//1.定义连接需要的数据变量
private static String url = null;
private static String username = null;
private static String password = null;
//2.通过静态块解析资源文件,为属性(username,password)赋值
static
{
//2.1.获取关联目标资源文件的,解析器对象
ResourceBundle bundle=ResourceBundle.getBundle("DBOptions");
//2.2.从资源文件获取数据,填充变量
url=bundle.getString("URL");
username=bundle.getString("USERNAME");
password=bundle.getString("PASSWORD");
}
//3.获取数据库连接
public static Connection getConnection()throws Exception
{
//3.1.通过驱动管理器匹配url,创建连接
Connection conn = DriverManager.getConnection(url, username, password);
//3.2.带出连接对象
return conn;
}
OK!这样之后用户使用的时候,只需要提前在.properties文件中输入好自己的用户名和密码,便可以完成正常操作!
针对问题2,要给用户一个更直观的操作结果。那么直接告诉操作成功与否就可以了嘛!很简单,修改一下返回值和输出吧!下边贴出修改的代码不予过多解释大家仔细分析一下吧!
StudentServices.java
package com.whm.services;
import java.sql.Connection;
import java.sql.PreparedStatement;
import com.whm.seystem.db.DBUtils;
public class StudentServices
{
//添加学生
public boolean addStudent(Object...val)throws Exception
{
//1.定义JDBC变量s
Connection conn = null;
PreparedStatement pstm = null;
try
{
//2.创建连接
conn = DBUtils.getConnection();
//3.定义sql
StringBuilder sql = new StringBuilder()
.append("INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)")
.append(" VALUES(S_STU.NEXTVAL,?,TO_DATE(?,'YYYY-MM-DD'),?,?)");
//4.预编译sql
pstm = conn.prepareStatement(sql.toString());
//5.参数赋值
int index = 1;
for(Object param:val)
{
pstm.setObject(index++, param);
}
//6.执行sql
return pstm.executeUpdate()>0;
}
finally//在此处销毁资源
{
DBUtils.close(pstm);
DBUtils.close(conn);
}
}
}
StudentServicesTest.java
package test;
import com.whm.services.StudentServices;
public class StudentServicesTest
{
public static void main(String[] args)
{
try
{
StudentServicesTest.addStudentTest();
}
catch(Exception e)
{
e.printStackTrace();
}
}
//测试添加学生
public static void addStudentTest()throws Exception
{
StudentServices services = new StudentServices();
/**
* 创建一个Object数组,用于提供我们想要传递的值
* 带上sql语句用于参照对应:
* INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)
*/
Object val[] = {"葫芦娃","1900-9-9","0","那时还没考试"};
//将值传入方法
String msg = services.addStudent(val)?"添加成功!":"添加失败!";
System.out.println(msg);
}
}
至此,我们把连接的配置也优化好啦!看上去似乎已经很好了,但实际还存在一些问题(这个我们之后再说)。
数据库基本操作“增删改查”,我们还差查询没有实现,先把这个实现了吧!