封装数据访问对象
1:通过分析总结,所有对数据库表的操作都可以总结为通过JDBC对表的增删改查,为了减少冗余代码,
使得每次操作表时,不必都写JDBC程序,所以将对一张表的所有数据访功能,封装在数据访问对象
(Data Access Object)中,方便调用。
2:为了方便数据传输,往往会将java程序中所有相关操作的零散字段值,封装成一个实体对象--entity。
实体封装原则:
表----实体类
字段---属性
实现序列化
提供set,get方法。
以下代码就是利用Dao数据访问对象写出的JDBC程序,利用封装简化了JDBC开发步骤。
试想一下,如果,有10个添加,20个删除的请求,还像JDBC1.0,2.0版本那样写的话,要写10遍,20遍大量相似代码,
基本一致的代码。这不仅耗时耗力,也不符合JAVA三大特性。所以,利用Dao数据访问层,将对表的常用操作,
封装成方法,这样再有10个添加或20个删除,我们只需要调用10次,20次这个封装好的添加或删除方法,
而不用再写那么多遍方法,大大简化了开发工作量。
以下是利用Dao思想实现的JDBC3.0是3.0版本后面还有更好的版本娓娓道来!>_<
JDBC_Dao.java
public class JDBC_Dao {
/**
* 向account表增加一条记录
*/
public void add(Account account){
Connection conn = null;
PreparedStatement pstm = null;
try {
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2创建连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
//3准备sql
String sql = "insert into account values(?,?,?,?)";
//4创建Statement,发送sql
pstm = conn.prepareStatement(sql);
pstm.setString(1,account.getCardId());
pstm.setString(2, account.getPassword());
pstm.setDouble(3, account.getBalance());
pstm.setString(4, account.getPhone());
int i = pstm.executeUpdate();
//5如果是查询的话,处理结果集
} catch (Exception e) {
e.printStackTrace();
}
finally{
//6释放资源
try {
pstm.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 向account表查询一条记录
* @param account
* @return
*/
public Account query(Account account){
Connection conn = null;
PreparedStatement pstm =null;
ResultSet rs = null;
try {
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2创建连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
//3准备sql
String sql = "select * from account where "
+ "card_id = ? and password = ?";
//4创建Statement发送语句
pstm = conn.prepareStatement(sql);
pstm.setString(1, account.getCardId());
pstm.setString(2, account.getPassword());
rs = pstm.executeQuery();
//5处理结果集
while (rs.next()) {
account.setCardId(rs.getString("card_id"));
account.setPassword(rs.getString("password"));
account.setBalance(rs.getDouble("balance"));
account.setPhone(rs.getString("phone"));
}
} catch (Exception e) {
e.getStackTrace();
}
finally{
//6释放资源
try {
rs.close();
pstm.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return account;
}
}
以上代码依旧使用account表,需要再写一个实体对象用来承载数据,一个test类用来调用方法,
,这些最基础的,这里就不赘述了,不清楚的同学就要自行参阅java语言了。
如果我查询A卡,B卡,C卡,三张银行卡信息,按照JDBC2.0要写三个查询方法,现在,只需要把参数传递过去,
调用三次query()方法就好了!
总结:可见利用Dao数据访问层封装JDBC常用方法,可以大大简化方法步骤,不用重复写方法,只需重复调用。
这就是JDBC3.0版本
=============================华丽丽的分割线================
但是仔细的读者一定发现了,这里还存在不少缺陷,没错,我们还可以改进它。
在JDBC3.0版本里,可以发现,查询,添加方法,存在大量冗余代码,比如:
①同的加载驱动, ②相同的创建连接,③相同的释放资源。
在上个版本的代码里我只写了添加查询方法,如果还有删除,修改,查询所有等方法呢,
没错这些方法,也存在相同的创建连接,释放链接。找见了问题,就好解决了。
那么解决的办法还是----封装。
我们可以尝试把1注册驱动,2创建连接,6释放资源,这三个步骤做成工具类-----JDBCutil
这样,我们在Dao层里面的JDBC方法,在遇到1,2,6等步骤时,不用再去写代码,只需调用封装好的工具即可。
没错程序员都是很懒得!
以下是JDBC4.0是4.0版本,后面还有更完善的版本娓娓道来!
public class JDBC_Util {
/**
* @return 返回链接
*/
public static Connection getConnection() throws Exception {
Connection conn = null;
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
return conn;
}
/**
* 释放资源
*/
public static void release(ResultSet rs,
Statement stm,
Connection conn){
try {
if(rs!=null){rs.close();}
if(stm!=null){stm.close();}
if(conn!=null){conn.close();}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class JDBC_Dao2 {
/**
* 向account表增加一条记录
*/
public void add(Account account){
Connection conn = null;
PreparedStatement pstm = null;
try {
conn = JDBC_Util.getConnection();
//3准备sql
String sql = "insert into account values(?,?,?,?)";
//4创建Statement,发送sql
pstm = conn.prepareStatement(sql);
pstm.setString(1,account.getCardId());
pstm.setString(2, account.getPassword());
pstm.setDouble(3, account.getBalance());
pstm.setString(4, account.getPhone());
int i = pstm.executeUpdate();
//5如果是查询的话,处理结果集
} catch (Exception e) {
e.printStackTrace();
}
finally{
//6释放资源
JDBC_Util.release(null, pstm, conn);
}
}
/**
* 向account表查询一条记录
* @param account
* @return
*/
public Account query(Account account){
Connection conn = null;
PreparedStatement pstm =null;
ResultSet rs = null;
try {
conn = JDBC_Util.getConnection();
//3准备sql
String sql = "select * from account where " + "card_id = ? and password = ?";
//4创建Statement发送语句
pstm = conn.prepareStatement(sql);
pstm.setString(1, account.getCardId());
pstm.setString(2, account.getPassword());
rs = pstm.executeQuery();
//5处理结果集
while (rs.next()) {
account.setCardId(rs.getString("card_id"));
account.setPassword(rs.getString("password"));
account.setBalance(rs.getDouble("balance"));
account.setPhone(rs.getString("phone"));
}
} catch (Exception e) {
e.getStackTrace();
}
finally{
//6释放资源
JDBC_Util.release(rs, pstm, conn);
}
return account;
}
}
细心地读者会发现在代码里原本创建连接和释放资源的位置都变成了方法调用。
conn = JDBC_Util.getConnection();
JDBC_Util.release(rs, pstm, conn);
4.0版本通过工具类调用的方式进一步精简了代码,那么4.0版本还有没有缺陷了呢。
=======================华丽丽的分割线============================
对于JDBC_Util.java来说,还有许多不足。
1:
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
比如创建连接的方式,是在代码里写死的用户名和密码,以及连接url,而java文件运行的时候,会编译成class文件
也就是说,JDBC_Util最终会是JDBC_Util.class文件,那么一旦数据库改变密码,用户名,或改换数据库,
整个文件还需要重新编译执行。对此,我们可以把经常变动的代码放到properties配置文件里去。
2:每次调用获得连接的方法都需要加载驱动,
Class.forName("com.mysql.jdbc.Driver");
调用10次则加载10次,大大浪费了JVM内存,其实对于加载驱动只需要加载一次,我们可以尝试把加载驱动放到
静态代码块里。静态代码块在类加载时执行,只执行一次。
properties配置文件简介及使用:
1: InputStream is = new FileInputStream("配置文件路径");
BufferedReader br = bew BufferedReader(new InputStramReader(is));
String as = br.readLine();
2:properties 是Map的实现类:
1:获得配置文件的输出流。
2:调用load(is);加载配置文件里的信息至Properties对象中。
下面的JDBC5.0版本是对JDBC_Util的改进。采用了静态代码块加读取配置文件的优化方案。
包括test.java,JDBC_Util2.java,JDBC_Dao2.java,properties文件,共四个。
JDBC_Uril2.java
public class JDBC_Util2 {
private static final Properties prop = new Properties();
static{
InputStream is = null;
try {
is = JDBC_Util2.class.getResourceAsStream("jdbc.properties");
prop.load(is);
String driverName = prop.getProperty("driverName");
Class.forName(driverName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @return 返回链接
*/
public static Connection getConnection() throws Exception {
Connection conn = null;
String user = prop.getProperty("user");
String password = prop.getProperty("password");
String url = prop.getProperty("url");
conn = DriverManager.getConnection(url,user,password);
return conn;
}
/**
* 释放资源
*/
public static void release(ResultSet rs,
Statement stm,
Connection conn){
try {
if(rs!=null){rs.close();}
if(stm!=null){stm.close();}
if(conn!=null){conn.close();}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JDBC_Dao2.java
public class JDBC_Dao2 {
/**
* 向account表增加一条记录
*/
public void add(Account account){
Connection conn = null;
PreparedStatement pstm = null;
try {
conn = JDBC_Util2.getConnection();
//3准备sql
String sql = "insert into account values(?,?,?,?)";
//4创建Statement,发送sql
pstm = conn.prepareStatement(sql);
pstm.setString(1,account.getCardId());
pstm.setString(2, account.getPassword());
pstm.setDouble(3, account.getBalance());
pstm.setString(4, account.getPhone());
int i = pstm.executeUpdate();
//5如果是查询的话,处理结果集
} catch (Exception e) {
e.printStackTrace();
}
finally{
//6释放资源
JDBC_Util2.release(null, pstm, conn);
}
}
/**
* 向account表查询一条记录
* @param account
* @return
*/
public Account query(Account account){
Connection conn = null;
PreparedStatement pstm =null;
ResultSet rs = null;
try {
conn = JDBC_Util2.getConnection();
//3准备sql
String sql = "select * from account where "
+ "card_id = ? and password = ?";
//4创建Statement发送语句
pstm = conn.prepareStatement(sql);
pstm.setString(1, account.getCardId());
pstm.setString(2, account.getPassword());
rs = pstm.executeQuery();
//5处理结果集
while (rs.next()) {
account.setCardId(rs.getString("card_id"));
account.setPassword(rs.getString("password"));
account.setBalance(rs.getDouble("balance"));
account.setPhone(rs.getString("phone"));
}
} catch (Exception e) {
e.getStackTrace();
}
finally{
//6释放资源
JDBC_Util2.release(rs, pstm, conn);
}
return account;
}
}
jdbc.properties文件
driverName=com.mysql.jdbc.Driver
user=root
password=root
url=jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC
Test_Dao.java
public class Test_Dao {
public static void main(String[] args) {
JDBC_Dao2 jd = new JDBC_Dao2();
Account account = new Account("10004","44444",99,"12345678900");
jd.add(account);
}
}
解决了依赖注入,冗余代码,资源浪费等问题之后,JDBC5.0完毕。这个版本可以算得上是较为完善的版本了,但是还有瑕疵。
后面关于JDBC的问题涉及到事务,以及MVC模式,这里由于篇幅问题,无法细细详谈,但我会竟可能详细的写。
请小伙伴自行阅读有关oracle事务一章节,还有有关mvc编程思想书籍。
============================华丽丽的分割线======================
由于篇幅原因,后续部分请大家阅读由浅到深学习JDBC三
不妥之处恳请读者批评指正,共同进步。>_<
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。